xfsprogs-4.9.0+nmu1ubuntu2/0000755000000000000000000000000013136024635012471 5ustar xfsprogs-4.9.0+nmu1ubuntu2/.gitcensus0000644000000000000000000001610213063067167014504 0ustar .gitignore Makefile README VERSION configure.ac copy/Makefile copy/xfs_copy.c copy/xfs_copy.h db/Makefile db/addr.c db/addr.h db/agf.c db/agf.h db/agfl.c db/agfl.h db/agi.c db/agi.h db/attr.c db/attr.h db/attrset.c db/attrset.h db/attrshort.c db/attrshort.h db/bit.c db/bit.h db/block.c db/block.h db/bmap.c db/bmap.h db/bmroot.c db/bmroot.h db/btblock.c db/btblock.h db/check.c db/check.h db/command.c db/command.h db/convert.c db/convert.h db/crc.c db/crc.h db/debug.c db/debug.h db/dir2.c db/dir2.h db/dir2sf.c db/dir2sf.h db/dquot.c db/dquot.h db/echo.c db/echo.h db/faddr.c db/faddr.h db/field.c db/field.h db/flist.c db/flist.h db/fprint.c db/fprint.h db/frag.c db/frag.h db/freesp.c db/freesp.h db/fsmap.c db/fsmap.h db/hash.c db/hash.h db/help.c db/help.h db/init.c db/init.h db/inode.c db/inode.h db/input.c db/input.h db/io.c db/io.h db/logformat.c db/logformat.h db/malloc.c db/malloc.h db/metadump.c db/metadump.h db/output.c db/output.h db/print.c db/print.h db/quit.c db/quit.h db/sb.c db/sb.h db/sig.c db/sig.h db/strvec.c db/strvec.h db/symlink.c db/symlink.h db/text.c db/text.h db/type.c db/type.h db/write.c db/write.h db/xfs_admin.sh db/xfs_metadump.sh db/xfs_ncheck.sh debian/Makefile debian/changelog debian/compat debian/control debian/copyright debian/postinst debian/rules debian/watch doc/CHANGES doc/COPYING doc/CREDITS doc/INSTALL doc/Makefile doc/sparse.txt estimate/Makefile estimate/xfs_estimate.c fs/xfs/xfs_rmap_item.c fs/xfs/xfs_rmap_item.h fsck/Makefile fsck/xfs_fsck.sh fsr/Makefile fsr/xfs_fsr.c growfs/Makefile growfs/xfs_growfs.c growfs/xfs_info.sh include/Makefile include/atomic.h include/bitops.h include/builddefs.in include/buildmacros include/buildrules include/cache.h include/command.h include/darwin.h include/freebsd.h include/gnukfreebsd.h include/handle.h include/hlist.h include/input.h include/install-sh include/irix.h include/jdm.h include/kmem.h include/libxcmd.h include/libxfs.h include/libxlog.h include/linux.h include/list.h include/parent.h include/path.h include/platform_defs.h.in include/project.h include/radix-tree.h include/xfs.h include/xfs_arch.h include/xfs_btree_trace.h include/xfs_inode.h include/xfs_log_recover.h include/xfs_metadump.h include/xfs_mount.h include/xfs_multidisk.h include/xfs_trace.h include/xfs_trans.h include/xqm.h io/Makefile io/attr.c io/bmap.c io/copy_file_range.c io/cowextsize.c io/fadvise.c io/fiemap.c io/file.c io/freeze.c io/fsync.c io/getrusage.c io/imap.c io/init.c io/init.h io/inject.c io/io.h io/link.c io/madvise.c io/mincore.c io/mmap.c io/open.c io/parent.c io/pread.c io/prealloc.c io/pwrite.c io/readdir.c io/reflink.c io/resblks.c io/seek.c io/sendfile.c io/shutdown.c io/sync.c io/sync_file_range.c io/truncate.c io/xfs_bmap.sh io/xfs_freeze.sh io/xfs_mkfile.sh libhandle/Makefile libhandle/handle.c libhandle/jdm.c libhandle/libhandle.sym libxcmd/Makefile libxcmd/command.c libxcmd/help.c libxcmd/input.c libxcmd/paths.c libxcmd/projects.c libxcmd/quit.c libxcmd/topology.c libxfs/Makefile libxfs/cache.c libxfs/crc32.c libxfs/crc32defs.h libxfs/darwin.c libxfs/defer_item.c libxfs/freebsd.c libxfs/gen_crc32table.c libxfs/init.c libxfs/init.h libxfs/irix.c libxfs/kmem.c libxfs/libxfs_api_defs.h libxfs/libxfs_io.h libxfs/libxfs_priv.h libxfs/linux.c libxfs/list_sort.c libxfs/logitem.c libxfs/radix-tree.c libxfs/rdwr.c libxfs/trans.c libxfs/util.c libxfs/xfs_ag_resv.c libxfs/xfs_ag_resv.h libxfs/xfs_alloc.c libxfs/xfs_alloc.h libxfs/xfs_alloc_btree.c libxfs/xfs_alloc_btree.h libxfs/xfs_attr.c libxfs/xfs_attr_leaf.c libxfs/xfs_attr_leaf.h libxfs/xfs_attr_remote.c libxfs/xfs_attr_remote.h libxfs/xfs_attr_sf.h libxfs/xfs_bit.c libxfs/xfs_bit.h libxfs/xfs_bmap.c libxfs/xfs_bmap.h libxfs/xfs_bmap_btree.c libxfs/xfs_bmap_btree.h libxfs/xfs_btree.c libxfs/xfs_btree.h libxfs/xfs_cksum.h libxfs/xfs_da_btree.c libxfs/xfs_da_btree.h libxfs/xfs_da_format.c libxfs/xfs_da_format.h libxfs/xfs_defer.c libxfs/xfs_defer.h libxfs/xfs_dir2.c libxfs/xfs_dir2.h libxfs/xfs_dir2_block.c libxfs/xfs_dir2_data.c libxfs/xfs_dir2_leaf.c libxfs/xfs_dir2_node.c libxfs/xfs_dir2_priv.h libxfs/xfs_dir2_sf.c libxfs/xfs_dquot_buf.c libxfs/xfs_format.h libxfs/xfs_fs.h libxfs/xfs_ialloc.c libxfs/xfs_ialloc.h libxfs/xfs_ialloc_btree.c libxfs/xfs_ialloc_btree.h libxfs/xfs_inode_buf.c libxfs/xfs_inode_buf.h libxfs/xfs_inode_fork.c libxfs/xfs_inode_fork.h libxfs/xfs_log_format.h libxfs/xfs_log_rlimit.c libxfs/xfs_quota_defs.h libxfs/xfs_refcount.c libxfs/xfs_refcount.h libxfs/xfs_refcount_btree.c libxfs/xfs_refcount_btree.h libxfs/xfs_rmap.c libxfs/xfs_rmap.h libxfs/xfs_rmap_btree.c libxfs/xfs_rmap_btree.h libxfs/xfs_rtbitmap.c libxfs/xfs_sb.c libxfs/xfs_sb.h libxfs/xfs_shared.h libxfs/xfs_symlink_remote.c libxfs/xfs_trans_resv.c libxfs/xfs_trans_resv.h libxfs/xfs_trans_space.h libxfs/xfs_types.h libxlog/Makefile libxlog/util.c libxlog/xfs_log_recover.c logprint/Makefile logprint/log_copy.c logprint/log_dump.c logprint/log_misc.c logprint/log_print_all.c logprint/log_print_trans.c logprint/log_redo.c logprint/logprint.c logprint/logprint.h m4/Makefile m4/manual_format.m4 m4/multilib.m4 m4/package_aiodev.m4 m4/package_blkid.m4 m4/package_globals.m4 m4/package_libcdev.m4 m4/package_pthread.m4 m4/package_rt.m4 m4/package_types.m4 m4/package_utilies.m4 m4/package_uuiddev.m4 man/Makefile man/man3/Makefile man/man3/handle.3 man/man3/xfsctl.3 man/man5/Makefile man/man5/projects.5 man/man5/projid.5 man/man5/xfs.5 man/man8/Makefile man/man8/fsck.xfs.8 man/man8/mkfs.xfs.8 man/man8/xfs_admin.8 man/man8/xfs_bmap.8 man/man8/xfs_copy.8 man/man8/xfs_db.8 man/man8/xfs_estimate.8 man/man8/xfs_freeze.8 man/man8/xfs_fsr.8 man/man8/xfs_growfs.8 man/man8/xfs_io.8 man/man8/xfs_logprint.8 man/man8/xfs_mdrestore.8 man/man8/xfs_metadump.8 man/man8/xfs_mkfile.8 man/man8/xfs_ncheck.8 man/man8/xfs_quota.8 man/man8/xfs_repair.8 man/man8/xfs_rtcp.8 mdrestore/Makefile mdrestore/xfs_mdrestore.c mkfs/Makefile mkfs/maxtrres.c mkfs/proto.c mkfs/xfs_mkfs.c po/Makefile po/de.po po/pl.po quota/Makefile quota/darwin.c quota/edit.c quota/free.c quota/freebsd.c quota/init.c quota/init.h quota/irix.c quota/linux.c quota/path.c quota/project.c quota/quot.c quota/quota.c quota/quota.h quota/report.c quota/state.c quota/util.c release.sh repair/Makefile repair/README repair/agheader.c repair/agheader.h repair/attr_repair.c repair/attr_repair.h repair/avl.c repair/avl.h repair/avl64.c repair/avl64.h repair/bmap.c repair/bmap.h repair/btree.c repair/btree.h repair/da_util.c repair/da_util.h repair/dino_chunks.c repair/dinode.c repair/dinode.h repair/dir2.c repair/dir2.h repair/err_protos.h repair/globals.c repair/globals.h repair/incore.c repair/incore.h repair/incore_bmc.c repair/incore_ext.c repair/incore_ino.c repair/init.c repair/phase1.c repair/phase2.c repair/phase3.c repair/phase4.c repair/phase5.c repair/phase6.c repair/phase7.c repair/prefetch.c repair/prefetch.h repair/progress.c repair/progress.h repair/protos.h repair/rmap.c repair/rmap.h repair/rt.c repair/rt.h repair/sb.c repair/scan.c repair/scan.h repair/slab.c repair/slab.h repair/threads.c repair/threads.h repair/versions.c repair/versions.h repair/xfs_repair.c rtcp/Makefile rtcp/xfs_rtcp.c tools/find-api-violations.sh tools/libxfs-apply tools/xfsbuflock.py xfsprogs-4.9.0+nmu1ubuntu2/.gitignore0000644000000000000000000000162713063067167014475 0ustar # object files *.o .dep .ltdep # build system .census .gitcensus /include/platform_defs.h /include/builddefs /install-sh # magic directory symlinks /include/disk /include/xfs # packaging /doc/CHANGES.gz /xfsprogs-* /xfsprogs_* /xfslibs-dev_* # autoconf generated files /aclocal.m4 /m4/libtool.m4 /m4/ltoptions.m4 /m4/ltsugar.m4 /m4/ltversion.m4 /m4/lt~obsolete.m4 /autom4te.cache/ /config.guess /config.log /config.status /config.sub /configure # libtool /libtool /ltmain.sh *.lo *.la .libs # gettext /po/de.mo /po/pl.mo /po/xfsprogs.pot # cscope stuff cscope.* # quilt stuff /.pc/ /patches/ # binaries /copy/xfs_copy /db/xfs_db /estimate/xfs_estimate /fsr/xfs_fsr /growfs/xfs_growfs /io/xfs_io /logprint/xfs_logprint /mdrestore/xfs_mdrestore /mkfs/fstyp /mkfs/mkfs.xfs /quota/xfs_quota /repair/xfs_repair /rtcp/xfs_rtcp # generated crc files /libxfs/crc32selftest /libxfs/crc32table.h /libxfs/gen_crc32table xfsprogs-4.9.0+nmu1ubuntu2/LIST0000644000000000000000000000017312777446630013205 0ustar 2be9e93986840038d880e282ead1ac81eb269251 721948f7688e7d571f0275c7e95036f3d74eb2df 83f4b5ac15fa3d583493160924b5994ebc835377 xfsprogs-4.9.0+nmu1ubuntu2/Makefile0000644000000000000000000001056113063067167014142 0ustar # # Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. # ifeq ("$(origin V)", "command line") BUILD_VERBOSE = $(V) endif ifndef BUILD_VERBOSE BUILD_VERBOSE = 0 endif ifeq ($(BUILD_VERBOSE),1) Q = else Q = @ endif MAKEOPTS = --no-print-directory Q=$(Q) TOPDIR = . HAVE_BUILDDEFS = $(shell test -f $(TOPDIR)/include/builddefs && echo yes || echo no) ifeq ($(HAVE_BUILDDEFS), yes) include $(TOPDIR)/include/builddefs endif SRCDIR = $(PKG_NAME)-$(PKG_VERSION) SRCTAR = $(PKG_NAME)-$(PKG_VERSION).tar.gz CONFIGURE = aclocal.m4 configure config.guess config.sub install-sh ltmain.sh LSRCFILES = configure.ac release.sh README VERSION $(CONFIGURE) SRCTARINC = m4/libtool.m4 m4/lt~obsolete.m4 m4/ltoptions.m4 m4/ltsugar.m4 \ m4/ltversion.m4 po/xfsprogs.pot .gitcensus $(CONFIGURE) LDIRT = config.log .ltdep .dep config.status config.cache confdefs.h \ conftest* built .census install.* install-dev.* *.gz \ autom4te.cache/* libtool include/builddefs include/platform_defs.h ifeq ($(HAVE_BUILDDEFS), yes) LDIRDIRT = $(SRCDIR) LDIRT += $(SRCTAR) endif # header install rules to populate include/xfs correctly HDR_SUBDIRS = include libxfs DLIB_SUBDIRS = libxlog libxcmd libhandle LIB_SUBDIRS = libxfs $(DLIB_SUBDIRS) TOOL_SUBDIRS = copy db estimate fsck growfs io logprint mkfs quota \ mdrestore repair rtcp m4 man doc debian ifneq ("$(PKG_PLATFORM)","darwin") TOOL_SUBDIRS += fsr endif ifneq ("$(XGETTEXT)","") TOOL_SUBDIRS += po endif # If we are on OS X, use glibtoolize from MacPorts, as OS X doesn't have # libtoolize binary itself. LIBTOOLIZE_TEST=$(shell libtoolize --version >/dev/null 2>&1 && echo found) LIBTOOLIZE_BIN=libtoolize ifneq ("$(LIBTOOLIZE_TEST)","found") LIBTOOLIZE_BIN=glibtoolize endif # include is listed last so it is processed last in clean rules. SUBDIRS = $(LIB_SUBDIRS) $(TOOL_SUBDIRS) include default: include/builddefs include/platform_defs.h ifeq ($(HAVE_BUILDDEFS), no) $(Q)$(MAKE) $(MAKEOPTS) -C . $@ else $(Q)$(MAKE) $(MAKEOPTS) headers $(Q)$(MAKE) $(MAKEOPTS) $(SUBDIRS) endif # tool/lib dependencies # note: include/xfs is set up by libxfs, too, so everything is dependent on it. $(LIB_SUBDIRS) $(TOOL_SUBDIRS): include $(DLIB_SUBDIRS) $(TOOL_SUBDIRS): libxfs db logprint: libxlog fsr: libhandle growfs: libxcmd io: libxcmd libhandle quota: libxcmd repair: libxlog libxcmd copy: libxlog mkfs: libxcmd ifeq ($(HAVE_BUILDDEFS), yes) include $(BUILDRULES) else clean: # if configure hasn't run, nothing to clean endif # Recent versions of libtool require the -i option for copying auxiliary # files (config.sub, config.guess, install-sh, ltmain.sh), while older # versions will copy those files anyway, and don't understand -i. LIBTOOLIZE_INSTALL = `$(LIBTOOLIZE_BIN) -n -i >/dev/null 2>/dev/null && echo -i` configure: $(LIBTOOLIZE_BIN) -c $(LIBTOOLIZE_INSTALL) -f cp include/install-sh . aclocal -I m4 autoconf include/builddefs: configure ./configure $$LOCAL_CONFIGURE_OPTIONS include/platform_defs.h: include/builddefs ## Recover from the removal of $@ @if test -f $@; then :; else \ rm -f include/builddefs; \ $(MAKE) $(MAKEOPTS) $(AM_MAKEFLAGS) include/builddefs; \ fi install: $(addsuffix -install,$(SUBDIRS)) $(INSTALL) -m 755 -d $(PKG_DOC_DIR) $(INSTALL) -m 644 README $(PKG_DOC_DIR) install-dev: $(addsuffix -install-dev,$(SUBDIRS)) %-install: @echo "Installing $@" $(Q)$(MAKE) $(MAKEOPTS) -C $* install %-install-dev: @echo "Installing $@" $(Q)$(MAKE) $(MAKEOPTS) -C $* install-dev distclean: clean $(Q)rm -f $(LDIRT) realclean: distclean $(Q)rm -f $(CONFIGURE) .gitcensus # # All this gunk is to allow for a make dist on an unconfigured tree # dist: include/builddefs include/platform_defs.h default ifeq ($(HAVE_BUILDDEFS), no) $(Q)$(MAKE) $(MAKEOPTS) -C . $@ else $(Q)$(MAKE) $(MAKEOPTS) $(SRCTAR) endif deb: include/builddefs include/platform_defs.h ifeq ($(HAVE_BUILDDEFS), no) $(Q)$(MAKE) $(MAKEOPTS) -C . $@ else # need to build translations before the source tarball $(Q)$(MAKE) $(MAKEOPTS) -C po $(Q)$(MAKE) $(MAKEOPTS) $(SRCDIR) $(Q)cd $(SRCDIR) && dpkg-buildpackage endif $(SRCDIR) : $(_FORCE) $(SRCTAR) rm -fr $@ $(Q)$(TAR) -zxvf $(SRCTAR) $(SRCTAR) : default $(SRCTARINC) .gitcensus $(Q)$(TAR) --transform "s,^,$(SRCDIR)/," -zcf $(SRCDIR).tar.gz \ `cat .gitcensus` $(SRCTARINC) echo Wrote: $@ .gitcensus: $(_FORCE) $(Q)if test -d .git; then \ git ls-files > .gitcensus && echo "new .gitcensus"; \ fi xfsprogs-4.9.0+nmu1ubuntu2/README0000644000000000000000000000053513063067167013362 0ustar XFS User Tools README _____________________ See the file doc/INSTALL for build, installation and post- install configuration steps. Refer to the xfs(5) manual page for general XFS information and references to other XFS manual pages. For more information and details on how to contribute to the XFS project see the web pages at: http://xfs.org/ xfsprogs-4.9.0+nmu1ubuntu2/VERSION0000644000000000000000000000016313063067167013547 0ustar # # This file is used by configure to get version information # PKG_MAJOR=4 PKG_MINOR=9 PKG_REVISION=0 PKG_BUILD=1 xfsprogs-4.9.0+nmu1ubuntu2/aclocal.m40000644000000000000000000000220213063067167014333 0ustar # generated automatically by aclocal 1.15 -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/manual_format.m4]) m4_include([m4/multilib.m4]) m4_include([m4/package_blkid.m4]) m4_include([m4/package_globals.m4]) m4_include([m4/package_libcdev.m4]) m4_include([m4/package_pthread.m4]) m4_include([m4/package_rt.m4]) m4_include([m4/package_types.m4]) m4_include([m4/package_utilies.m4]) m4_include([m4/package_uuiddev.m4]) xfsprogs-4.9.0+nmu1ubuntu2/config.guess0000755000000000000000000012564413063067167015033 0ustar #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-10-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || \ echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; mips64el:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac cat >&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: xfsprogs-4.9.0+nmu1ubuntu2/config.sub0000755000000000000000000010676313063067167014477 0ustar #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-11-04' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: xfsprogs-4.9.0+nmu1ubuntu2/configure0000755000000000000000000167411013063067167014420 0ustar #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for xfsprogs 4.9.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: linux-xfs@vger.kernel.org about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='xfsprogs' PACKAGE_TARNAME='xfsprogs' PACKAGE_VERSION='4.9.0' PACKAGE_STRING='xfsprogs 4.9.0' PACKAGE_BUGREPORT='linux-xfs@vger.kernel.org' PACKAGE_URL='' ac_unique_file="include/libxfs.h" ac_default_prefix=/usr # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS have_zipped_manpages libblkid need_internal_fsxattr have_mremap have_fsetxattr have_readdir have_fls have_mntent have_sync_file_range have_copy_file_range have_preadv have_fiemap have_fallocate have_getmntinfo have_getmntent have_sendfile have_mincore have_madvise have_fadvise libpthread libuuid librt libdirsuffix rpmbuild RPMBUILD rpm_version rpm RPM xgettext XGETTEXT msgmerge MSGMERGE msgfmt MSGFMT sort SORT echo ECHO sed awk makedepend zip ZIP tar TAR make MAKE cc pkg_platform pkg_distribution pkg_group pkg_user malloc_lib opt_build debug_build pkg_release pkg_version pkg_name LOCALIZED_FILES root_libdir root_sbindir enable_librt enable_lib64 libtermcap enable_editline libeditline enable_readline libreadline enable_blkid enable_gettext enable_shared BUILD_CC CPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL AWK RANLIB STRIP ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock enable_gettext enable_blkid enable_readline enable_editline enable_termcap enable_lib64 enable_librt ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS LT_SYS_LIBRARY_PATH CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures xfsprogs 4.9.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/xfsprogs] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of xfsprogs 4.9.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-shared=yes/no Enable use of shared libraries default=yes --enable-gettext=yes/no Enable alternate language support default=yes --enable-blkid=yes/no Enable use of block device id library default=yes --enable-readline=yes/no Enable readline command editing default=no --enable-editline=yes/no Enable editline command editing default=no --enable-termcap=yes/no Enable terminal capabilities library default=no --enable-lib64=yes/no Enable lib64 support default=yes --enable-librt=yes/no Enable librt support default=yes Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory LT_SYS_LIBRARY_PATH User-defined run-time library search path. CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF xfsprogs configure 4.9.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ---------------------------------------- ## ## Report this to linux-xfs@vger.kernel.org ## ## ---------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by xfsprogs $as_me 4.9.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in . "$srcdir"/.; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. ac_config_headers="$ac_config_headers include/platform_defs.h" case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC ac_config_commands="$ac_config_commands libtool" # Only expand once: ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $cross_compiling = no; then BUILD_CC="$CC" else for ac_prog in gcc cc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_BUILD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$BUILD_CC"; then ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_BUILD_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi BUILD_CC=$ac_cv_prog_BUILD_CC if test -n "$BUILD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 $as_echo "$BUILD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$BUILD_CC" && break done fi # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; else enable_shared=yes fi # Check whether --enable-gettext was given. if test "${enable_gettext+set}" = set; then : enableval=$enable_gettext; else enable_gettext=yes fi # Check whether --enable-blkid was given. if test "${enable_blkid+set}" = set; then : enableval=$enable_blkid; else enable_blkid=yes fi # Check whether --enable-readline was given. if test "${enable_readline+set}" = set; then : enableval=$enable_readline; test $enable_readline = yes && libreadline="-lreadline" else enable_readline=no fi # Check whether --enable-editline was given. if test "${enable_editline+set}" = set; then : enableval=$enable_editline; test $enable_editline = yes && libeditline="-ledit" else enable_editline=no fi # Check whether --enable-termcap was given. if test "${enable_termcap+set}" = set; then : enableval=$enable_termcap; test $enable_termcap = yes && libtermcap="-ltermcap" fi # Check whether --enable-lib64 was given. if test "${enable_lib64+set}" = set; then : enableval=$enable_lib64; else enable_lib64=yes fi # Check whether --enable-librt was given. if test "${enable_librt+set}" = set; then : enableval=$enable_librt; else enable_librt=yes fi # # If the user specified a libdir ending in lib64 do not append another # 64 to the library names. # base_libdir=`basename "$libdir"` case $base_libdir in lib64) enable_lib64=no esac # # Some important tools should be installed into the root partitions. # # Check whether exec_prefix=/usr: and install them to /sbin in that # case. If the user choses a different prefix assume he just wants # a local install for testing and not a system install. # case $exec_prefix:$prefix in NONE:NONE | NONE:/usr | /usr:*) root_sbindir='/sbin' root_libdir="/${base_libdir}" ;; *) root_sbindir="${sbindir}" root_libdir="${libdir}" ;; esac # Find localized files. Don't descend into any "dot directories" # (like .git or .pc from quilt). Strangely, the "-print" argument # to "find" is required, to avoid including such directories in the # list. LOCALIZED_FILES="" for lfile in `find ${srcdir} -path './.??*' -prune -o -name '*.c' -type f -print || exit 1`; do LOCALIZED_FILES="$LOCALIZED_FILES \$(TOPDIR)/$lfile" done pkg_name="xfsprogs" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu . ./VERSION pkg_version=${PKG_MAJOR}.${PKG_MINOR}.${PKG_REVISION} pkg_release=$PKG_BUILD test -z "$BUILD_VERSION" || pkg_release="$BUILD_VERSION" DEBUG=${DEBUG:-'-DDEBUG'} debug_build="$DEBUG" OPTIMIZER=${OPTIMIZER:-'-g -O2'} opt_build="$OPTIMIZER" MALLOCLIB=${MALLOCLIB:-''} malloc_lib="$MALLOCLIB" pkg_user=`id -u -n` test -z "$INSTALL_USER" || pkg_user="$INSTALL_USER" pkg_group=`id -g -n` test -z "$INSTALL_GROUP" || pkg_group="$INSTALL_GROUP" pkg_distribution=`uname -s` test -z "$DISTRIBUTION" || pkg_distribution="$DISTRIBUTION" pkg_platform=`uname -s | tr 'A-Z' 'a-z' | tr -d / | sed -e 's/irix64/irix/'` test -z "$PLATFORM" || pkg_platform="$PLATFORM" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cc="$CC" if test -z ""$cc""; then echo echo FATAL ERROR: cc does not seem to be installed. echo xfsprogs cannot be built without a working C compiler installation. exit 1 fi if test -z "$MAKE"; then # Extract the first word of "gmake", so it can be a program name with args. set dummy gmake; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $MAKE in [\\/]* | ?:[\\/]*) ac_cv_path_MAKE="$MAKE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MAKE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MAKE=$ac_cv_path_MAKE if test -n "$MAKE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 $as_echo "$MAKE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$MAKE"; then # Extract the first word of "make", so it can be a program name with args. set dummy make; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $MAKE in [\\/]* | ?:[\\/]*) ac_cv_path_MAKE="$MAKE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MAKE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MAKE=$ac_cv_path_MAKE if test -n "$MAKE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 $as_echo "$MAKE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi make=$MAKE if test -z ""$make""; then echo echo FATAL ERROR: make does not seem to be installed. echo xfsprogs cannot be built without a working GNU make installation. exit 1 fi if test -z "$TAR"; then # Extract the first word of "tar", so it can be a program name with args. set dummy tar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_TAR+:} false; then : $as_echo_n "(cached) " >&6 else case $TAR in [\\/]* | ?:[\\/]*) ac_cv_path_TAR="$TAR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi TAR=$ac_cv_path_TAR if test -n "$TAR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TAR" >&5 $as_echo "$TAR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi tar=$TAR if test -z "$ZIP"; then # Extract the first word of "gzip", so it can be a program name with args. set dummy gzip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ZIP+:} false; then : $as_echo_n "(cached) " >&6 else case $ZIP in [\\/]* | ?:[\\/]*) ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ZIP=$ac_cv_path_ZIP if test -n "$ZIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP" >&5 $as_echo "$ZIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi zip=$ZIP { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc -MM is supported" >&5 $as_echo_n "checking whether gcc -MM is supported... " >&6; } if ${ac_cv_gcc_nodeps+:} false; then : $as_echo_n "(cached) " >&6 else cat > conftest.c < int main() { exit(0); } EOF ac_cv_gcc_nodeps=no if ${CC} -MM conftest.c >/dev/null 2>&1; then ac_cv_gcc_nodeps=yes fi rm -f conftest.c a.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gcc_nodeps" >&5 $as_echo "$ac_cv_gcc_nodeps" >&6; } makedepend="$cc -MM" if test $ac_cv_gcc_nodeps = no; then makedepend=/bin/true fi if test -z "$AWK"; then # Extract the first word of "awk", so it can be a program name with args. set dummy awk; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_AWK+:} false; then : $as_echo_n "(cached) " >&6 else case $AWK in [\\/]* | ?:[\\/]*) ac_cv_path_AWK="$AWK" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_AWK="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi AWK=$ac_cv_path_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi awk=$AWK if test -z "$SED"; then # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else case $SED in [\\/]* | ?:[\\/]*) ac_cv_path_SED="$SED" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi SED=$ac_cv_path_SED if test -n "$SED"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 $as_echo "$SED" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi sed=$SED if test -z "$ECHO"; then # Extract the first word of "echo", so it can be a program name with args. set dummy echo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ECHO+:} false; then : $as_echo_n "(cached) " >&6 else case $ECHO in [\\/]* | ?:[\\/]*) ac_cv_path_ECHO="$ECHO" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ECHO="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ECHO=$ac_cv_path_ECHO if test -n "$ECHO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECHO" >&5 $as_echo "$ECHO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi echo=$ECHO if test -z "$SORT"; then # Extract the first word of "sort", so it can be a program name with args. set dummy sort; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SORT+:} false; then : $as_echo_n "(cached) " >&6 else case $SORT in [\\/]* | ?:[\\/]*) ac_cv_path_SORT="$SORT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SORT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi SORT=$ac_cv_path_SORT if test -n "$SORT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SORT" >&5 $as_echo "$SORT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi sort=$SORT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi if test "$enable_gettext" = yes; then if test -z "$MSGFMT"; then # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $MSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MSGFMT=$ac_cv_path_MSGFMT if test -n "$MSGFMT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 $as_echo "$MSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi msgfmt=$MSGFMT if test -z ""$msgfmt""; then echo echo FATAL ERROR: msgfmt does not seem to be installed. echo xfsprogs cannot be built without a working gettext installation. exit 1 fi if test -z "$MSGMERGE"; then # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGMERGE+:} false; then : $as_echo_n "(cached) " >&6 else case $MSGMERGE in [\\/]* | ?:[\\/]*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MSGMERGE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MSGMERGE=$ac_cv_path_MSGMERGE if test -n "$MSGMERGE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 $as_echo "$MSGMERGE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi msgmerge=$MSGMERGE if test -z ""$msgmerge""; then echo echo FATAL ERROR: msgmerge does not seem to be installed. echo xfsprogs cannot be built without a working gettext installation. exit 1 fi if test -z "$XGETTEXT"; then # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_XGETTEXT+:} false; then : $as_echo_n "(cached) " >&6 else case $XGETTEXT in [\\/]* | ?:[\\/]*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_XGETTEXT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi XGETTEXT=$ac_cv_path_XGETTEXT if test -n "$XGETTEXT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 $as_echo "$XGETTEXT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi xgettext=$XGETTEXT if test -z ""$xgettext""; then echo echo FATAL ERROR: xgettext does not seem to be installed. echo xfsprogs cannot be built without a working gettext installation. exit 1 fi fi if test -z "$RPM"; then # Extract the first word of "rpm", so it can be a program name with args. set dummy rpm; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_RPM+:} false; then : $as_echo_n "(cached) " >&6 else case $RPM in [\\/]* | ?:[\\/]*) ac_cv_path_RPM="$RPM" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_RPM="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RPM=$ac_cv_path_RPM if test -n "$RPM"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RPM" >&5 $as_echo "$RPM" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi rpm=$RPM rpm_version=0 test -n "$RPM" && test -x "$RPM" && rpm_version=`$RPM --version \ | awk '{print $NF}' | awk -F. '{V=1; print $V}'` if test $rpm_version -ge 4; then # Extract the first word of "rpmbuild", so it can be a program name with args. set dummy rpmbuild; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_RPMBUILD+:} false; then : $as_echo_n "(cached) " >&6 else case $RPMBUILD in [\\/]* | ?:[\\/]*) ac_cv_path_RPMBUILD="$RPMBUILD" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_RPMBUILD="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RPMBUILD=$ac_cv_path_RPMBUILD if test -n "$RPMBUILD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RPMBUILD" >&5 $as_echo "$RPMBUILD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rpmbuild=$RPMBUILD else rpmbuild=$RPM fi enable_lib64="$enable_lib64" libdirsuffix="" searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test "$enable_lib64" = "yes" -a -n "$searchpath"; then save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) libdirsuffix=64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) libdirsuffix=64 ;; esac ;; esac fi done IFS="$save_IFS" fi if test "$enable_librt" = "yes"; then librt="-lrt" else librt="" fi for ac_header in uuid.h sys/uuid.h uuid/uuid.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test $ac_cv_header_uuid_h = no -a \ $ac_cv_header_sys_uuid_h = no -a \ $ac_cv_header_uuid_uuid_h = no; then echo echo 'FATAL ERROR: could not find a valid UUID header.' echo 'Install the Universally Unique Identifiers development package.' exit 1 fi for ac_func in uuid_compare do : ac_fn_c_check_func "$LINENO" "uuid_compare" "ac_cv_func_uuid_compare" if test "x$ac_cv_func_uuid_compare" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UUID_COMPARE 1 _ACEOF fi done if test $ac_cv_func_uuid_compare = yes; then libuuid="" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_compare in -luuid" >&5 $as_echo_n "checking for uuid_compare in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_compare+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char uuid_compare (); int main () { return uuid_compare (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_uuid_uuid_compare=yes else ac_cv_lib_uuid_uuid_compare=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_compare" >&5 $as_echo "$ac_cv_lib_uuid_uuid_compare" >&6; } if test "x$ac_cv_lib_uuid_uuid_compare" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBUUID 1 _ACEOF LIBS="-luuid $LIBS" else echo echo 'FATAL ERROR: could not find a valid UUID library.' echo 'Install the Universally Unique Identifiers library package.' exit 1 fi libuuid="-luuid" fi for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF fi done if test $ac_cv_header_pthread_h = no; then for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF else echo echo 'FATAL ERROR: could not find a valid pthread header.' exit 1 fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_mutex_init=yes else ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" else echo echo 'FATAL ERROR: could not find a valid pthread library.' exit 1 fi libpthread=-lpthread { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fadvise " >&5 $as_echo_n "checking for fadvise ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include int main () { posix_fadvise(0, 1, 0, POSIX_FADV_NORMAL); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_fadvise=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for madvise " >&5 $as_echo_n "checking for madvise ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include int main () { posix_madvise(0, 0, MADV_NORMAL); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_madvise=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mincore " >&5 $as_echo_n "checking for mincore ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include int main () { mincore(0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_mincore=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sendfile " >&5 $as_echo_n "checking for sendfile ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include int main () { sendfile(0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_sendfile=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getmntent " >&5 $as_echo_n "checking for getmntent ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { getmntent(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_getmntent=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getmntinfo " >&5 $as_echo_n "checking for getmntinfo ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { getmntinfo(0, 0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_getmntinfo=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fallocate" >&5 $as_echo_n "checking for fallocate... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include #include int main () { fallocate(0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_fallocate=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fiemap" >&5 $as_echo_n "checking for fiemap... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include #include int main () { struct fiemap *fiemap; ioctl(0, FS_IOC_FIEMAP, (unsigned long)fiemap); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_fiemap=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for preadv" >&5 $as_echo_n "checking for preadv... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _BSD_SOURCE #include int main () { preadv(0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_preadv=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for copy_file_range" >&5 $as_echo_n "checking for copy_file_range... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include #include int main () { syscall(__NR_copy_file_range, 0, 0, 0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_copy_file_range=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sync_file_range" >&5 $as_echo_n "checking for sync_file_range... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include int main () { sync_file_range(0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_sync_file_range=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for ac_header in mntent.h do : ac_fn_c_check_header_mongrel "$LINENO" "mntent.h" "ac_cv_header_mntent_h" "$ac_includes_default" if test "x$ac_cv_header_mntent_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MNTENT_H 1 _ACEOF have_mntent=yes fi done ac_fn_c_check_decl "$LINENO" "fls" "ac_cv_have_decl_fls" "#include " if test "x$ac_cv_have_decl_fls" = xyes; then : have_fls=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readdir" >&5 $as_echo_n "checking for readdir... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { readdir(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_readdir=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_fn_c_check_decl "$LINENO" "fsetxattr" "ac_cv_have_decl_fsetxattr" "#include #include " if test "x$ac_cv_have_decl_fsetxattr" = xyes; then : have_fsetxattr=yes fi ac_fn_c_check_decl "$LINENO" "mremap" "ac_cv_have_decl_mremap" "#define _GNU_SOURCE #include " if test "x$ac_cv_have_decl_mremap" = xyes; then : have_mremap=yes fi ac_fn_c_check_type "$LINENO" "struct fsxattr" "ac_cv_type_struct_fsxattr" "#include " if test "x$ac_cv_type_struct_fsxattr" = xyes; then : ac_fn_c_check_member "$LINENO" "struct fsxattr" "fsx_cowextsize" "ac_cv_member_struct_fsxattr_fsx_cowextsize" "#include " if test "x$ac_cv_member_struct_fsxattr_fsx_cowextsize" = xyes; then : else need_internal_fsxattr=yes fi fi if test "$enable_blkid" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing blkid_probe_all" >&5 $as_echo_n "checking for library containing blkid_probe_all... " >&6; } if ${ac_cv_search_blkid_probe_all+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char blkid_probe_all (); int main () { return blkid_probe_all (); ; return 0; } _ACEOF for ac_lib in '' blkid; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_blkid_probe_all=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_blkid_probe_all+:} false; then : break fi done if ${ac_cv_search_blkid_probe_all+:} false; then : else ac_cv_search_blkid_probe_all=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_blkid_probe_all" >&5 $as_echo "$ac_cv_search_blkid_probe_all" >&6; } ac_res=$ac_cv_search_blkid_probe_all if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi for ac_func in blkid_probe_get_topology do : ac_fn_c_check_func "$LINENO" "blkid_probe_get_topology" "ac_cv_func_blkid_probe_get_topology" if test "x$ac_cv_func_blkid_probe_get_topology" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BLKID_PROBE_GET_TOPOLOGY 1 _ACEOF fi done if test $ac_cv_func_blkid_probe_get_topology = yes; then libblkid="-lblkid" else echo echo 'FATAL ERROR: could not find a valid BLKID header.' echo 'Install the Block device ID development package.' exit 1 fi fi # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 $as_echo_n "checking size of long... " >&6; } if ${ac_cv_sizeof_long+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : else if test "$ac_cv_type_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 $as_echo "$ac_cv_sizeof_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char *" >&5 $as_echo_n "checking size of char *... " >&6; } if ${ac_cv_sizeof_char_p+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char *))" "ac_cv_sizeof_char_p" "$ac_includes_default"; then : else if test "$ac_cv_type_char_p" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (char *) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_char_p=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char_p" >&5 $as_echo "$ac_cv_sizeof_char_p" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_CHAR_P $ac_cv_sizeof_char_p _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for umode_t" >&5 $as_echo_n "checking for umode_t... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { umode_t umode; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_UMODE_T 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext have_zipped_manpages=false for d in ${prefix}/share/man ${prefix}/man ; do if test -f $d/man1/man.1.gz then have_zipped_manpages=true break fi done ac_config_files="$ac_config_files include/builddefs" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by xfsprogs $as_me 4.9.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ xfsprogs config.status 4.9.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "include/platform_defs.h") CONFIG_HEADERS="$CONFIG_HEADERS include/platform_defs.h" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "include/builddefs") CONFIG_FILES="$CONFIG_FILES include/builddefs" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi xfsprogs-4.9.0+nmu1ubuntu2/configure.ac0000644000000000000000000000667413063067167015002 0ustar AC_INIT([xfsprogs], [4.9.0], [linux-xfs@vger.kernel.org]) AC_PREREQ(2.50) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([include/libxfs.h]) AC_CONFIG_HEADER(include/platform_defs.h) AC_PREFIX_DEFAULT(/usr) AC_PROG_LIBTOOL AC_PROG_CC if test $cross_compiling = no; then BUILD_CC="$CC" AC_SUBST(BUILD_CC) else AC_CHECK_PROGS(BUILD_CC, gcc cc) fi AC_ARG_ENABLE(shared, [ --enable-shared=[yes/no] Enable use of shared libraries [default=yes]],, enable_shared=yes) AC_SUBST(enable_shared) AC_ARG_ENABLE(gettext, [ --enable-gettext=[yes/no] Enable alternate language support [default=yes]],, enable_gettext=yes) AC_SUBST(enable_gettext) AC_ARG_ENABLE(blkid, [ --enable-blkid=[yes/no] Enable use of block device id library [default=yes]],, enable_blkid=yes) AC_SUBST(enable_blkid) AC_ARG_ENABLE(readline, [ --enable-readline=[yes/no] Enable readline command editing [default=no]], test $enable_readline = yes && libreadline="-lreadline", enable_readline=no) AC_SUBST(libreadline) AC_SUBST(enable_readline) AC_ARG_ENABLE(editline, [ --enable-editline=[yes/no] Enable editline command editing [default=no]], test $enable_editline = yes && libeditline="-ledit", enable_editline=no) AC_SUBST(libeditline) AC_SUBST(enable_editline) AC_ARG_ENABLE(termcap, [ --enable-termcap=[yes/no] Enable terminal capabilities library [default=no]], test $enable_termcap = yes && libtermcap="-ltermcap",) AC_SUBST(libtermcap) AC_ARG_ENABLE(lib64, [ --enable-lib64=[yes/no] Enable lib64 support [default=yes]],, enable_lib64=yes) AC_SUBST(enable_lib64) AC_ARG_ENABLE(librt, [ --enable-librt=[yes/no] Enable librt support [default=yes]],, enable_librt=yes) AC_SUBST(enable_librt) # # If the user specified a libdir ending in lib64 do not append another # 64 to the library names. # base_libdir=`basename "$libdir"` case $base_libdir in lib64) enable_lib64=no esac # # Some important tools should be installed into the root partitions. # # Check whether exec_prefix=/usr: and install them to /sbin in that # case. If the user choses a different prefix assume he just wants # a local install for testing and not a system install. # case $exec_prefix:$prefix in NONE:NONE | NONE:/usr | /usr:*) root_sbindir='/sbin' root_libdir="/${base_libdir}" ;; *) root_sbindir="${sbindir}" root_libdir="${libdir}" ;; esac AC_SUBST([root_sbindir]) AC_SUBST([root_libdir]) # Find localized files. Don't descend into any "dot directories" # (like .git or .pc from quilt). Strangely, the "-print" argument # to "find" is required, to avoid including such directories in the # list. LOCALIZED_FILES="" for lfile in `find ${srcdir} -path './.??*' -prune -o -name '*.c' -type f -print || exit 1`; do LOCALIZED_FILES="$LOCALIZED_FILES \$(TOPDIR)/$lfile" done AC_SUBST(LOCALIZED_FILES) AC_PACKAGE_GLOBALS(xfsprogs) AC_PACKAGE_UTILITIES(xfsprogs) AC_MULTILIB($enable_lib64) AC_RT($enable_librt) AC_PACKAGE_NEED_UUID_H AC_PACKAGE_NEED_UUIDCOMPARE AC_PACKAGE_NEED_PTHREAD_H AC_PACKAGE_NEED_PTHREADMUTEXINIT AC_HAVE_FADVISE AC_HAVE_MADVISE AC_HAVE_MINCORE AC_HAVE_SENDFILE AC_HAVE_GETMNTENT AC_HAVE_GETMNTINFO AC_HAVE_FALLOCATE AC_HAVE_FIEMAP AC_HAVE_PREADV AC_HAVE_COPY_FILE_RANGE AC_HAVE_SYNC_FILE_RANGE AC_HAVE_MNTENT AC_HAVE_FLS AC_HAVE_READDIR AC_HAVE_FSETXATTR AC_HAVE_MREMAP AC_NEED_INTERNAL_FSXATTR if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO fi AC_CHECK_SIZEOF([long]) AC_CHECK_SIZEOF([char *]) AC_TYPE_UMODE_T AC_MANUAL_FORMAT AC_CONFIG_FILES([include/builddefs]) AC_OUTPUT xfsprogs-4.9.0+nmu1ubuntu2/copy/0000755000000000000000000000000013063067174013447 5ustar xfsprogs-4.9.0+nmu1ubuntu2/copy/Makefile0000644000000000000000000000077513063067173015117 0ustar # # Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_copy CFILES = xfs_copy.c HFILES = xfs_copy.h LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBPTHREAD) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) LLDFLAGS = -static-libtool-libs default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/copy/xfs_copy.c0000644000000000000000000010117313063067173015447 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include #include #include #include #include "xfs_copy.h" #include "libxlog.h" #define rounddown(x, y) (((x)/(y))*(y)) #define uuid_equal(s,d) (platform_uuid_compare((s),(d)) == 0) extern int platform_check_ismounted(char *, char *, struct stat *, int); int logfd; char *logfile_name; FILE *logerr; char LOGFILE_NAME[] = "/var/tmp/xfs_copy.log.XXXXXX"; char *source_name; int source_fd; unsigned int source_blocksize; /* source filesystem blocksize */ unsigned int source_sectorsize; /* source disk sectorsize */ xfs_agblock_t first_agbno; __uint64_t barcount[11]; unsigned int num_targets; target_control *target; wbuf w_buf; wbuf btree_buf; pid_t parent_pid; unsigned int kids; thread_control glob_masks; thread_args *targ; pthread_mutex_t mainwait; #define ACTIVE 1 #define INACTIVE 2 xfs_off_t write_log_trailer(int fd, wbuf *w, xfs_mount_t *mp); xfs_off_t write_log_header(int fd, wbuf *w, xfs_mount_t *mp); static int format_logs(struct xfs_mount *); /* general purpose message reporting routine */ #define OUT 0x01 /* use stdout stream */ #define ERR 0x02 /* use stderr stream */ #define LOG 0x04 /* use logerr stream */ #define PRE 0x08 /* append strerror string */ #define LAST 0x10 /* final message we print */ void signal_maskfunc(int addset, int newset) { sigset_t set; sigemptyset(&set); sigaddset(&set, addset); sigprocmask(newset, &set, NULL); } void do_message(int flags, int code, const char *fmt, ...) { va_list ap; int eek = 0; if (flags & LOG) { va_start(ap, fmt); if (vfprintf(logerr, fmt, ap) <= 0) eek = 1; va_end(ap); } if (eek) flags |= ERR; /* failed, force stderr */ if (flags & ERR) { va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } else if (flags & OUT) { va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); } if (flags & PRE) { do_message(flags & ~PRE, 0, ": %s\n", strerror(code)); if (flags & LAST) fprintf(stderr, _("Check logfile \"%s\" for more details\n"), logfile_name); } /* logfile is broken, force a write to stderr */ if (eek) { fprintf(stderr, _("%s: could not write to logfile \"%s\".\n"), progname, logfile_name); fprintf(stderr, _("Aborting XFS copy -- logfile error -- reason: %s\n"), strerror(errno)); pthread_exit(NULL); } } #define do_out(args...) do_message(OUT|LOG, 0, ## args) #define do_log(args...) do_message(ERR|LOG, 0, ## args) #define do_warn(args...) do_message(LOG, 0, ## args) #define do_error(e,s) do_message(ERR|LOG|PRE, e, s) #define do_fatal(e,s) do_message(ERR|LOG|PRE|LAST, e, s) #define do_vfatal(e,s,args...) do_message(ERR|LOG|PRE|LAST, e, s, ## args) #define die_perror() \ do { \ do_message(ERR|LOG|PRE|LAST, errno, \ _("Aborting XFS copy - reason")); \ exit(1); \ } while (0) /* workaround craziness in the xlog routines */ int xlog_recover_do_trans(struct xlog *log, struct xlog_recover *t, int p) { return 0; } void check_errors(void) { int i, first_error = 0; for (i = 0; i < num_targets; i++) { if (target[i].state == INACTIVE) { if (first_error == 0) { first_error++; do_log( _("THE FOLLOWING COPIES FAILED TO COMPLETE\n")); } do_log(" %s -- ", target[i].name); if (target[i].err_type == 0) do_log(_("write error")); else do_log(_("lseek error")); do_log(_(" at offset %lld\n"), target[i].position); } } if (first_error == 0) { fprintf(stdout, _("All copies completed.\n")); fflush(NULL); } else { fprintf(stderr, _("See \"%s\" for more details.\n"), logfile_name); exit(1); } } /* * don't have to worry about alignment and mins because those * are taken care of when the buffer's read in */ int do_write( thread_args *args, wbuf *buf) { int res; int error = 0; if (!buf) buf = &w_buf; if (target[args->id].position != buf->position) { if (lseek(args->fd, buf->position, SEEK_SET) < 0) { error = target[args->id].err_type = 1; } else { target[args->id].position = buf->position; } } if ((res = write(target[args->id].fd, buf->data, buf->length)) == buf->length) { target[args->id].position += res; } else { error = 2; } if (error) { target[args->id].error = errno; target[args->id].position = buf->position; } return error; } void * begin_reader(void *arg) { thread_args *args = arg; for (;;) { pthread_mutex_lock(&args->wait); if (do_write(args, NULL)) goto handle_error; pthread_mutex_lock(&glob_masks.mutex); if (--glob_masks.num_working == 0) pthread_mutex_unlock(&mainwait); pthread_mutex_unlock(&glob_masks.mutex); } /* NOTREACHED */ handle_error: /* error will be logged by primary thread */ pthread_mutex_lock(&glob_masks.mutex); target[args->id].state = INACTIVE; if (--glob_masks.num_working == 0) pthread_mutex_unlock(&mainwait); pthread_mutex_unlock(&glob_masks.mutex); pthread_exit(NULL); return NULL; } void handler(int sig) { pid_t pid; int status, i; pid = wait(&status); kids--; for (i = 0; i < num_targets; i++) { if (target[i].pid == pid) { if (target[i].state == INACTIVE) { /* thread got an I/O error */ if (target[i].err_type == 0) { do_warn( _("%s: write error on target %d \"%s\" at offset %lld\n"), progname, i, target[i].name, target[i].position); } else { do_warn( _("%s: lseek error on target %d \"%s\" at offset %lld\n"), progname, i, target[i].name, target[i].position); } do_vfatal(target[i].error, _("Aborting target %d - reason"), i); if (kids == 0) { do_log( _("Aborting XFS copy - no more targets.\n")); check_errors(); pthread_exit(NULL); } signal(SIGCHLD, handler); return; } else { /* it just croaked it bigtime, log it */ do_warn( _("%s: thread %d died unexpectedly, target \"%s\" incomplete\n"), progname, i, target[i].name); do_warn(_("%s: offset was probably %lld\n"), progname, target[i].position); do_fatal(target[i].error, _("Aborting XFS copy - reason")); pthread_exit(NULL); } } } /* unknown child -- something very wrong */ do_warn(_("%s: Unknown child died (should never happen!)\n"), progname); die_perror(); pthread_exit(NULL); signal(SIGCHLD, handler); } void usage(void) { fprintf(stderr, _("Usage: %s [-bdV] [-L logfile] source target [target ...]\n"), progname); exit(1); } void init_bar(__uint64_t source_blocks) { int i; for (i = 0; i < 11; i++) barcount[i] = (source_blocks/10)*i; } int bump_bar(int tenths, __uint64_t numblocks) { static char *bar[11] = { " 0% ", " ... 10% ", " ... 20% ", " ... 30% ", " ... 40% ", " ... 50% ", " ... 60% ", " ... 70% ", " ... 80% ", " ... 90% ", " ... 100%\n\n", }; if (tenths > 10) { printf("%s", bar[10]); fflush(stdout); } else { while (tenths < 10 && numblocks > barcount[tenths]) { printf("%s", bar[tenths]); fflush(stdout); tenths++; } } return tenths; } static xfs_off_t source_position = -1; wbuf * wbuf_init(wbuf *buf, int data_size, int data_align, int min_io_size, int id) { ASSERT(data_size % BBSIZE == 0); while ((buf->data = memalign(data_align, data_size)) == NULL) { data_size >>= 1; if (data_size < min_io_size) return NULL; } ASSERT(min_io_size % BBSIZE == 0); buf->data_align = data_align; buf->min_io_size = min_io_size; buf->size = data_size; buf->id = id; return buf; } void read_wbuf(int fd, wbuf *buf, xfs_mount_t *mp) { int res = 0; xfs_off_t lres = 0; xfs_off_t newpos; size_t diff; newpos = rounddown(buf->position, (xfs_off_t) buf->min_io_size); if (newpos != buf->position) { diff = buf->position - newpos; buf->position = newpos; buf->length += diff; } if (source_position != buf->position) { lres = lseek(fd, buf->position, SEEK_SET); if (lres < 0LL) { do_warn(_("%s: lseek failure at offset %lld\n"), progname, source_position); die_perror(); } source_position = buf->position; } ASSERT(source_position % source_sectorsize == 0); /* round up length for direct I/O if necessary */ if (buf->length % buf->min_io_size != 0) buf->length = roundup(buf->length, buf->min_io_size); if (buf->length > buf->size) { do_warn(_("assert error: buf->length = %d, buf->size = %d\n"), buf->length, buf->size); exit(1); } if ((res = read(fd, buf->data, buf->length)) < 0) { do_warn(_("%s: read failure at offset %lld\n"), progname, source_position); die_perror(); } if (res < buf->length && source_position + res == mp->m_sb.sb_dblocks * source_blocksize) res = buf->length; else ASSERT(res == buf->length); source_position += res; buf->length = res; } void read_ag_header(int fd, xfs_agnumber_t agno, wbuf *buf, ag_header_t *ag, xfs_mount_t *mp, int blocksize, int sectorsize) { xfs_daddr_t off; int length; xfs_off_t newpos; size_t diff; /* initial settings */ diff = 0; off = XFS_AG_DADDR(mp, agno, XFS_SB_DADDR); buf->position = (xfs_off_t) off * (xfs_off_t) BBSIZE; length = buf->length = first_agbno * blocksize; if (length == 0) { do_log(_("ag header buffer invalid!\n")); exit(1); } /* handle alignment stuff */ newpos = rounddown(buf->position, (xfs_off_t) buf->min_io_size); if (newpos != buf->position) { diff = buf->position - newpos; buf->position = newpos; buf->length += diff; } /* round up length for direct I/O if necessary */ if (buf->length % buf->min_io_size != 0) buf->length = roundup(buf->length, buf->min_io_size); read_wbuf(fd, buf, mp); ASSERT(buf->length >= length); ag->xfs_sb = (xfs_dsb_t *) (buf->data + diff); ASSERT(be32_to_cpu(ag->xfs_sb->sb_magicnum) == XFS_SB_MAGIC); ag->xfs_agf = (xfs_agf_t *) (buf->data + diff + sectorsize); ASSERT(be32_to_cpu(ag->xfs_agf->agf_magicnum) == XFS_AGF_MAGIC); ag->xfs_agi = (xfs_agi_t *) (buf->data + diff + 2 * sectorsize); ASSERT(be32_to_cpu(ag->xfs_agi->agi_magicnum) == XFS_AGI_MAGIC); ag->xfs_agfl = (xfs_agfl_t *) (buf->data + diff + 3 * sectorsize); } void write_wbuf(void) { int i; /* verify target threads */ for (i = 0; i < num_targets; i++) if (target[i].state != INACTIVE) glob_masks.num_working++; /* release target threads */ for (i = 0; i < num_targets; i++) if (target[i].state != INACTIVE) pthread_mutex_unlock(&targ[i].wait); /* wake up */ signal_maskfunc(SIGCHLD, SIG_UNBLOCK); pthread_mutex_lock(&mainwait); signal_maskfunc(SIGCHLD, SIG_BLOCK); } void sb_update_uuid( xfs_sb_t *sb, /* Original fs superblock */ ag_header_t *ag_hdr, /* AG hdr to update for this copy */ thread_args *tcarg) /* Args for this thread, with UUID */ { /* * If this filesystem has CRCs, the original UUID is stamped into * all metadata. If we don't have an existing meta_uuid field in the * the original filesystem and we are changing the UUID in this copy, * we must copy the original sb_uuid to the sb_meta_uuid slot and set * the incompat flag for the feature on this copy. */ if (xfs_sb_version_hascrc(sb) && !xfs_sb_version_hasmetauuid(sb) && !uuid_equal(&tcarg->uuid, &sb->sb_uuid)) { __be32 feat; feat = be32_to_cpu(ag_hdr->xfs_sb->sb_features_incompat); feat |= XFS_SB_FEAT_INCOMPAT_META_UUID; ag_hdr->xfs_sb->sb_features_incompat = cpu_to_be32(feat); platform_uuid_copy(&ag_hdr->xfs_sb->sb_meta_uuid, &sb->sb_uuid); } /* Copy the (possibly new) fs-identifier UUID into sb_uuid */ platform_uuid_copy(&ag_hdr->xfs_sb->sb_uuid, &tcarg->uuid); /* We may have changed the UUID, so update the superblock CRC */ if (xfs_sb_version_hascrc(sb)) xfs_update_cksum((char *)ag_hdr->xfs_sb, sb->sb_sectsize, XFS_SB_CRC_OFF); } int main(int argc, char **argv) { int i, j; int howfar = 0; int open_flags; xfs_off_t pos; size_t length; int c; __uint64_t size, sizeb; __uint64_t numblocks = 0; int wblocks = 0; int num_threads = 0; struct dioattr d; int wbuf_size; int wbuf_align; int wbuf_miniosize; int source_is_file = 0; int buffered_output = 0; int duplicate = 0; uint btree_levels, current_level; ag_header_t ag_hdr; xfs_mount_t *mp; xfs_mount_t mbuf; struct xlog xlog; xfs_buf_t *sbp; xfs_sb_t *sb; xfs_agnumber_t num_ags, agno; xfs_agblock_t bno; xfs_daddr_t begin, next_begin, ag_begin, new_begin, ag_end; struct xfs_btree_block *block; xfs_alloc_ptr_t *ptr; xfs_alloc_rec_t *rec_ptr; extern char *optarg; extern int optind; libxfs_init_t xargs; thread_args *tcarg; struct stat statbuf; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((c = getopt(argc, argv, "bdL:V")) != EOF) { switch (c) { case 'b': buffered_output = 1; break; case 'd': duplicate = 1; break; case 'L': logfile_name = optarg; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); case '?': usage(); } } if (argc - optind < 2) usage(); if (logfile_name) { logfd = open(logfile_name, O_CREAT|O_WRONLY|O_EXCL, 0600); } else { logfile_name = LOGFILE_NAME; logfd = mkstemp(logfile_name); } if (logfd < 0) { fprintf(stderr, _("%s: couldn't open log file \"%s\"\n"), progname, logfile_name); perror(_("Aborting XFS copy - reason")); exit(1); } if ((logerr = fdopen(logfd, "w")) == NULL) { fprintf(stderr, _("%s: couldn't set up logfile stream\n"), progname); perror(_("Aborting XFS copy - reason")); exit(1); } source_name = argv[optind]; source_fd = -1; optind++; num_targets = argc - optind; if ((target = malloc(sizeof(target_control) * num_targets)) == NULL) { do_log(_("Couldn't allocate target array\n")); die_perror(); } for (i = 0; optind < argc; i++, optind++) { target[i].name = argv[optind]; target[i].fd = -1; target[i].position = -1; target[i].state = INACTIVE; target[i].error = 0; target[i].err_type = 0; } parent_pid = getpid(); /* open up source -- is it a file? */ open_flags = O_RDONLY; if ((source_fd = open(source_name, open_flags)) < 0) { do_log(_("%s: couldn't open source \"%s\"\n"), progname, source_name); die_perror(); } if (fstat(source_fd, &statbuf) < 0) { do_log(_("%s: couldn't stat source \"%s\"\n"), progname, source_name); die_perror(); } if (S_ISREG(statbuf.st_mode)) source_is_file = 1; if (source_is_file && platform_test_xfs_fd(source_fd)) { if (fcntl(source_fd, F_SETFL, open_flags | O_DIRECT) < 0) { do_log(_("%s: Cannot set direct I/O flag on \"%s\".\n"), progname, source_name); die_perror(); } if (xfsctl(source_name, source_fd, XFS_IOC_DIOINFO, &d) < 0) { do_log(_("%s: xfsctl on file \"%s\" failed.\n"), progname, source_name); die_perror(); } wbuf_align = d.d_mem; wbuf_size = MIN(d.d_maxiosz, 1 * 1024 * 1024); wbuf_miniosize = d.d_miniosz; } else { /* set arbitrary I/O params, miniosize at least 1 disk block */ wbuf_align = getpagesize(); wbuf_size = 1 * 1024 * 1024; wbuf_miniosize = -1; /* set after mounting source fs */ } if (!source_is_file) { /* * check to make sure a filesystem isn't mounted * on the device */ if (platform_check_ismounted(source_name, NULL, &statbuf, 0)) { do_log( _("%s: Warning -- a filesystem is mounted on the source device.\n"), progname); do_log( _("\t\tGenerated copies may be corrupt unless the source is\n")); do_log( _("\t\tunmounted or mounted read-only. Copy proceeding...\n")); } } /* prepare the libxfs_init structure */ memset(&xargs, 0, sizeof(xargs)); xargs.isdirect = LIBXFS_DIRECT; xargs.isreadonly = LIBXFS_ISREADONLY; if (source_is_file) { xargs.dname = source_name; xargs.disfile = 1; } else xargs.volname = source_name; if (!libxfs_init(&xargs)) { do_log(_("%s: couldn't initialize XFS library\n" "%s: Aborting.\n"), progname, progname); exit(1); } memset(&mbuf, 0, sizeof(xfs_mount_t)); /* We don't yet know the sector size, so read maximal size */ libxfs_buftarg_init(&mbuf, xargs.ddev, xargs.logdev, xargs.rtdev); sbp = libxfs_readbuf(mbuf.m_ddev_targp, XFS_SB_DADDR, 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, NULL); sb = &mbuf.m_sb; libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbp)); /* Do it again, now with proper length and verifier */ libxfs_putbuf(sbp); libxfs_purgebuf(sbp); sbp = libxfs_readbuf(mbuf.m_ddev_targp, XFS_SB_DADDR, 1 << (sb->sb_sectlog - BBSHIFT), 0, &xfs_sb_buf_ops); libxfs_putbuf(sbp); mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev, 0); if (mp == NULL) { do_log(_("%s: %s filesystem failed to initialize\n" "%s: Aborting.\n"), progname, source_name, progname); exit(1); } else if (mp->m_sb.sb_inprogress) { do_log(_("%s %s filesystem failed to initialize\n" "%s: Aborting.\n"), progname, source_name, progname); exit(1); } else if (mp->m_sb.sb_logstart == 0) { do_log(_("%s: %s has an external log.\n%s: Aborting.\n"), progname, source_name, progname); exit(1); } else if (mp->m_sb.sb_rextents != 0) { do_log(_("%s: %s has a real-time section.\n" "%s: Aborting.\n"), progname, source_name, progname); exit(1); } /* * Set up the mount pointer to access the log and check whether the log * is clean. Fail on a dirty or corrupt log in non-duplicate mode * because the log is formatted as part of the copy and we don't want to * destroy data. We also need the current log cycle to format v5 * superblock logs correctly. */ memset(&xlog, 0, sizeof(struct xlog)); mp->m_log = &xlog; c = xlog_is_dirty(mp, mp->m_log, &xargs, 0); if (!duplicate) { if (c == 1) { do_log(_( "Error: source filesystem log is dirty. Mount the filesystem to replay the\n" "log, unmount and retry xfs_copy.\n")); exit(1); } else if (c < 0) { do_log(_( "Error: could not determine the log head or tail of the source filesystem.\n" "Mount the filesystem to replay the log or run xfs_repair.\n")); exit(1); } } source_blocksize = mp->m_sb.sb_blocksize; source_sectorsize = mp->m_sb.sb_sectsize; if (wbuf_miniosize == -1) wbuf_miniosize = source_sectorsize; ASSERT(source_blocksize % source_sectorsize == 0); ASSERT(source_sectorsize % BBSIZE == 0); if (source_blocksize < source_sectorsize) { do_log(_("Error: filesystem block size is smaller than the" " disk sectorsize.\nAborting XFS copy now.\n")); exit(1); } first_agbno = XFS_AGFL_BLOCK(mp) + 1; /* now open targets */ open_flags = O_RDWR; for (i = 0; i < num_targets; i++) { int write_last_block = 0; if (stat(target[i].name, &statbuf) < 0) { /* ok, assume it's a file and create it */ do_out(_("Creating file %s\n"), target[i].name); open_flags |= O_CREAT; if (!buffered_output) open_flags |= O_DIRECT; write_last_block = 1; } else if (S_ISREG(statbuf.st_mode)) { open_flags |= O_TRUNC; if (!buffered_output) open_flags |= O_DIRECT; write_last_block = 1; } else { /* * check to make sure a filesystem isn't mounted * on the device */ if (platform_check_ismounted(target[i].name, NULL, &statbuf, 0)) { do_log(_("%s: a filesystem is mounted " "on target device \"%s\".\n" "%s cannot copy to mounted filesystems." " Aborting\n"), progname, target[i].name, progname); exit(1); } } target[i].fd = open(target[i].name, open_flags, 0644); if (target[i].fd < 0) { do_log(_("%s: couldn't open target \"%s\"\n"), progname, target[i].name); die_perror(); } if (write_last_block) { /* ensure regular files are correctly sized */ if (ftruncate(target[i].fd, mp->m_sb.sb_dblocks * source_blocksize)) { do_log(_("%s: cannot grow data section.\n"), progname); die_perror(); } if (platform_test_xfs_fd(target[i].fd)) { if (xfsctl(target[i].name, target[i].fd, XFS_IOC_DIOINFO, &d) < 0) { do_log( _("%s: xfsctl on \"%s\" failed.\n"), progname, target[i].name); die_perror(); } else { wbuf_align = MAX(wbuf_align, d.d_mem); wbuf_size = MIN(d.d_maxiosz, wbuf_size); wbuf_miniosize = MAX(d.d_miniosz, wbuf_miniosize); } } } else { char *lb[XFS_MAX_SECTORSIZE] = { NULL }; off64_t off; /* ensure device files are sufficiently large */ off = mp->m_sb.sb_dblocks * source_blocksize; off -= sizeof(lb); if (pwrite(target[i].fd, lb, sizeof(lb), off) < 0) { do_log(_("%s: failed to write last block\n"), progname); do_log(_("\tIs target \"%s\" too small?\n"), target[i].name); die_perror(); } } } /* initialize locks and bufs */ if (pthread_mutex_init(&glob_masks.mutex, NULL) != 0) { do_log(_("Couldn't initialize global thread mask\n")); die_perror(); } glob_masks.num_working = 0; if (wbuf_init(&w_buf, wbuf_size, wbuf_align, wbuf_miniosize, 0) == NULL) { do_log(_("Error initializing wbuf 0\n")); die_perror(); } wblocks = wbuf_size / BBSIZE; if (wbuf_init(&btree_buf, MAX(source_blocksize, wbuf_miniosize), wbuf_align, wbuf_miniosize, 1) == NULL) { do_log(_("Error initializing btree buf 1\n")); die_perror(); } if (pthread_mutex_init(&mainwait,NULL) != 0) { do_log(_("Error creating first semaphore.\n")); die_perror(); exit(1); } /* need to start out blocking */ pthread_mutex_lock(&mainwait); /* set up sigchild signal handler */ signal(SIGCHLD, handler); signal_maskfunc(SIGCHLD, SIG_BLOCK); /* make children */ if ((targ = malloc(num_targets * sizeof(thread_args))) == NULL) { do_log(_("Couldn't malloc space for thread args\n")); die_perror(); exit(1); } for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++) { if (!duplicate) platform_uuid_generate(&tcarg->uuid); else platform_uuid_copy(&tcarg->uuid, &mp->m_sb.sb_uuid); if (pthread_mutex_init(&tcarg->wait, NULL) != 0) { do_log(_("Error creating thread mutex %d\n"), i); die_perror(); exit(1); } /* need to start out blocking */ pthread_mutex_lock(&tcarg->wait); } for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++) { tcarg->id = i; tcarg->fd = target[i].fd; target[i].state = ACTIVE; num_threads++; if (pthread_create(&target[i].pid, NULL, begin_reader, (void *)tcarg)) { do_log(_("Error creating thread for target %d\n"), i); die_perror(); } } ASSERT(num_targets == num_threads); /* set up statistics */ num_ags = mp->m_sb.sb_agcount; init_bar(mp->m_sb.sb_blocksize / BBSIZE * ((__uint64_t)mp->m_sb.sb_dblocks - (__uint64_t)mp->m_sb.sb_fdblocks + 10 * num_ags)); kids = num_targets; for (agno = 0; agno < num_ags && kids > 0; agno++) { /* read in first blocks of the ag */ read_ag_header(source_fd, agno, &w_buf, &ag_hdr, mp, source_blocksize, source_sectorsize); /* set the in_progress bit for the first AG */ if (agno == 0) ag_hdr.xfs_sb->sb_inprogress = 1; /* save what we need (agf) in the btree buffer */ memmove(btree_buf.data, ag_hdr.xfs_agf, source_sectorsize); ag_hdr.xfs_agf = (xfs_agf_t *) btree_buf.data; btree_buf.length = source_blocksize; /* write the ag header out */ write_wbuf(); /* traverse btree until we get to the leftmost leaf node */ bno = be32_to_cpu(ag_hdr.xfs_agf->agf_roots[XFS_BTNUM_BNOi]); current_level = 0; btree_levels = be32_to_cpu(ag_hdr.xfs_agf-> agf_levels[XFS_BTNUM_BNOi]); ag_end = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(ag_hdr.xfs_agf->agf_length) - 1) + source_blocksize / BBSIZE; for (;;) { /* none of this touches the w_buf buffer */ if (current_level >= btree_levels) { do_log( _("Error: current level %d >= btree levels %d\n"), current_level, btree_levels); exit(1); } current_level++; btree_buf.position = pos = (xfs_off_t) XFS_AGB_TO_DADDR(mp,agno,bno) << BBSHIFT; btree_buf.length = source_blocksize; read_wbuf(source_fd, &btree_buf, mp); block = (struct xfs_btree_block *) ((char *)btree_buf.data + pos - btree_buf.position); if (be32_to_cpu(block->bb_magic) != (xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTB_CRC_MAGIC : XFS_ABTB_MAGIC)) { do_log(_("Bad btree magic 0x%x\n"), be32_to_cpu(block->bb_magic)); exit(1); } if (be16_to_cpu(block->bb_level) == 0) break; ptr = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); bno = be32_to_cpu(ptr[0]); } /* align first data copy but don't overwrite ag header */ pos = w_buf.position >> BBSHIFT; length = w_buf.length >> BBSHIFT; next_begin = pos + length; ag_begin = next_begin; ASSERT(w_buf.position % source_sectorsize == 0); /* handle the rest of the ag */ for (;;) { if (be16_to_cpu(block->bb_level) != 0) { do_log( _("WARNING: source filesystem inconsistent.\n")); do_log( _(" A leaf btree rec isn't a leaf. Aborting now.\n")); exit(1); } rec_ptr = XFS_ALLOC_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++, rec_ptr++) { /* calculate in daddr's */ begin = next_begin; /* * protect against pathological case of a * hole right after the ag header in a * mis-aligned case */ if (begin < ag_begin) begin = ag_begin; /* * round size up to ensure we copy a * range bigger than required */ sizeb = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(rec_ptr->ar_startblock)) - begin; size = roundup(sizeb < 0) { /* copy extent */ w_buf.position = (xfs_off_t) begin << BBSHIFT; while (size > 0) { /* * let lower layer do alignment */ if (size > w_buf.size) { w_buf.length = w_buf.size; size -= w_buf.size; sizeb -= wblocks; numblocks += wblocks; } else { w_buf.length = size; numblocks += sizeb; size = 0; } read_wbuf(source_fd, &w_buf, mp); write_wbuf(); w_buf.position += w_buf.length; howfar = bump_bar( howfar, numblocks); } } /* round next starting point down */ new_begin = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(rec_ptr->ar_startblock) + be32_to_cpu(rec_ptr->ar_blockcount)); next_begin = rounddown(new_begin, w_buf.min_io_size >> BBSHIFT); } if (be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK) break; /* read in next btree record block */ btree_buf.position = pos = (xfs_off_t) XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu( block->bb_u.s.bb_rightsib)) << BBSHIFT; btree_buf.length = source_blocksize; /* let read_wbuf handle alignment */ read_wbuf(source_fd, &btree_buf, mp); block = (struct xfs_btree_block *) ((char *) btree_buf.data + pos - btree_buf.position); ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC); } /* * write out range of used blocks after last range * of free blocks in AG */ if (next_begin < ag_end) { begin = next_begin; sizeb = ag_end - begin; size = roundup(sizeb << BBSHIFT, wbuf_miniosize); if (size > 0) { /* copy extent */ w_buf.position = (xfs_off_t) begin << BBSHIFT; while (size > 0) { /* * let lower layer do alignment */ if (size > w_buf.size) { w_buf.length = w_buf.size; size -= w_buf.size; sizeb -= wblocks; numblocks += wblocks; } else { w_buf.length = size; numblocks += sizeb; size = 0; } read_wbuf(source_fd, &w_buf, mp); write_wbuf(); w_buf.position += w_buf.length; howfar = bump_bar(howfar, numblocks); } } } } if (kids > 0) { if (!duplicate) /* write a clean log using the specified UUID */ format_logs(mp); else num_ags = 1; /* reread and rewrite superblocks (UUID and in-progress) */ /* [backwards, so inprogress bit only updated when done] */ for (i = num_ags - 1; i >= 0; i--) { read_ag_header(source_fd, i, &w_buf, &ag_hdr, mp, source_blocksize, source_sectorsize); if (i == 0) ag_hdr.xfs_sb->sb_inprogress = 0; /* do each thread in turn, each has its own UUID */ for (j = 0, tcarg = targ; j < num_targets; j++) { sb_update_uuid(sb, &ag_hdr, tcarg); do_write(tcarg, NULL); tcarg++; } } bump_bar(100, 0); } check_errors(); libxfs_umount(mp); return 0; } char * next_log_chunk(char *p, int offset, void *private) { wbuf *buf = (wbuf *)private; if (buf->length < (int)(p - buf->data) + offset) { /* need to flush this one, then start afresh */ do_write(buf->owner, NULL); memset(buf->data, 0, buf->length); return buf->data; } return p + offset; } /* * Writes a log header at the start of the log (with the real * filesystem UUID embedded into it), and writes to all targets. * * Returns the next buffer-length-aligned disk address. */ xfs_off_t write_log_header(int fd, wbuf *buf, xfs_mount_t *mp) { char *p = buf->data; xfs_off_t logstart; int offset; logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart) << BBSHIFT; buf->position = rounddown(logstart, (xfs_off_t)buf->length); memset(p, 0, buf->size); if (logstart % buf->length) { /* unaligned */ read_wbuf(fd, buf, mp); offset = logstart - buf->position; p += offset; memset(p, 0, buf->length - offset); } offset = libxfs_log_header(p, &buf->owner->uuid, xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1, mp->m_sb.sb_logsunit, XLOG_FMT, NULLCOMMITLSN, NULLCOMMITLSN, next_log_chunk, buf); do_write(buf->owner, NULL); return roundup(logstart + offset, buf->length); } /* * May do an aligned read of the last buffer in the log (& zero * the start of that buffer). Returns the disk address at the * end of last aligned buffer in the log. */ xfs_off_t write_log_trailer(int fd, wbuf *buf, xfs_mount_t *mp) { xfs_off_t logend; int offset; logend = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart) << BBSHIFT; logend += XFS_FSB_TO_B(mp, mp->m_sb.sb_logblocks); buf->position = rounddown(logend, (xfs_off_t)buf->length); if (logend % buf->length) { /* unaligned */ read_wbuf(fd, buf, mp); offset = (int)(logend - buf->position); memset(buf->data, 0, offset); do_write(buf->owner, NULL); } return buf->position; } /* * Clear a log by writing a record at the head, the tail and zeroing everything * in between. */ static void clear_log( struct xfs_mount *mp, thread_args *tcarg) { xfs_off_t pos; xfs_off_t end_pos; w_buf.owner = tcarg; w_buf.length = rounddown(w_buf.size, w_buf.min_io_size); pos = write_log_header(source_fd, &w_buf, mp); end_pos = write_log_trailer(source_fd, &w_buf, mp); w_buf.position = pos; memset(w_buf.data, 0, w_buf.length); while (w_buf.position < end_pos) { do_write(tcarg, NULL); w_buf.position += w_buf.length; } } /* * Format the log to a particular cycle number. This is required for version 5 * superblock filesystems to provide metadata LSN validity guarantees. */ static void format_log( struct xfs_mount *mp, thread_args *tcarg, wbuf *buf) { int logstart; int length; int cycle = XLOG_INIT_CYCLE; buf->owner = tcarg; buf->length = buf->size; buf->position = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart) << BBSHIFT; logstart = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logstart); length = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); /* * Bump the cycle number on v5 superblock filesystems to guarantee that * all existing metadata LSNs are valid (behind the current LSN) on the * target fs. */ if (xfs_sb_version_hascrc(&mp->m_sb)) cycle = mp->m_log->l_curr_cycle + 1; /* * Format the entire log into the memory buffer and write it out. If the * write fails, mark the target inactive so the failure is reported. */ libxfs_log_clear(NULL, buf->data, logstart, length, &buf->owner->uuid, xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1, mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true); if (do_write(buf->owner, buf)) target[tcarg->id].state = INACTIVE; } static int format_logs( struct xfs_mount *mp) { thread_args *tcarg; int i; wbuf logbuf; int logsize; if (xfs_sb_version_hascrc(&mp->m_sb)) { logsize = XFS_FSB_TO_B(mp, mp->m_sb.sb_logblocks); if (!wbuf_init(&logbuf, logsize, w_buf.data_align, w_buf.min_io_size, w_buf.id)) return -ENOMEM; } for (i = 0, tcarg = targ; i < num_targets; i++) { if (xfs_sb_version_hascrc(&mp->m_sb)) format_log(mp, tcarg, &logbuf); else clear_log(mp, tcarg); tcarg++; } if (xfs_sb_version_hascrc(&mp->m_sb)) free(logbuf.data); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/copy/xfs_copy.h0000644000000000000000000000572213063067173015457 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * An on-disk allocation group header is composed of 4 structures, * each of which is 1 disk sector long where the sector size is at * least 512 bytes long (BBSIZE). * * There's one ag_header per ag and the superblock in the first ag * is the contains the real data for the entire filesystem (although * most of the relevant data won't change anyway even on a growfs). * * The filesystem superblock specifies the number of AG's and * the AG size. That splits the filesystem up into N pieces, * each of which is an AG and has an ag_header at the beginning. */ typedef struct ag_header { xfs_dsb_t *xfs_sb; /* superblock for filesystem or AG */ xfs_agf_t *xfs_agf; /* free space info */ xfs_agi_t *xfs_agi; /* free inode info */ xfs_agfl_t *xfs_agfl; /* AG freelist */ char *residue; int residue_length; } ag_header_t; /* * The position/buf_position, length/buf_length, data/buffer pairs * exist because of alignment constraints for direct I/O and dealing * with scenarios where either the source or target or both is a file * and the blocksize of the filesystem where file resides is different * from that of the filesystem image being duplicated. You can get * alignment problems resulting from things like AG's starting on * non-aligned points in the filesystem. So you have to be able * to read from points "before" the requested starting point and * read in more data than requested. */ struct t_args; typedef struct { int id; /* buffer ID */ size_t size; /* size of buffer -- fixed */ size_t min_io_size; /* for direct I/O */ int data_align; /* data buffer alignment */ xfs_off_t position; /* requested position (bytes) */ size_t length; /* requested length (bytes) */ char *data; /* pointer to data buffer */ struct t_args *owner; /* for non-parallel writes */ } wbuf; typedef struct t_args { int id; uuid_t uuid; pthread_mutex_t wait; int fd; } thread_args; typedef struct { pthread_mutex_t mutex; int num_working; wbuf *buffer; } thread_control; typedef int thread_id; typedef int tm_index; /* index into thread mask array */ typedef __uint32_t thread_mask; /* a thread mask */ typedef struct { char *name; int fd; xfs_off_t position; pthread_t pid; int state; int error; int err_type; } target_control; xfsprogs-4.9.0+nmu1ubuntu2/db/0000755000000000000000000000000013063067174013062 5ustar xfsprogs-4.9.0+nmu1ubuntu2/db/Makefile0000644000000000000000000000247513063067170014526 0ustar # # Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_db HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \ btblock.h bmroot.h check.h command.h convert.h crc.h debug.h \ dir2.h dir2sf.h dquot.h echo.h faddr.h field.h \ flist.h fprint.h frag.h freesp.h hash.h help.h init.h inode.h input.h \ io.h logformat.h malloc.h metadump.h output.h print.h quit.h sb.h \ sig.h strvec.h text.h type.h write.h attrset.h symlink.h fsmap.h CFILES = $(HFILES:.h=.c) LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) LLDFLAGS += -static-libtool-libs ifeq ($(ENABLE_READLINE),yes) LLDLIBS += $(LIBREADLINE) $(LIBTERMCAP) CFLAGS += -DENABLE_READLINE endif ifeq ($(ENABLE_EDITLINE),yes) LLDLIBS += $(LIBEDITLINE) $(LIBTERMCAP) CFLAGS += -DENABLE_EDITLINE endif default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) $(INSTALL) -m 755 xfs_admin.sh $(PKG_SBIN_DIR)/xfs_admin $(INSTALL) -m 755 xfs_ncheck.sh $(PKG_SBIN_DIR)/xfs_ncheck $(INSTALL) -m 755 xfs_metadump.sh $(PKG_SBIN_DIR)/xfs_metadump install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/db/addr.c0000644000000000000000000000541113063067170014135 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "addr.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "io.h" #include "flist.h" #include "inode.h" #include "output.h" static int addr_f(int argc, char **argv); static void addr_help(void); static const cmdinfo_t addr_cmd = { "addr", "a", addr_f, 0, 1, 1, N_("[field-expression]"), N_("set current address"), addr_help }; static void addr_help(void) { dbprintf(_( "\n" " 'addr' uses the given field to set the filesystem address and type\n" "\n" " Examples:\n" "\n" " sb\n" " a rootino - set the type to inode and set position to the root inode\n" " a u.bmx[0].startblock (for inode with blockmap)\n" "\n" )); } static int addr_f( int argc, char **argv) { adfnc_t adf; const ftattr_t *fa; flist_t *fl; const field_t *fld; typnm_t next; flist_t *tfl; if (argc == 1) { print_iocur("current", iocur_top); return 0; } if (cur_typ == NULL) { dbprintf(_("no current type\n")); return 0; } fld = cur_typ->fields; if (fld != NULL && fld->name[0] == '\0') { fa = &ftattrtab[fld->ftyp]; ASSERT(fa->ftyp == fld->ftyp); fld = fa->subfld; } if (fld == NULL) { dbprintf(_("no fields for type %s\n"), cur_typ->name); return 0; } fl = flist_scan(argv[1]); if (fl == NULL) return 0; if (!flist_parse(fld, fl, iocur_top->data, 0)) goto out; flist_print(fl); for (tfl = fl; tfl->child != NULL; tfl = tfl->child) { if ((tfl->flags & FL_OKLOW) && tfl->low < tfl->high) { dbprintf(_("array not allowed for addr command\n")); goto out; } } fld = tfl->fld; next = fld->next; if (next == TYP_INODATA) next = inode_next_type(); if (next == TYP_NONE) { dbprintf(_("no next type for field %s\n"), fld->name); goto out; } fa = &ftattrtab[fld->ftyp]; ASSERT(fa->ftyp == fld->ftyp); adf = fa->adfunc; if (adf == NULL) { dbprintf(_("no addr function for field %s (type %s)\n"), fld->name, fa->name); goto out; } (*adf)(iocur_top->data, tfl->offset, next); out: flist_free(fl); return 0; } void addr_init(void) { add_command(&addr_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/addr.h0000644000000000000000000000136513063067170014146 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void addr_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/agf.c0000644000000000000000000001066513063067170013767 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "io.h" #include "bit.h" #include "output.h" #include "init.h" #include "agf.h" static int agf_f(int argc, char **argv); static void agf_help(void); static const cmdinfo_t agf_cmd = { "agf", NULL, agf_f, 0, 1, 1, N_("[agno]"), N_("set address to agf header"), agf_help }; const field_t agf_hfld[] = { { "", FLDT_AGF, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(xfs_agf_t, agf_ ## f)) #define SZ(f) bitszof(xfs_agf_t, agf_ ## f) const field_t agf_flds[] = { { "magicnum", FLDT_UINT32X, OI(OFF(magicnum)), C1, 0, TYP_NONE }, { "versionnum", FLDT_UINT32D, OI(OFF(versionnum)), C1, 0, TYP_NONE }, { "seqno", FLDT_AGNUMBER, OI(OFF(seqno)), C1, 0, TYP_NONE }, { "length", FLDT_AGBLOCK, OI(OFF(length)), C1, 0, TYP_NONE }, { "roots", FLDT_AGBLOCK, OI(OFF(roots)), CI(XFS_BTNUM_AGF), FLD_ARRAY|FLD_SKIPALL, TYP_NONE }, { "bnoroot", FLDT_AGBLOCK, OI(OFF(roots) + XFS_BTNUM_BNO * SZ(roots[XFS_BTNUM_BNO])), C1, 0, TYP_BNOBT }, { "cntroot", FLDT_AGBLOCK, OI(OFF(roots) + XFS_BTNUM_CNT * SZ(roots[XFS_BTNUM_CNT])), C1, 0, TYP_CNTBT }, { "rmaproot", FLDT_AGBLOCKNZ, OI(OFF(roots) + XFS_BTNUM_RMAP * SZ(roots[XFS_BTNUM_RMAP])), C1, 0, TYP_RMAPBT }, { "refcntroot", FLDT_AGBLOCKNZ, OI(OFF(refcount_root)), C1, 0, TYP_REFCBT }, { "levels", FLDT_UINT32D, OI(OFF(levels)), CI(XFS_BTNUM_AGF), FLD_ARRAY|FLD_SKIPALL, TYP_NONE }, { "bnolevel", FLDT_UINT32D, OI(OFF(levels) + XFS_BTNUM_BNO * SZ(levels[XFS_BTNUM_BNO])), C1, 0, TYP_NONE }, { "cntlevel", FLDT_UINT32D, OI(OFF(levels) + XFS_BTNUM_CNT * SZ(levels[XFS_BTNUM_CNT])), C1, 0, TYP_NONE }, { "rmaplevel", FLDT_UINT32D, OI(OFF(levels) + XFS_BTNUM_RMAP * SZ(levels[XFS_BTNUM_RMAP])), C1, 0, TYP_NONE }, { "refcntlevel", FLDT_UINT32D, OI(OFF(refcount_level)), C1, 0, TYP_NONE }, { "rmapblocks", FLDT_UINT32D, OI(OFF(rmap_blocks)), C1, 0, TYP_NONE }, { "refcntblocks", FLDT_UINT32D, OI(OFF(refcount_blocks)), C1, 0, TYP_NONE }, { "flfirst", FLDT_UINT32D, OI(OFF(flfirst)), C1, 0, TYP_NONE }, { "fllast", FLDT_UINT32D, OI(OFF(fllast)), C1, 0, TYP_NONE }, { "flcount", FLDT_UINT32D, OI(OFF(flcount)), C1, 0, TYP_NONE }, { "freeblks", FLDT_EXTLEN, OI(OFF(freeblks)), C1, 0, TYP_NONE }, { "longest", FLDT_EXTLEN, OI(OFF(longest)), C1, 0, TYP_NONE }, { "btreeblks", FLDT_UINT32D, OI(OFF(btreeblks)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE }, { "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE }, { NULL } }; static void agf_help(void) { dbprintf(_( "\n" " set allocation group free block list\n" "\n" " Example:\n" "\n" " agf 2 - move location to AGF in 2nd filesystem allocation group\n" "\n" " Located in the second sector of each allocation group, the AGF\n" " contains the root of two different freespace btrees:\n" " The 'cnt' btree keeps track freespace indexed on section size.\n" " The 'bno' btree tracks sections of freespace indexed on block number.\n" )); } static int agf_f( int argc, char **argv) { xfs_agnumber_t agno; char *p; if (argc > 1) { agno = (xfs_agnumber_t)strtoul(argv[1], &p, 0); if (*p != '\0' || agno >= mp->m_sb.sb_agcount) { dbprintf(_("bad allocation group number %s\n"), argv[1]); return 0; } cur_agno = agno; } else if (cur_agno == NULLAGNUMBER) cur_agno = 0; ASSERT(typtab[TYP_AGF].typnm == TYP_AGF); set_cur(&typtab[TYP_AGF], XFS_AG_DADDR(mp, cur_agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_ADD, NULL); return 0; } void agf_init(void) { add_command(&agf_cmd); } int agf_size( void *obj, int startoff, int idx) { return bitize(mp->m_sb.sb_sectsize); } xfsprogs-4.9.0+nmu1ubuntu2/db/agf.h0000644000000000000000000000157013063067170013767 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field agf_flds[]; extern const struct field agf_hfld[]; extern void agf_init(void); extern int agf_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/agfl.c0000644000000000000000000000617613063067170014145 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "io.h" #include "bit.h" #include "output.h" #include "init.h" #include "agfl.h" static int agfl_bno_size(void *obj, int startoff); static int agfl_f(int argc, char **argv); static void agfl_help(void); static const cmdinfo_t agfl_cmd = { "agfl", NULL, agfl_f, 0, 1, 1, N_("[agno]"), N_("set address to agfl block"), agfl_help }; const field_t agfl_hfld[] = { { "", FLDT_AGFL, OI(0), C1, 0, TYP_NONE, }, { NULL } }; const field_t agfl_crc_hfld[] = { { "", FLDT_AGFL_CRC, OI(0), C1, 0, TYP_NONE, }, { NULL } }; #define OFF(f) bitize(offsetof(xfs_agfl_t, agfl_ ## f)) const field_t agfl_flds[] = { { "bno", FLDT_AGBLOCKNZ, OI(OFF(magicnum)), agfl_bno_size, FLD_ARRAY|FLD_COUNT, TYP_DATA }, { NULL } }; const field_t agfl_crc_flds[] = { { "magicnum", FLDT_UINT32X, OI(OFF(magicnum)), C1, 0, TYP_NONE }, { "seqno", FLDT_AGNUMBER, OI(OFF(seqno)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE }, { "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE }, { "bno", FLDT_AGBLOCKNZ, OI(OFF(bno)), agfl_bno_size, FLD_ARRAY|FLD_COUNT, TYP_DATA }, { NULL } }; static int agfl_bno_size( void *obj, int startoff) { return XFS_AGFL_SIZE(mp); } static void agfl_help(void) { dbprintf(_( "\n" " set allocation group freelist\n" "\n" " Example:\n" "\n" " agfl 5" "\n" " Located in the fourth sector of each allocation group,\n" " the agfl freelist for internal btree space allocation is maintained\n" " for each allocation group. This acts as a reserved pool of space\n" " separate from the general filesystem freespace (not used for user data).\n" "\n" )); } static int agfl_f( int argc, char **argv) { xfs_agnumber_t agno; char *p; if (argc > 1) { agno = (xfs_agnumber_t)strtoul(argv[1], &p, 0); if (*p != '\0' || agno >= mp->m_sb.sb_agcount) { dbprintf(_("bad allocation group number %s\n"), argv[1]); return 0; } cur_agno = agno; } else if (cur_agno == NULLAGNUMBER) cur_agno = 0; ASSERT(typtab[TYP_AGFL].typnm == TYP_AGFL); set_cur(&typtab[TYP_AGFL], XFS_AG_DADDR(mp, cur_agno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_ADD, NULL); return 0; } void agfl_init(void) { add_command(&agfl_cmd); } /*ARGSUSED*/ int agfl_size( void *obj, int startoff, int idx) { return bitize(mp->m_sb.sb_sectsize); } xfsprogs-4.9.0+nmu1ubuntu2/db/agfl.h0000644000000000000000000000172213063067170014142 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field agfl_flds[]; extern const struct field agfl_hfld[]; extern const struct field agfl_crc_flds[]; extern const struct field agfl_crc_hfld[]; extern void agfl_init(void); extern int agfl_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/agi.c0000644000000000000000000000661513063067170013772 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "io.h" #include "bit.h" #include "output.h" #include "init.h" #include "agi.h" static int agi_f(int argc, char **argv); static void agi_help(void); static const cmdinfo_t agi_cmd = { "agi", NULL, agi_f, 0, 1, 1, N_("[agno]"), N_("set address to agi header"), agi_help }; const field_t agi_hfld[] = { { "", FLDT_AGI, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(xfs_agi_t, agi_ ## f)) const field_t agi_flds[] = { { "magicnum", FLDT_UINT32X, OI(OFF(magicnum)), C1, 0, TYP_NONE }, { "versionnum", FLDT_UINT32D, OI(OFF(versionnum)), C1, 0, TYP_NONE }, { "seqno", FLDT_AGNUMBER, OI(OFF(seqno)), C1, 0, TYP_NONE }, { "length", FLDT_AGBLOCK, OI(OFF(length)), C1, 0, TYP_NONE }, { "count", FLDT_AGINO, OI(OFF(count)), C1, 0, TYP_NONE }, { "root", FLDT_AGBLOCK, OI(OFF(root)), C1, 0, TYP_INOBT }, { "level", FLDT_UINT32D, OI(OFF(level)), C1, 0, TYP_NONE }, { "freecount", FLDT_AGINO, OI(OFF(freecount)), C1, 0, TYP_NONE }, { "newino", FLDT_AGINO, OI(OFF(newino)), C1, 0, TYP_INODE }, { "dirino", FLDT_AGINO, OI(OFF(dirino)), C1, 0, TYP_INODE }, { "unlinked", FLDT_AGINONN, OI(OFF(unlinked)), CI(XFS_AGI_UNLINKED_BUCKETS), FLD_ARRAY, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE }, { "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE }, { "free_root", FLDT_AGBLOCK, OI(OFF(free_root)), C1, 0, TYP_INOBT }, { "free_level", FLDT_UINT32D, OI(OFF(free_level)), C1, 0, TYP_NONE }, { NULL } }; static void agi_help(void) { dbprintf(_( "\n" " set allocation group inode btree\n" "\n" " Example:\n" "\n" " agi 3 (set location to 3rd allocation group inode btree and type to 'agi')\n" "\n" " Located in the 3rd 512 byte block of each allocation group,\n" " the agi inode btree tracks all used/free inodes in the allocation group.\n" " Inodes are allocated in 16k 'chunks', each btree entry tracks a 'chunk'.\n" "\n" )); } static int agi_f( int argc, char **argv) { xfs_agnumber_t agno; char *p; if (argc > 1) { agno = (xfs_agnumber_t)strtoul(argv[1], &p, 0); if (*p != '\0' || agno >= mp->m_sb.sb_agcount) { dbprintf(_("bad allocation group number %s\n"), argv[1]); return 0; } cur_agno = agno; } else if (cur_agno == NULLAGNUMBER) cur_agno = 0; ASSERT(typtab[TYP_AGI].typnm == TYP_AGI); set_cur(&typtab[TYP_AGI], XFS_AG_DADDR(mp, cur_agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_ADD, NULL); return 0; } void agi_init(void) { add_command(&agi_cmd); } /*ARGSUSED*/ int agi_size( void *obj, int startoff, int idx) { return bitize(mp->m_sb.sb_sectsize); } xfsprogs-4.9.0+nmu1ubuntu2/db/agi.h0000644000000000000000000000157013063067170013772 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field agi_flds[]; extern const struct field agi_hfld[]; extern void agi_init(void); extern int agi_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/attr.c0000644000000000000000000003630113063067170014177 0ustar /* * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "bit.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "attr.h" #include "io.h" #include "init.h" #include "output.h" static int attr_leaf_entries_count(void *obj, int startoff); static int attr_leaf_hdr_count(void *obj, int startoff); static int attr_leaf_name_local_count(void *obj, int startoff); static int attr_leaf_name_local_name_count(void *obj, int startoff); static int attr_leaf_name_local_value_count(void *obj, int startoff); static int attr_leaf_name_local_value_offset(void *obj, int startoff, int idx); static int attr_leaf_name_remote_count(void *obj, int startoff); static int attr_leaf_name_remote_name_count(void *obj, int startoff); static int attr_leaf_nvlist_count(void *obj, int startoff); static int attr_leaf_nvlist_offset(void *obj, int startoff, int idx); static int attr_node_btree_count(void *obj, int startoff); static int attr_node_hdr_count(void *obj, int startoff); const field_t attr_hfld[] = { { "", FLDT_ATTR, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define LOFF(f) bitize(offsetof(xfs_attr_leafblock_t, f)) #define NOFF(f) bitize(offsetof(xfs_da_intnode_t, f)) const field_t attr_flds[] = { { "hdr", FLDT_ATTR_LEAF_HDR, OI(LOFF(hdr)), attr_leaf_hdr_count, FLD_COUNT, TYP_NONE }, { "hdr", FLDT_ATTR_NODE_HDR, OI(NOFF(hdr)), attr_node_hdr_count, FLD_COUNT, TYP_NONE }, { "entries", FLDT_ATTR_LEAF_ENTRY, OI(LOFF(entries)), attr_leaf_entries_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "btree", FLDT_ATTR_NODE_ENTRY, OI(NOFF(__btree)), attr_node_btree_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "nvlist", FLDT_ATTR_LEAF_NAME, attr_leaf_nvlist_offset, attr_leaf_nvlist_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { NULL } }; #define BOFF(f) bitize(offsetof(xfs_da_blkinfo_t, f)) const field_t attr_blkinfo_flds[] = { { "forw", FLDT_ATTRBLOCK, OI(BOFF(forw)), C1, 0, TYP_ATTR }, { "back", FLDT_ATTRBLOCK, OI(BOFF(back)), C1, 0, TYP_ATTR }, { "magic", FLDT_UINT16X, OI(BOFF(magic)), C1, 0, TYP_NONE }, { "pad", FLDT_UINT16X, OI(BOFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, { NULL } }; #define LEOFF(f) bitize(offsetof(xfs_attr_leaf_entry_t, f)) const field_t attr_leaf_entry_flds[] = { { "hashval", FLDT_UINT32X, OI(LEOFF(hashval)), C1, 0, TYP_NONE }, { "nameidx", FLDT_UINT16D, OI(LEOFF(nameidx)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT8X, OI(LEOFF(flags)), C1, FLD_SKIPALL, TYP_NONE }, { "incomplete", FLDT_UINT1, OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_INCOMPLETE_BIT - 1), C1, 0, TYP_NONE }, { "root", FLDT_UINT1, OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_ROOT_BIT - 1), C1, 0, TYP_NONE }, { "secure", FLDT_UINT1, OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_SECURE_BIT - 1), C1, 0, TYP_NONE }, { "local", FLDT_UINT1, OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_LOCAL_BIT - 1), C1, 0, TYP_NONE }, { "pad2", FLDT_UINT8X, OI(LEOFF(pad2)), C1, FLD_SKIPALL, TYP_NONE }, { NULL } }; #define LHOFF(f) bitize(offsetof(xfs_attr_leaf_hdr_t, f)) const field_t attr_leaf_hdr_flds[] = { { "info", FLDT_ATTR_BLKINFO, OI(LHOFF(info)), C1, 0, TYP_NONE }, { "count", FLDT_UINT16D, OI(LHOFF(count)), C1, 0, TYP_NONE }, { "usedbytes", FLDT_UINT16D, OI(LHOFF(usedbytes)), C1, 0, TYP_NONE }, { "firstused", FLDT_UINT16D, OI(LHOFF(firstused)), C1, 0, TYP_NONE }, { "holes", FLDT_UINT8D, OI(LHOFF(holes)), C1, 0, TYP_NONE }, { "pad1", FLDT_UINT8X, OI(LHOFF(pad1)), C1, FLD_SKIPALL, TYP_NONE }, { "freemap", FLDT_ATTR_LEAF_MAP, OI(LHOFF(freemap)), CI(XFS_ATTR_LEAF_MAPSIZE), FLD_ARRAY, TYP_NONE }, { NULL } }; #define LMOFF(f) bitize(offsetof(xfs_attr_leaf_map_t, f)) const field_t attr_leaf_map_flds[] = { { "base", FLDT_UINT16D, OI(LMOFF(base)), C1, 0, TYP_NONE }, { "size", FLDT_UINT16D, OI(LMOFF(size)), C1, 0, TYP_NONE }, { NULL } }; #define LNOFF(f) bitize(offsetof(xfs_attr_leaf_name_local_t, f)) #define LVOFF(f) bitize(offsetof(xfs_attr_leaf_name_remote_t, f)) const field_t attr_leaf_name_flds[] = { { "valuelen", FLDT_UINT16D, OI(LNOFF(valuelen)), attr_leaf_name_local_count, FLD_COUNT, TYP_NONE }, { "namelen", FLDT_UINT8D, OI(LNOFF(namelen)), attr_leaf_name_local_count, FLD_COUNT, TYP_NONE }, { "name", FLDT_CHARNS, OI(LNOFF(nameval)), attr_leaf_name_local_name_count, FLD_COUNT, TYP_NONE }, { "value", FLDT_CHARNS, attr_leaf_name_local_value_offset, attr_leaf_name_local_value_count, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "valueblk", FLDT_UINT32X, OI(LVOFF(valueblk)), attr_leaf_name_remote_count, FLD_COUNT, TYP_NONE }, { "valuelen", FLDT_UINT32D, OI(LVOFF(valuelen)), attr_leaf_name_remote_count, FLD_COUNT, TYP_NONE }, { "namelen", FLDT_UINT8D, OI(LVOFF(namelen)), attr_leaf_name_remote_count, FLD_COUNT, TYP_NONE }, { "name", FLDT_CHARNS, OI(LVOFF(name)), attr_leaf_name_remote_name_count, FLD_COUNT, TYP_NONE }, { NULL } }; #define EOFF(f) bitize(offsetof(xfs_da_node_entry_t, f)) const field_t attr_node_entry_flds[] = { { "hashval", FLDT_UINT32X, OI(EOFF(hashval)), C1, 0, TYP_NONE }, { "before", FLDT_ATTRBLOCK, OI(EOFF(before)), C1, 0, TYP_ATTR }, { NULL } }; #define HOFF(f) bitize(offsetof(xfs_da_node_hdr_t, f)) const field_t attr_node_hdr_flds[] = { { "info", FLDT_ATTR_BLKINFO, OI(HOFF(info)), C1, 0, TYP_NONE }, { "count", FLDT_UINT16D, OI(HOFF(__count)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(HOFF(__level)), C1, 0, TYP_NONE }, { NULL } }; static int attr_leaf_entries_count( void *obj, int startoff) { struct xfs_attr_leafblock *leaf = obj; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC) return 0; return be16_to_cpu(leaf->hdr.count); } static int attr3_leaf_entries_count( void *obj, int startoff) { struct xfs_attr3_leafblock *leaf = obj; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.hdr.magic) != XFS_ATTR3_LEAF_MAGIC) return 0; return be16_to_cpu(leaf->hdr.count); } static int attr_leaf_hdr_count( void *obj, int startoff) { struct xfs_attr_leafblock *leaf = obj; ASSERT(startoff == 0); return be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC; } static int attr3_leaf_hdr_count( void *obj, int startoff) { struct xfs_attr3_leafblock *leaf = obj; ASSERT(startoff == 0); return be16_to_cpu(leaf->hdr.info.hdr.magic) == XFS_ATTR3_LEAF_MAGIC; } typedef int (*attr_leaf_entry_walk_f)(struct xfs_attr_leafblock *, struct xfs_attr_leaf_entry *, int); static int attr_leaf_entry_walk( void *obj, int startoff, attr_leaf_entry_walk_f func) { struct xfs_attr_leafblock *leaf = obj; struct xfs_attr3_icleaf_hdr leafhdr; struct xfs_attr_leaf_entry *entries; struct xfs_attr_leaf_entry *e; int i; int off; ASSERT(bitoffs(startoff) == 0); if (be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC && be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR3_LEAF_MAGIC) return 0; off = byteize(startoff); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); entries = xfs_attr3_leaf_entryp(leaf); for (i = 0; i < leafhdr.count; i++) { e = &entries[i]; if (be16_to_cpu(e->nameidx) == off) return func(leaf, e, i); } return 0; } static int __attr_leaf_name_local_count( struct xfs_attr_leafblock *leaf, struct xfs_attr_leaf_entry *e, int i) { return (e->flags & XFS_ATTR_LOCAL) != 0; } static int attr_leaf_name_local_count( void *obj, int startoff) { return attr_leaf_entry_walk(obj, startoff, __attr_leaf_name_local_count); } static int __attr_leaf_name_local_name_count( struct xfs_attr_leafblock *leaf, struct xfs_attr_leaf_entry *e, int i) { struct xfs_attr_leaf_name_local *l; if (!(e->flags & XFS_ATTR_LOCAL)) return 0; l = xfs_attr3_leaf_name_local(leaf, i); return l->namelen; } static int attr_leaf_name_local_name_count( void *obj, int startoff) { return attr_leaf_entry_walk(obj, startoff, __attr_leaf_name_local_name_count); } static int __attr_leaf_name_local_value_count( struct xfs_attr_leafblock *leaf, struct xfs_attr_leaf_entry *e, int i) { struct xfs_attr_leaf_name_local *l; if (!(e->flags & XFS_ATTR_LOCAL)) return 0; l = xfs_attr3_leaf_name_local(leaf, i); return be16_to_cpu(l->valuelen); } static int attr_leaf_name_local_value_count( void *obj, int startoff) { return attr_leaf_entry_walk(obj, startoff, __attr_leaf_name_local_value_count); } static int __attr_leaf_name_local_value_offset( struct xfs_attr_leafblock *leaf, struct xfs_attr_leaf_entry *e, int i) { struct xfs_attr_leaf_name_local *l; char *vp; l = xfs_attr3_leaf_name_local(leaf, i); vp = (char *)&l->nameval[l->namelen]; return (int)bitize(vp - (char *)l); } static int attr_leaf_name_local_value_offset( void *obj, int startoff, int idx) { return attr_leaf_entry_walk(obj, startoff, __attr_leaf_name_local_value_offset); } static int __attr_leaf_name_remote_count( struct xfs_attr_leafblock *leaf, struct xfs_attr_leaf_entry *e, int i) { return (e->flags & XFS_ATTR_LOCAL) == 0; } static int attr_leaf_name_remote_count( void *obj, int startoff) { return attr_leaf_entry_walk(obj, startoff, __attr_leaf_name_remote_count); } static int __attr_leaf_name_remote_name_count( struct xfs_attr_leafblock *leaf, struct xfs_attr_leaf_entry *e, int i) { struct xfs_attr_leaf_name_remote *r; if (e->flags & XFS_ATTR_LOCAL) return 0; r = xfs_attr3_leaf_name_remote(leaf, i); return r->namelen; } static int attr_leaf_name_remote_name_count( void *obj, int startoff) { return attr_leaf_entry_walk(obj, startoff, __attr_leaf_name_remote_name_count); } int attr_leaf_name_size( void *obj, int startoff, int idx) { struct xfs_attr_leafblock *leaf = obj; struct xfs_attr_leaf_entry *e; struct xfs_attr_leaf_name_local *l; struct xfs_attr_leaf_name_remote *r; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC && be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR3_LEAF_MAGIC) return 0; e = &xfs_attr3_leaf_entryp(leaf)[idx]; if (e->flags & XFS_ATTR_LOCAL) { l = xfs_attr3_leaf_name_local(leaf, idx); return (int)bitize(xfs_attr_leaf_entsize_local(l->namelen, be16_to_cpu(l->valuelen))); } else { r = xfs_attr3_leaf_name_remote(leaf, idx); return (int)bitize(xfs_attr_leaf_entsize_remote(r->namelen)); } } static int attr_leaf_nvlist_count( void *obj, int startoff) { struct xfs_attr_leafblock *leaf = obj; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC) return 0; return be16_to_cpu(leaf->hdr.count); } static int attr3_leaf_nvlist_count( void *obj, int startoff) { struct xfs_attr3_leafblock *leaf = obj; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.hdr.magic) != XFS_ATTR3_LEAF_MAGIC) return 0; return be16_to_cpu(leaf->hdr.count); } static int attr_leaf_nvlist_offset( void *obj, int startoff, int idx) { struct xfs_attr_leafblock *leaf = obj; struct xfs_attr_leaf_entry *e; ASSERT(startoff == 0); e = &xfs_attr3_leaf_entryp(leaf)[idx]; return bitize(be16_to_cpu(e->nameidx)); } static int attr_node_btree_count( void *obj, int startoff) { struct xfs_da_intnode *node = obj; ASSERT(startoff == 0); /* this is a base structure */ if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) return 0; return be16_to_cpu(node->hdr.__count); } static int attr3_node_btree_count( void *obj, int startoff) { struct xfs_da3_intnode *node = obj; ASSERT(startoff == 0); if (be16_to_cpu(node->hdr.info.hdr.magic) != XFS_DA3_NODE_MAGIC) return 0; return be16_to_cpu(node->hdr.__count); } static int attr_node_hdr_count( void *obj, int startoff) { struct xfs_da_intnode *node = obj; ASSERT(startoff == 0); return be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC; } static int attr3_node_hdr_count( void *obj, int startoff) { struct xfs_da3_intnode *node = obj; ASSERT(startoff == 0); return be16_to_cpu(node->hdr.info.hdr.magic) == XFS_DA3_NODE_MAGIC; } int attr_size( void *obj, int startoff, int idx) { return bitize(mp->m_sb.sb_blocksize); } /* * CRC enabled attribute block field definitions */ const field_t attr3_hfld[] = { { "", FLDT_ATTR3, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define L3OFF(f) bitize(offsetof(struct xfs_attr3_leafblock, f)) #define N3OFF(f) bitize(offsetof(struct xfs_da3_intnode, f)) const field_t attr3_flds[] = { { "hdr", FLDT_ATTR3_LEAF_HDR, OI(L3OFF(hdr)), attr3_leaf_hdr_count, FLD_COUNT, TYP_NONE }, { "hdr", FLDT_DA3_NODE_HDR, OI(N3OFF(hdr)), attr3_node_hdr_count, FLD_COUNT, TYP_NONE }, { "entries", FLDT_ATTR_LEAF_ENTRY, OI(L3OFF(entries)), attr3_leaf_entries_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "btree", FLDT_ATTR_NODE_ENTRY, OI(N3OFF(__btree)), attr3_node_btree_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "nvlist", FLDT_ATTR_LEAF_NAME, attr_leaf_nvlist_offset, attr3_leaf_nvlist_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { NULL } }; #define LH3OFF(f) bitize(offsetof(struct xfs_attr3_leaf_hdr, f)) const field_t attr3_leaf_hdr_flds[] = { { "info", FLDT_DA3_BLKINFO, OI(LH3OFF(info)), C1, 0, TYP_NONE }, { "count", FLDT_UINT16D, OI(LH3OFF(count)), C1, 0, TYP_NONE }, { "usedbytes", FLDT_UINT16D, OI(LH3OFF(usedbytes)), C1, 0, TYP_NONE }, { "firstused", FLDT_UINT16D, OI(LH3OFF(firstused)), C1, 0, TYP_NONE }, { "holes", FLDT_UINT8D, OI(LH3OFF(holes)), C1, 0, TYP_NONE }, { "pad1", FLDT_UINT8X, OI(LH3OFF(pad1)), C1, FLD_SKIPALL, TYP_NONE }, { "freemap", FLDT_ATTR_LEAF_MAP, OI(LH3OFF(freemap)), CI(XFS_ATTR_LEAF_MAPSIZE), FLD_ARRAY, TYP_NONE }, { NULL } }; /* * Special read verifier for attribute buffers. Detect the magic number * appropriately and set the correct verifier and call it. */ static void xfs_attr3_db_read_verify( struct xfs_buf *bp) { __be32 magic32; __be16 magic16; magic32 = *(__be32 *)bp->b_addr; magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic; switch (magic16) { case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): bp->b_ops = &xfs_attr3_leaf_buf_ops; goto verify; case cpu_to_be16(XFS_DA3_NODE_MAGIC): bp->b_ops = &xfs_da3_node_buf_ops; goto verify; default: break; } switch (magic32) { case cpu_to_be32(XFS_ATTR3_RMT_MAGIC): bp->b_ops = &xfs_attr3_rmt_buf_ops; break; default: dbprintf(_("Unknown attribute buffer type!\n")); xfs_buf_ioerror(bp, -EFSCORRUPTED); return; } verify: bp->b_ops->verify_read(bp); } static void xfs_attr3_db_write_verify( struct xfs_buf *bp) { dbprintf(_("Writing unknown attribute buffer type!\n")); xfs_buf_ioerror(bp, -EFSCORRUPTED); } const struct xfs_buf_ops xfs_attr3_db_buf_ops = { .name = "xfs_attr3", .verify_read = xfs_attr3_db_read_verify, .verify_write = xfs_attr3_db_write_verify, }; xfsprogs-4.9.0+nmu1ubuntu2/db/attr.h0000644000000000000000000000263613063067170014210 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const field_t attr_flds[]; extern const field_t attr_hfld[]; extern const field_t attr_blkinfo_flds[]; extern const field_t attr_leaf_entry_flds[]; extern const field_t attr_leaf_hdr_flds[]; extern const field_t attr_leaf_map_flds[]; extern const field_t attr_leaf_name_flds[]; extern const field_t attr_node_entry_flds[]; extern const field_t attr_node_hdr_flds[]; extern const field_t attr3_flds[]; extern const field_t attr3_hfld[]; extern const field_t attr3_leaf_hdr_flds[]; extern const field_t attr3_node_hdr_flds[]; extern int attr_leaf_name_size(void *obj, int startoff, int idx); extern int attr_size(void *obj, int startoff, int idx); extern const struct xfs_buf_ops xfs_attr3_db_buf_ops; xfsprogs-4.9.0+nmu1ubuntu2/db/attrset.c0000644000000000000000000001330213063067170014707 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "attrset.h" #include "io.h" #include "output.h" #include "type.h" #include "init.h" #include "fprint.h" #include "faddr.h" #include "field.h" #include "inode.h" #include "malloc.h" static int attr_set_f(int argc, char **argv); static int attr_remove_f(int argc, char **argv); static void attrset_help(void); static const cmdinfo_t attr_set_cmd = { "attr_set", "aset", attr_set_f, 1, -1, 0, N_("[-r|-s|-p|-u] [-n] [-R|-C] [-v n] name"), N_("set the named attribute on the current inode"), attrset_help }; static const cmdinfo_t attr_remove_cmd = { "attr_remove", "aremove", attr_remove_f, 1, -1, 0, N_("[-r|-s|-p|-u] [-n] name"), N_("remove the named attribute from the current inode"), attrset_help }; static void attrset_help(void) { dbprintf(_( "\n" " The 'attr_set' and 'attr_remove' commands provide interfaces for debugging\n" " the extended attribute allocation and removal code.\n" " Both commands require an attribute name to be specified, and the attr_set\n" " command allows an optional value length (-v) to be provided as well.\n" " There are 4 namespace flags:\n" " -r -- 'root'\n" " -u -- 'user' (default)\n" " -s -- 'secure'\n" "\n" " For attr_set, these options further define the type of set operation:\n" " -C -- 'create' - create attribute, fail if it already exists\n" " -R -- 'replace' - replace attribute, fail if it does not exist\n" " The backward compatibility mode 'noattr2' can be emulated (-n) also.\n" "\n")); } void attrset_init(void) { if (!expert_mode) return; add_command(&attr_set_cmd); add_command(&attr_remove_cmd); } static int attr_set_f( int argc, char **argv) { xfs_inode_t *ip = NULL; char *name, *value, *sp; int c, valuelen = 0, flags = 0; if (cur_typ == NULL) { dbprintf(_("no current type\n")); return 0; } if (cur_typ->typnm != TYP_INODE) { dbprintf(_("current type is not inode\n")); return 0; } while ((c = getopt(argc, argv, "rusCRnv:")) != EOF) { switch (c) { /* namespaces */ case 'r': flags |= LIBXFS_ATTR_ROOT; flags &= ~LIBXFS_ATTR_SECURE; break; case 'u': flags &= ~(LIBXFS_ATTR_ROOT | LIBXFS_ATTR_SECURE); break; case 's': flags |= LIBXFS_ATTR_SECURE; flags &= ~LIBXFS_ATTR_ROOT; break; /* modifiers */ case 'C': flags |= LIBXFS_ATTR_CREATE; break; case 'R': flags |= LIBXFS_ATTR_REPLACE; break; case 'n': mp->m_flags |= LIBXFS_MOUNT_COMPAT_ATTR; break; /* value length */ case 'v': valuelen = (int)strtol(optarg, &sp, 0); if (*sp != '\0' || valuelen < 0 || valuelen > 64*1024) { dbprintf(_("bad attr_set valuelen %s\n"), optarg); return 0; } break; default: dbprintf(_("bad option for attr_set command\n")); return 0; } } if (optind != argc - 1) { dbprintf(_("too few options for attr_set (no name given)\n")); return 0; } name = argv[optind]; if (valuelen) { value = (char *)memalign(getpagesize(), valuelen); if (!value) { dbprintf(_("cannot allocate buffer (%d)\n"), valuelen); goto out; } memset(value, 'v', valuelen); } else { value = NULL; } if (libxfs_iget(mp, NULL, iocur_top->ino, 0, &ip)) { dbprintf(_("failed to iget inode %llu\n"), (unsigned long long)iocur_top->ino); goto out; } if (libxfs_attr_set(ip, (unsigned char *)name, (unsigned char *)value, valuelen, flags)) { dbprintf(_("failed to set attr %s on inode %llu\n"), name, (unsigned long long)iocur_top->ino); goto out; } /* refresh with updated inode contents */ set_cur_inode(iocur_top->ino); out: mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR; if (ip) IRELE(ip); if (value) free(value); return 0; } static int attr_remove_f( int argc, char **argv) { xfs_inode_t *ip = NULL; char *name; int c, flags = 0; if (cur_typ == NULL) { dbprintf(_("no current type\n")); return 0; } if (cur_typ->typnm != TYP_INODE) { dbprintf(_("current type is not inode\n")); return 0; } while ((c = getopt(argc, argv, "rusn")) != EOF) { switch (c) { /* namespaces */ case 'r': flags |= LIBXFS_ATTR_ROOT; flags &= ~LIBXFS_ATTR_SECURE; break; case 'u': flags &= ~(LIBXFS_ATTR_ROOT | LIBXFS_ATTR_SECURE); break; case 's': flags |= LIBXFS_ATTR_SECURE; flags &= ~LIBXFS_ATTR_ROOT; break; case 'n': mp->m_flags |= LIBXFS_MOUNT_COMPAT_ATTR; break; default: dbprintf(_("bad option for attr_remove command\n")); return 0; } } if (optind != argc - 1) { dbprintf(_("too few options for attr_remove (no name given)\n")); return 0; } name = argv[optind]; if (libxfs_iget(mp, NULL, iocur_top->ino, 0, &ip)) { dbprintf(_("failed to iget inode %llu\n"), (unsigned long long)iocur_top->ino); goto out; } if (libxfs_attr_remove(ip, (unsigned char *)name, flags)) { dbprintf(_("failed to remove attr %s from inode %llu\n"), name, (unsigned long long)iocur_top->ino); goto out; } /* refresh with updated inode contents */ set_cur_inode(iocur_top->ino); out: mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR; if (ip) IRELE(ip); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/db/attrset.h0000644000000000000000000000135613063067167014730 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void attrset_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/attrshort.c0000644000000000000000000001074013063067170015256 0ustar /* * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "bit.h" #include "attrshort.h" static int attr_sf_entry_name_count(void *obj, int startoff); static int attr_sf_entry_value_count(void *obj, int startoff); static int attr_sf_entry_value_offset(void *obj, int startoff, int idx); static int attr_shortform_list_count(void *obj, int startoff); static int attr_shortform_list_offset(void *obj, int startoff, int idx); #define OFF(f) bitize(offsetof(xfs_attr_shortform_t, f)) const field_t attr_shortform_flds[] = { { "hdr", FLDT_ATTR_SF_HDR, OI(OFF(hdr)), C1, 0, TYP_NONE }, { "list", FLDT_ATTR_SF_ENTRY, attr_shortform_list_offset, attr_shortform_list_count, FLD_ARRAY|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { NULL } }; #define HOFF(f) bitize(offsetof(xfs_attr_sf_hdr_t, f)) const field_t attr_sf_hdr_flds[] = { { "totsize", FLDT_UINT16D, OI(HOFF(totsize)), C1, 0, TYP_NONE }, { "count", FLDT_UINT8D, OI(HOFF(count)), C1, 0, TYP_NONE }, { NULL } }; #define EOFF(f) bitize(offsetof(xfs_attr_sf_entry_t, f)) const field_t attr_sf_entry_flds[] = { { "namelen", FLDT_UINT8D, OI(EOFF(namelen)), C1, 0, TYP_NONE }, { "valuelen", FLDT_UINT8D, OI(EOFF(valuelen)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT8X, OI(EOFF(flags)), C1, FLD_SKIPALL, TYP_NONE }, { "root", FLDT_UINT1, OI(EOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_ROOT_BIT - 1), C1, 0, TYP_NONE }, { "secure", FLDT_UINT1, OI(EOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_SECURE_BIT - 1), C1, 0, TYP_NONE }, { "name", FLDT_CHARNS, OI(EOFF(nameval)), attr_sf_entry_name_count, FLD_COUNT, TYP_NONE }, { "value", FLDT_CHARNS, attr_sf_entry_value_offset, attr_sf_entry_value_count, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { NULL } }; static int attr_sf_entry_name_count( void *obj, int startoff) { xfs_attr_sf_entry_t *e; ASSERT(bitoffs(startoff) == 0); e = (xfs_attr_sf_entry_t *)((char *)obj + byteize(startoff)); return e->namelen; } int attr_sf_entry_size( void *obj, int startoff, int idx) { xfs_attr_sf_entry_t *e; int i; xfs_attr_shortform_t *sf; ASSERT(bitoffs(startoff) == 0); sf = (xfs_attr_shortform_t *)((char *)obj + byteize(startoff)); e = &sf->list[0]; for (i = 0; i < idx; i++) e = XFS_ATTR_SF_NEXTENTRY(e); return bitize((int)XFS_ATTR_SF_ENTSIZE(e)); } static int attr_sf_entry_value_count( void *obj, int startoff) { xfs_attr_sf_entry_t *e; ASSERT(bitoffs(startoff) == 0); e = (xfs_attr_sf_entry_t *)((char *)obj + byteize(startoff)); return e->valuelen; } /*ARGSUSED*/ static int attr_sf_entry_value_offset( void *obj, int startoff, int idx) { xfs_attr_sf_entry_t *e; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); e = (xfs_attr_sf_entry_t *)((char *)obj + byteize(startoff)); return bitize((int)((char *)&e->nameval[e->namelen] - (char *)e)); } static int attr_shortform_list_count( void *obj, int startoff) { xfs_attr_shortform_t *sf; ASSERT(bitoffs(startoff) == 0); sf = (xfs_attr_shortform_t *)((char *)obj + byteize(startoff)); return sf->hdr.count; } static int attr_shortform_list_offset( void *obj, int startoff, int idx) { xfs_attr_sf_entry_t *e; int i; xfs_attr_shortform_t *sf; ASSERT(bitoffs(startoff) == 0); sf = (xfs_attr_shortform_t *)((char *)obj + byteize(startoff)); e = &sf->list[0]; for (i = 0; i < idx; i++) e = XFS_ATTR_SF_NEXTENTRY(e); return bitize((int)((char *)e - (char *)sf)); } /*ARGSUSED*/ int attrshort_size( void *obj, int startoff, int idx) { xfs_attr_sf_entry_t *e; int i; xfs_attr_shortform_t *sf; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); sf = (xfs_attr_shortform_t *)((char *)obj + byteize(startoff)); e = &sf->list[0]; for (i = 0; i < sf->hdr.count; i++) e = XFS_ATTR_SF_NEXTENTRY(e); return bitize((int)((char *)e - (char *)sf)); } xfsprogs-4.9.0+nmu1ubuntu2/db/attrshort.h0000644000000000000000000000177613063067170015274 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const field_t attr_sf_entry_flds[]; extern const field_t attr_sf_hdr_flds[]; extern const field_t attr_shortform_flds[]; extern const field_t attrshort_hfld[]; extern int attr_sf_entry_size(void *obj, int startoff, int idx); extern int attrshort_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/bit.c0000644000000000000000000000767713063067167014027 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "bit.h" #undef setbit /* defined in param.h on Linux */ static int getbit(char *ptr, int bit); static void setbit(char *ptr, int bit, int val); static int getbit( char *ptr, int bit) { int mask; int shift; ptr += byteize(bit); bit = bitoffs(bit); shift = 7 - bit; mask = 1 << shift; return (*ptr & mask) >> shift; } static void setbit( char *ptr, int bit, int val) { int mask; int shift; ptr += byteize(bit); bit = bitoffs(bit); shift = 7 - bit; mask = (1 << shift); if (val) { *ptr |= mask; } else { mask = ~mask; *ptr &= mask; } } __int64_t getbitval( void *obj, int bitoff, int nbits, int flags) { int bit; int i; char *p; __int64_t rval; int signext; int z1, z2, z3, z4; ASSERT(nbits<=64); p = (char *)obj + byteize(bitoff); bit = bitoffs(bitoff); signext = (flags & BVSIGNED) != 0; z4 = ((intptr_t)p & 0xf) == 0 && bit == 0; if (nbits == 64 && z4) return be64_to_cpu(*(__be64 *)p); z3 = ((intptr_t)p & 0x7) == 0 && bit == 0; if (nbits == 32 && z3) { if (signext) return (__s32)be32_to_cpu(*(__be32 *)p); else return (__u32)be32_to_cpu(*(__be32 *)p); } z2 = ((intptr_t)p & 0x3) == 0 && bit == 0; if (nbits == 16 && z2) { if (signext) return (__s16)be16_to_cpu(*(__be16 *)p); else return (__u16)be16_to_cpu(*(__be16 *)p); } z1 = ((intptr_t)p & 0x1) == 0 && bit == 0; if (nbits == 8 && z1) { if (signext) return *(__s8 *)p; else return *(__u8 *)p; } for (i = 0, rval = 0LL; i < nbits; i++) { if (getbit(p, bit + i)) { /* If the last bit is on and we care about sign * bits and we don't have a full 64 bit * container, turn all bits on between the * sign bit and the most sig bit. */ /* handle endian swap here */ #if __BYTE_ORDER == LITTLE_ENDIAN if (i == 0 && signext && nbits < 64) rval = -1LL << nbits; rval |= 1LL << (nbits - i - 1); #else if ((i == (nbits - 1)) && signext && nbits < 64) rval |= (-1LL << nbits); rval |= 1LL << (nbits - i - 1); #endif } } return rval; } /* * The input data can be 8, 16, 32, and 64 sized numeric values * aligned on a byte boundry, or odd sized numbers stored on odd * aligned offset (for example the bmbt fields). * * The input data sent to this routine has been converted to big endian * and has been adjusted in the array so that the first input bit is to * be written in the first bit in the output. * * If the field length and the output buffer are byte aligned, then use * memcpy from the input to the output, but if either entries are not byte * aligned, then loop over the entire bit range reading the input value * and set/clear the matching bit in the output. * * example when ibuf is not multiple of a byte in length: * * ibuf: | BBBBBBBB | bbbxxxxx | * \\\\\\\\--\\\\ * obuf+bitoff: | xBBBBBBB | Bbbbxxxx | * */ void setbitval( void *obuf, /* start of buffer to write into */ int bitoff, /* bit offset into the output buffer */ int nbits, /* number of bits to write */ void *ibuf) /* source bits */ { char *in = ibuf; char *out = obuf; int bit; if (bitoff % NBBY || nbits % NBBY) { for (bit = 0; bit < nbits; bit++) setbit(out, bit + bitoff, getbit(in, bit)); } else memcpy(out + byteize(bitoff), in, byteize(nbits)); } xfsprogs-4.9.0+nmu1ubuntu2/db/bit.h0000644000000000000000000000210613063067170014004 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define bitize(s) ((s) * NBBY) #define bitsz(t) bitize(sizeof(t)) #define bitszof(x,y) bitize(szof(x,y)) #define byteize(s) ((s) / NBBY) #define bitoffs(s) ((s) % NBBY) #define BVUNSIGNED 0 #define BVSIGNED 1 extern __int64_t getbitval(void *obj, int bitoff, int nbits, int flags); extern void setbitval(void *obuf, int bitoff, int nbits, void *ibuf); xfsprogs-4.9.0+nmu1ubuntu2/db/block.c0000644000000000000000000001473113063067167014330 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "block.h" #include "bmap.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "inode.h" #include "io.h" #include "output.h" #include "init.h" static int ablock_f(int argc, char **argv); static void ablock_help(void); static int daddr_f(int argc, char **argv); static void daddr_help(void); static int dblock_f(int argc, char **argv); static void dblock_help(void); static int fsblock_f(int argc, char **argv); static void fsblock_help(void); static void print_rawdata(void *data, int len); static const cmdinfo_t ablock_cmd = { "ablock", NULL, ablock_f, 1, 1, 1, N_("filoff"), N_("set address to file offset (attr fork)"), ablock_help }; static const cmdinfo_t daddr_cmd = { "daddr", NULL, daddr_f, 0, 1, 1, N_("[d]"), N_("set address to daddr value"), daddr_help }; static const cmdinfo_t dblock_cmd = { "dblock", NULL, dblock_f, 1, 1, 1, N_("filoff"), N_("set address to file offset (data fork)"), dblock_help }; static const cmdinfo_t fsblock_cmd = { "fsblock", "fsb", fsblock_f, 0, 1, 1, N_("[fsb]"), N_("set address to fsblock value"), fsblock_help }; static void ablock_help(void) { dbprintf(_( "\n Example:\n" "\n" " 'ablock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's attribute fork. The filesystem block size is specified in\n" " the superblock.\n\n" )); } /*ARGSUSED*/ static int ablock_f( int argc, char **argv) { bmap_ext_t bm; xfs_fileoff_t bno; xfs_fsblock_t dfsbno; int haveattr; int nex; char *p; bno = (xfs_fileoff_t)strtoull(argv[1], &p, 0); if (*p != '\0') { dbprintf(_("bad block number %s\n"), argv[1]); return 0; } push_cur(); set_cur_inode(iocur_top->ino); haveattr = XFS_DFORK_Q((xfs_dinode_t *)iocur_top->data); pop_cur(); if (!haveattr) { dbprintf(_("no attribute data for file\n")); return 0; } nex = 1; bmap(bno, 1, XFS_ATTR_FORK, &nex, &bm); if (nex == 0) { dbprintf(_("file attr block is unmapped\n")); return 0; } dfsbno = bm.startblock + (bno - bm.startoff); ASSERT(typtab[TYP_ATTR].typnm == TYP_ATTR); set_cur(&typtab[TYP_ATTR], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), blkbb, DB_RING_ADD, NULL); return 0; } void block_init(void) { add_command(&ablock_cmd); add_command(&daddr_cmd); add_command(&dblock_cmd); add_command(&fsblock_cmd); } static void daddr_help(void) { dbprintf(_( "\n Example:\n" "\n" " 'daddr 102' - sets position to the 102nd absolute disk block\n" " (512 byte block).\n" )); } static int daddr_f( int argc, char **argv) { __int64_t d; char *p; if (argc == 1) { dbprintf(_("current daddr is %lld\n"), iocur_top->off >> BBSHIFT); return 0; } d = (__int64_t)strtoull(argv[1], &p, 0); if (*p != '\0' || d >= mp->m_sb.sb_dblocks << (mp->m_sb.sb_blocklog - BBSHIFT)) { dbprintf(_("bad daddr %s\n"), argv[1]); return 0; } ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); set_cur(&typtab[TYP_DATA], d, 1, DB_RING_ADD, NULL); return 0; } static void dblock_help(void) { dbprintf(_( "\n Example:\n" "\n" " 'dblock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's data fork. The filesystem block size is specified in the\n" " superblock.\n\n" )); } static int dblock_f( int argc, char **argv) { bbmap_t bbmap; bmap_ext_t *bmp; xfs_fileoff_t bno; xfs_fsblock_t dfsbno; int nb; int nex; char *p; typnm_t type; bno = (xfs_fileoff_t)strtoull(argv[1], &p, 0); if (*p != '\0') { dbprintf(_("bad block number %s\n"), argv[1]); return 0; } push_cur(); set_cur_inode(iocur_top->ino); type = inode_next_type(); pop_cur(); if (type == TYP_NONE) { dbprintf(_("no type for file data\n")); return 0; } nex = nb = type == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1; bmp = malloc(nb * sizeof(*bmp)); bmap(bno, nb, XFS_DATA_FORK, &nex, bmp); if (nex == 0) { dbprintf(_("file data block is unmapped\n")); free(bmp); return 0; } dfsbno = bmp->startblock + (bno - bmp->startoff); ASSERT(typtab[type].typnm == type); if (nex > 1) make_bbmap(&bbmap, nex, bmp); set_cur(&typtab[type], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), nb * blkbb, DB_RING_ADD, nex > 1 ? &bbmap : NULL); free(bmp); return 0; } static void fsblock_help(void) { dbprintf(_( "\n Example:\n" "\n" " 'fsblock 1023' - sets the file position to the 1023rd filesystem block.\n" " The filesystem block size is specified in the superblock and set during\n" " mkfs time. Offset is absolute (not AG relative).\n\n" )); } static int fsblock_f( int argc, char **argv) { xfs_agblock_t agbno; xfs_agnumber_t agno; xfs_fsblock_t d; char *p; if (argc == 1) { dbprintf(_("current fsblock is %lld\n"), XFS_DADDR_TO_FSB(mp, iocur_top->off >> BBSHIFT)); return 0; } d = strtoull(argv[1], &p, 0); if (*p != '\0') { dbprintf(_("bad fsblock %s\n"), argv[1]); return 0; } agno = XFS_FSB_TO_AGNO(mp, d); agbno = XFS_FSB_TO_AGBNO(mp, d); if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks) { dbprintf(_("bad fsblock %s\n"), argv[1]); return 0; } ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); set_cur(&typtab[TYP_DATA], XFS_AGB_TO_DADDR(mp, agno, agbno), blkbb, DB_RING_ADD, NULL); return 0; } void print_block( const field_t *fields, int argc, char **argv) { print_rawdata(iocur_top->data, iocur_top->len); } static void print_rawdata( void *data, int len) { int i; int j; int lastaddr; int offchars; unsigned char *p; lastaddr = (len - 1) & ~(32 - 1); if (lastaddr < 0x10) offchars = 1; else if (lastaddr < 0x100) offchars = 2; else if (lastaddr < 0x1000) offchars = 3; else offchars = 4; for (i = 0, p = data; i < len; i += 32) { dbprintf("%-0*.*x:", offchars, offchars, i); for (j = 0; j < 32 && i + j < len; j++, p++) { if ((j & 3) == 0) dbprintf(" "); dbprintf("%02x", *p); } dbprintf("\n"); } } xfsprogs-4.9.0+nmu1ubuntu2/db/block.h0000644000000000000000000000152113063067170014320 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ struct field; extern void block_init(void); extern void print_block(const struct field *fields, int argc, char **argv); xfsprogs-4.9.0+nmu1ubuntu2/db/bmap.c0000644000000000000000000001646613063067170014156 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "type.h" #include "fprint.h" #include "faddr.h" #include "field.h" #include "bmap.h" #include "io.h" #include "inode.h" #include "output.h" #include "init.h" static int bmap_f(int argc, char **argv); static int bmap_one_extent(xfs_bmbt_rec_t *ep, xfs_fileoff_t *offp, xfs_fileoff_t eoff, int *idxp, bmap_ext_t *bep); static xfs_fsblock_t select_child(xfs_fileoff_t off, xfs_bmbt_key_t *kp, xfs_bmbt_ptr_t *pp, int nrecs); static const cmdinfo_t bmap_cmd = { "bmap", NULL, bmap_f, 0, 3, 0, N_("[-ad] [block [len]]"), N_("show block map for current file"), NULL }; void bmap( xfs_fileoff_t offset, xfs_filblks_t len, int whichfork, int *nexp, bmap_ext_t *bep) { struct xfs_btree_block *block; xfs_fsblock_t bno; xfs_fileoff_t curoffset; xfs_dinode_t *dip; xfs_fileoff_t eoffset; xfs_bmbt_rec_t *ep; xfs_dinode_fmt_t fmt; int fsize; xfs_bmbt_key_t *kp; int n; int nex; xfs_fsblock_t nextbno; int nextents; xfs_bmbt_ptr_t *pp; xfs_bmdr_block_t *rblock; typnm_t typ; xfs_bmbt_rec_t *xp; push_cur(); set_cur_inode(iocur_top->ino); nex = *nexp; *nexp = 0; ASSERT(nex > 0); dip = iocur_top->data; n = 0; eoffset = offset + len - 1; curoffset = offset; fmt = (xfs_dinode_fmt_t)XFS_DFORK_FORMAT(dip, whichfork); typ = whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA; ASSERT(typtab[typ].typnm == typ); ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS || fmt == XFS_DINODE_FMT_BTREE); if (fmt == XFS_DINODE_FMT_EXTENTS) { nextents = XFS_DFORK_NEXTENTS(dip, whichfork); xp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork); for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep)) break; } } else if (fmt == XFS_DINODE_FMT_BTREE) { push_cur(); rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); fsize = XFS_DFORK_SIZE(dip, mp, whichfork); pp = XFS_BMDR_PTR_ADDR(rblock, 1, libxfs_bmdr_maxrecs(fsize, 0)); kp = XFS_BMDR_KEY_ADDR(rblock, 1); bno = select_child(curoffset, kp, pp, be16_to_cpu(rblock->bb_numrecs)); for (;;) { set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_IGN, NULL); block = (struct xfs_btree_block *)iocur_top->data; if (be16_to_cpu(block->bb_level) == 0) break; pp = XFS_BMBT_PTR_ADDR(mp, block, 1, libxfs_bmbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0)); kp = XFS_BMBT_KEY_ADDR(mp, block, 1); bno = select_child(curoffset, kp, pp, be16_to_cpu(block->bb_numrecs)); } for (;;) { nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); nextents = be16_to_cpu(block->bb_numrecs); xp = (xfs_bmbt_rec_t *) XFS_BMBT_REC_ADDR(mp, block, 1); for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep)) { nextbno = NULLFSBLOCK; break; } } bno = nextbno; if (bno == NULLFSBLOCK) break; set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_IGN, NULL); block = (struct xfs_btree_block *)iocur_top->data; } pop_cur(); } pop_cur(); *nexp = n; } static int bmap_f( int argc, char **argv) { int afork = 0; bmap_ext_t be; int c; xfs_fileoff_t co, cosave; int dfork = 0; xfs_dinode_t *dip; xfs_fileoff_t eo; xfs_filblks_t len; int nex; char *p; int whichfork; if (iocur_top->ino == NULLFSINO) { dbprintf(_("no current inode\n")); return 0; } optind = 0; if (argc) while ((c = getopt(argc, argv, "ad")) != EOF) { switch (c) { case 'a': afork = 1; break; case 'd': dfork = 1; break; default: dbprintf(_("bad option for bmap command\n")); return 0; } } if (afork + dfork == 0) { push_cur(); set_cur_inode(iocur_top->ino); dip = iocur_top->data; if (be32_to_cpu(dip->di_nextents)) dfork = 1; if (be16_to_cpu(dip->di_anextents)) afork = 1; pop_cur(); } if (optind < argc) { co = (xfs_fileoff_t)strtoull(argv[optind], &p, 0); if (*p != '\0') { dbprintf(_("bad block number for bmap %s\n"), argv[optind]); return 0; } optind++; if (optind < argc) { len = (xfs_filblks_t)strtoull(argv[optind], &p, 0); if (*p != '\0') { dbprintf(_("bad len for bmap %s\n"), argv[optind]); return 0; } eo = co + len - 1; } else eo = co; } else { co = 0; eo = -1; } cosave = co; for (whichfork = XFS_DATA_FORK; whichfork <= XFS_ATTR_FORK; whichfork++) { if (whichfork == XFS_DATA_FORK && !dfork) continue; if (whichfork == XFS_ATTR_FORK && !afork) continue; for (;;) { nex = 1; bmap(co, eo - co + 1, whichfork, &nex, &be); if (nex == 0) break; dbprintf(_("%s offset %lld startblock %llu (%u/%u) count " "%llu flag %u\n"), whichfork == XFS_DATA_FORK ? _("data") : _("attr"), be.startoff, be.startblock, XFS_FSB_TO_AGNO(mp, be.startblock), XFS_FSB_TO_AGBNO(mp, be.startblock), be.blockcount, be.flag); co = be.startoff + be.blockcount; } co = cosave; } return 0; } void bmap_init(void) { add_command(&bmap_cmd); } static int bmap_one_extent( xfs_bmbt_rec_t *ep, xfs_fileoff_t *offp, xfs_fileoff_t eoff, int *idxp, bmap_ext_t *bep) { xfs_filblks_t c; xfs_fileoff_t curoffset; int f; int idx; xfs_fileoff_t o; xfs_fsblock_t s; convert_extent(ep, &o, &s, &c, &f); curoffset = *offp; idx = *idxp; if (o + c <= curoffset) return 1; if (o > eoff) return 0; if (o < curoffset) { c -= curoffset - o; s += curoffset - o; o = curoffset; } if (o + c - 1 > eoff) c -= (o + c - 1) - eoff; bep[idx].startoff = o; bep[idx].startblock = s; bep[idx].blockcount = c; bep[idx].flag = f; *idxp = idx + 1; *offp = o + c; return 1; } void convert_extent( xfs_bmbt_rec_t *rp, xfs_fileoff_t *op, xfs_fsblock_t *sp, xfs_filblks_t *cp, int *fp) { struct xfs_bmbt_irec irec; libxfs_bmbt_disk_get_all(rp, &irec); *fp = irec.br_state == XFS_EXT_UNWRITTEN; *op = irec.br_startoff; *sp = irec.br_startblock; *cp = irec.br_blockcount; } void make_bbmap( bbmap_t *bbmap, int nex, bmap_ext_t *bmp) { int i; for (i = 0; i < nex; i++) { bbmap->b[i].bm_bn = XFS_FSB_TO_DADDR(mp, bmp[i].startblock); bbmap->b[i].bm_len = XFS_FSB_TO_BB(mp, bmp[i].blockcount); } bbmap->nmaps = nex; } static xfs_fsblock_t select_child( xfs_fileoff_t off, xfs_bmbt_key_t *kp, xfs_bmbt_ptr_t *pp, int nrecs) { int i; for (i = 0; i < nrecs; i++) { if (be64_to_cpu(kp[i].br_startoff) == off) return be64_to_cpu(pp[i]); if (be64_to_cpu(kp[i].br_startoff) > off) { if (i == 0) return be64_to_cpu(pp[i]); else return be64_to_cpu(pp[i - 1]); } } return be64_to_cpu(pp[nrecs - 1]); } xfsprogs-4.9.0+nmu1ubuntu2/db/bmap.h0000644000000000000000000000232213063067170014145 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ struct bbmap; struct xfs_bmbt_rec; typedef struct bmap_ext { xfs_fileoff_t startoff; xfs_fsblock_t startblock; xfs_filblks_t blockcount; int flag; } bmap_ext_t; extern void bmap(xfs_fileoff_t offset, xfs_filblks_t len, int whichfork, int *nexp, bmap_ext_t *bep); extern void bmap_init(void); extern void convert_extent(struct xfs_bmbt_rec *rp, xfs_fileoff_t *op, xfs_fsblock_t *sp, xfs_filblks_t *cp, int *fp); extern void make_bbmap(struct bbmap *bbmap, int nex, bmap_ext_t *bmp); xfsprogs-4.9.0+nmu1ubuntu2/db/bmroot.c0000644000000000000000000001523413063067170014531 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "bmroot.h" #include "io.h" #include "print.h" #include "bit.h" #include "init.h" static int bmroota_key_count(void *obj, int startoff); static int bmroota_key_offset(void *obj, int startoff, int idx); static int bmroota_ptr_count(void *obj, int startoff); static int bmroota_ptr_offset(void *obj, int startoff, int idx); static int bmrootd_key_count(void *obj, int startoff); static int bmrootd_key_offset(void *obj, int startoff, int idx); static int bmrootd_ptr_count(void *obj, int startoff); static int bmrootd_ptr_offset(void *obj, int startoff, int idx); #define OFF(f) bitize(offsetof(xfs_bmdr_block_t, bb_ ## f)) const field_t bmroota_flds[] = { { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "keys", FLDT_BMROOTAKEY, bmroota_key_offset, bmroota_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BMROOTAPTR, bmroota_ptr_offset, bmroota_ptr_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BMAPBTA }, { NULL } }; const field_t bmrootd_flds[] = { { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "keys", FLDT_BMROOTDKEY, bmrootd_key_offset, bmrootd_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BMROOTDPTR, bmrootd_ptr_offset, bmrootd_ptr_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BMAPBTD }, { NULL } }; #define KOFF(f) bitize(offsetof(xfs_bmdr_key_t, br_ ## f)) const field_t bmroota_key_flds[] = { { "startoff", FLDT_DFILOFFA, OI(KOFF(startoff)), C1, 0, TYP_NONE }, { NULL } }; const field_t bmrootd_key_flds[] = { { "startoff", FLDT_DFILOFFD, OI(KOFF(startoff)), C1, 0, TYP_NONE }, { NULL } }; static int bmroota_key_count( void *obj, int startoff) { xfs_bmdr_block_t *block; #ifdef DEBUG xfs_dinode_t *dip = obj; #endif ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(XFS_DFORK_Q(dip) && (char *)block == XFS_DFORK_APTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); return be16_to_cpu(block->bb_numrecs); } static int bmroota_key_offset( void *obj, int startoff, int idx) { xfs_bmdr_block_t *block; #ifdef DEBUG xfs_dinode_t *dip = obj; #endif xfs_bmdr_key_t *kp; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(XFS_DFORK_Q(dip) && (char *)block == XFS_DFORK_APTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); kp = XFS_BMDR_KEY_ADDR(block, idx); return bitize((int)((char *)kp - (char *)block)); } static int bmroota_ptr_count( void *obj, int startoff) { xfs_bmdr_block_t *block; #ifdef DEBUG xfs_dinode_t *dip = obj; #endif ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(XFS_DFORK_Q(dip) && (char *)block == XFS_DFORK_APTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); return be16_to_cpu(block->bb_numrecs); } static int bmroota_ptr_offset( void *obj, int startoff, int idx) { xfs_bmdr_block_t *block; xfs_dinode_t *dip; xfs_bmdr_ptr_t *pp; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(XFS_DFORK_Q(dip) && (char *)block == XFS_DFORK_APTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); pp = XFS_BMDR_PTR_ADDR(block, idx, libxfs_bmdr_maxrecs(XFS_DFORK_ASIZE(dip, mp), 0)); return bitize((int)((char *)pp - (char *)block)); } int bmroota_size( void *obj, int startoff, int idx) { xfs_dinode_t *dip; #ifdef DEBUG xfs_bmdr_block_t *block; #endif ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); ASSERT(idx == 0); dip = obj; #ifdef DEBUG block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(XFS_DFORK_Q(dip) && (char *)block == XFS_DFORK_APTR(dip)); #endif return bitize((int)XFS_DFORK_ASIZE(dip, mp)); } static int bmrootd_key_count( void *obj, int startoff) { xfs_bmdr_block_t *block; #ifdef DEBUG xfs_dinode_t *dip = obj; #endif ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT((char *)block == XFS_DFORK_DPTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); return be16_to_cpu(block->bb_numrecs); } static int bmrootd_key_offset( void *obj, int startoff, int idx) { xfs_bmdr_block_t *block; xfs_bmdr_key_t *kp; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(be16_to_cpu(block->bb_level) > 0); kp = XFS_BMDR_KEY_ADDR(block, idx); return bitize((int)((char *)kp - (char *)block)); } static int bmrootd_ptr_count( void *obj, int startoff) { xfs_bmdr_block_t *block; #ifdef DEBUG xfs_dinode_t *dip = obj; #endif ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT((char *)block == XFS_DFORK_DPTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); return be16_to_cpu(block->bb_numrecs); } static int bmrootd_ptr_offset( void *obj, int startoff, int idx) { xfs_bmdr_block_t *block; xfs_bmdr_ptr_t *pp; xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(be16_to_cpu(block->bb_level) > 0); pp = XFS_BMDR_PTR_ADDR(block, idx, libxfs_bmdr_maxrecs(XFS_DFORK_DSIZE(dip, mp), 0)); return bitize((int)((char *)pp - (char *)block)); } int bmrootd_size( void *obj, int startoff, int idx) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); ASSERT(idx == 0); dip = obj; return bitize((int)XFS_DFORK_DSIZE(dip, mp)); } xfsprogs-4.9.0+nmu1ubuntu2/db/bmroot.h0000644000000000000000000000177713063067170014545 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field bmroota_flds[]; extern const struct field bmroota_key_flds[]; extern const struct field bmrootd_flds[]; extern const struct field bmrootd_key_flds[]; extern int bmroota_size(void *obj, int startoff, int idx); extern int bmrootd_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/btblock.c0000644000000000000000000006503613063067170014654 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "btblock.h" #include "print.h" #include "bit.h" #include "init.h" /* * Definition of the possible btree block layouts. */ struct xfs_db_btree { uint32_t magic; size_t block_len; size_t key_len; size_t rec_len; size_t ptr_len; } btrees[] = { { XFS_BMAP_MAGIC, XFS_BTREE_LBLOCK_LEN, sizeof(xfs_bmbt_key_t), sizeof(xfs_bmbt_rec_t), sizeof(__be64), }, { XFS_ABTB_MAGIC, XFS_BTREE_SBLOCK_LEN, sizeof(xfs_alloc_key_t), sizeof(xfs_alloc_rec_t), sizeof(__be32), }, { XFS_ABTC_MAGIC, XFS_BTREE_SBLOCK_LEN, sizeof(xfs_alloc_key_t), sizeof(xfs_alloc_rec_t), sizeof(__be32), }, { XFS_IBT_MAGIC, XFS_BTREE_SBLOCK_LEN, sizeof(xfs_inobt_key_t), sizeof(xfs_inobt_rec_t), sizeof(__be32), }, { XFS_FIBT_MAGIC, XFS_BTREE_SBLOCK_LEN, sizeof(xfs_inobt_key_t), sizeof(xfs_inobt_rec_t), sizeof(__be32), }, { XFS_BMAP_CRC_MAGIC, XFS_BTREE_LBLOCK_CRC_LEN, sizeof(xfs_bmbt_key_t), sizeof(xfs_bmbt_rec_t), sizeof(__be64), }, { XFS_ABTB_CRC_MAGIC, XFS_BTREE_SBLOCK_CRC_LEN, sizeof(xfs_alloc_key_t), sizeof(xfs_alloc_rec_t), sizeof(__be32), }, { XFS_ABTC_CRC_MAGIC, XFS_BTREE_SBLOCK_CRC_LEN, sizeof(xfs_alloc_key_t), sizeof(xfs_alloc_rec_t), sizeof(__be32), }, { XFS_IBT_CRC_MAGIC, XFS_BTREE_SBLOCK_CRC_LEN, sizeof(xfs_inobt_key_t), sizeof(xfs_inobt_rec_t), sizeof(__be32), }, { XFS_FIBT_CRC_MAGIC, XFS_BTREE_SBLOCK_CRC_LEN, sizeof(xfs_inobt_key_t), sizeof(xfs_inobt_rec_t), sizeof(__be32), }, { XFS_RMAP_CRC_MAGIC, XFS_BTREE_SBLOCK_CRC_LEN, 2 * sizeof(struct xfs_rmap_key), sizeof(struct xfs_rmap_rec), sizeof(__be32), }, { XFS_REFC_CRC_MAGIC, XFS_BTREE_SBLOCK_CRC_LEN, sizeof(struct xfs_refcount_key), sizeof(struct xfs_refcount_rec), sizeof(__be32), }, { 0, }, }; /* * Find the right block defintion for a given ondisk block. * * We use the least significant bit of the magic number as index into * the array of block defintions. */ static struct xfs_db_btree * block_to_bt( struct xfs_btree_block *bb) { struct xfs_db_btree *btp = &btrees[0]; do { if (be32_to_cpu((bb)->bb_magic) == btp->magic) return btp; btp++; } while (btp->magic != 0); return NULL; } /* calculate max records. Only for non-leaves. */ static int btblock_maxrecs(struct xfs_db_btree *bt, int blocksize) { blocksize -= bt->block_len; return blocksize / (bt->key_len + bt->ptr_len); } /* * Get the number of keys in a btree block. * * Note: can also be used to get the number of ptrs because there are * always the same number of keys and ptrs in a block. */ static int btblock_key_count( void *obj, int startoff) { struct xfs_btree_block *block = obj; ASSERT(startoff == 0); if (block->bb_level == 0) return 0; return be16_to_cpu(block->bb_numrecs); } /* * Get the number of keys in a btree block. */ static int btblock_rec_count( void *obj, int startoff) { struct xfs_btree_block *block = obj; ASSERT(startoff == 0); if (block->bb_level != 0) return 0; return be16_to_cpu(block->bb_numrecs); } /* * Get the offset of the key at idx in a btree block. */ static int btblock_key_offset( void *obj, int startoff, int idx) { struct xfs_btree_block *block = obj; struct xfs_db_btree *bt = block_to_bt(block); int offset; ASSERT(startoff == 0); ASSERT(block->bb_level != 0); offset = bt->block_len + (idx - 1) * bt->key_len; return bitize(offset); } /* * Get the offset of the ptr at idx in a btree block. */ static int btblock_ptr_offset( void *obj, int startoff, int idx) { struct xfs_btree_block *block = obj; struct xfs_db_btree *bt = block_to_bt(block); int offset; int maxrecs; ASSERT(startoff == 0); ASSERT(block->bb_level != 0); maxrecs = btblock_maxrecs(bt, mp->m_sb.sb_blocksize); offset = bt->block_len + maxrecs * bt->key_len + (idx - 1) * bt->ptr_len; return bitize(offset); } /* * Get the offset of the record at idx in a btree block. */ static int btblock_rec_offset( void *obj, int startoff, int idx) { struct xfs_btree_block *block = obj; struct xfs_db_btree *bt = block_to_bt(block); int offset; ASSERT(startoff == 0); ASSERT(block->bb_level == 0); offset = bt->block_len + (idx - 1) * bt->rec_len; return bitize(offset); } /* * Get the size of a btree block. */ int btblock_size( void *obj, int startoff, int idx) { return bitize(mp->m_sb.sb_blocksize); } /* * Bmap btree. */ const field_t bmapbta_hfld[] = { { "", FLDT_BMAPBTA, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t bmapbtd_hfld[] = { { "", FLDT_BMAPBTD, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t bmapbta_crc_hfld[] = { { "", FLDT_BMAPBTA_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t bmapbtd_crc_hfld[] = { { "", FLDT_BMAPBTD_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) const field_t bmapbta_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_DFSBNO, OI(OFF(u.l.bb_leftsib)), C1, 0, TYP_BMAPBTA }, { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_BMAPBTA }, { "recs", FLDT_BMAPBTAREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_BMAPBTAKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BMAPBTAPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BMAPBTA }, { NULL } }; const field_t bmapbtd_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_DFSBNO, OI(OFF(u.l.bb_leftsib)), C1, 0, TYP_BMAPBTD }, { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_BMAPBTD }, { "recs", FLDT_BMAPBTDREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_BMAPBTDKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BMAPBTDPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BMAPBTD }, { NULL } }; /* crc enabled versions */ const field_t bmapbta_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_DFSBNO, OI(OFF(u.l.bb_leftsib)), C1, 0, TYP_BMAPBTA }, { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_BMAPBTA }, { "bno", FLDT_DFSBNO, OI(OFF(u.l.bb_blkno)), C1, 0, TYP_BMAPBTD }, { "lsn", FLDT_UINT64X, OI(OFF(u.l.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.l.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_INO, OI(OFF(u.l.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_BMAPBTAREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_BMAPBTAKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BMAPBTAPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BMAPBTA }, { NULL } }; const field_t bmapbtd_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_DFSBNO, OI(OFF(u.l.bb_leftsib)), C1, 0, TYP_BMAPBTD }, { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_BMAPBTD }, { "bno", FLDT_DFSBNO, OI(OFF(u.l.bb_blkno)), C1, 0, TYP_BMAPBTD }, { "lsn", FLDT_UINT64X, OI(OFF(u.l.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.l.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_INO, OI(OFF(u.l.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_BMAPBTDREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_BMAPBTDKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BMAPBTDPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BMAPBTD }, { NULL } }; #undef OFF #define KOFF(f) bitize(offsetof(xfs_bmbt_key_t, br_ ## f)) const field_t bmapbta_key_flds[] = { { "startoff", FLDT_DFILOFFA, OI(KOFF(startoff)), C1, 0, TYP_ATTR }, { NULL } }; const field_t bmapbtd_key_flds[] = { { "startoff", FLDT_DFILOFFD, OI(KOFF(startoff)), C1, 0, TYP_INODATA }, { NULL } }; #undef KOFF #define BMBT_EXNTFLAG_BITOFF 0 #define BMBT_STARTOFF_BITOFF (BMBT_EXNTFLAG_BITOFF + BMBT_EXNTFLAG_BITLEN) #define BMBT_STARTBLOCK_BITOFF (BMBT_STARTOFF_BITOFF + BMBT_STARTOFF_BITLEN) #define BMBT_BLOCKCOUNT_BITOFF \ (BMBT_STARTBLOCK_BITOFF + BMBT_STARTBLOCK_BITLEN) const field_t bmapbta_rec_flds[] = { { "startoff", FLDT_CFILEOFFA, OI(BMBT_STARTOFF_BITOFF), C1, 0, TYP_ATTR }, { "startblock", FLDT_CFSBLOCK, OI(BMBT_STARTBLOCK_BITOFF), C1, 0, TYP_ATTR }, { "blockcount", FLDT_CEXTLEN, OI(BMBT_BLOCKCOUNT_BITOFF), C1, 0, TYP_NONE }, { "extentflag", FLDT_CEXTFLG, OI(BMBT_EXNTFLAG_BITOFF), C1, 0, TYP_NONE }, { NULL } }; const field_t bmapbtd_rec_flds[] = { { "startoff", FLDT_CFILEOFFD, OI(BMBT_STARTOFF_BITOFF), C1, 0, TYP_INODATA }, { "startblock", FLDT_CFSBLOCK, OI(BMBT_STARTBLOCK_BITOFF), C1, 0, TYP_INODATA }, { "blockcount", FLDT_CEXTLEN, OI(BMBT_BLOCKCOUNT_BITOFF), C1, 0, TYP_NONE }, { "extentflag", FLDT_CEXTFLG, OI(BMBT_EXNTFLAG_BITOFF), C1, 0, TYP_NONE }, { NULL } }; /* * Inode allocation btree. */ const field_t inobt_hfld[] = { { "", FLDT_INOBT, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t inobt_crc_hfld[] = { { "", FLDT_INOBT_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t inobt_spcrc_hfld[] = { { "", FLDT_INOBT_SPCRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) const field_t inobt_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_INOBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_INOBT }, { "recs", FLDT_INOBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_INOBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_INOBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_INOBT }, { NULL } }; const field_t inobt_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_INOBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_INOBT }, { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_INOBT }, { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_INOBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_INOBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_INOBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_INOBT }, { NULL } }; const field_t inobt_spcrc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_INOBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_INOBT }, { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_INOBT }, { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_INOBTSPREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_INOBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_INOBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_INOBT }, { NULL } }; #undef OFF #define KOFF(f) bitize(offsetof(xfs_inobt_key_t, ir_ ## f)) const field_t inobt_key_flds[] = { { "startino", FLDT_AGINO, OI(KOFF(startino)), C1, 0, TYP_INODE }, { NULL } }; #undef KOFF #define ROFF(f) bitize(offsetof(xfs_inobt_rec_t, f)) const field_t inobt_rec_flds[] = { { "startino", FLDT_AGINO, OI(ROFF(ir_startino)), C1, 0, TYP_INODE }, { "freecount", FLDT_INT32D, OI(ROFF(ir_u.f.ir_freecount)), C1, 0, TYP_NONE }, { "free", FLDT_INOFREE, OI(ROFF(ir_free)), C1, 0, TYP_NONE }, { NULL } }; /* sparse inode on-disk format */ const field_t inobt_sprec_flds[] = { { "startino", FLDT_AGINO, OI(ROFF(ir_startino)), C1, 0, TYP_INODE }, { "holemask", FLDT_UINT16X, OI(ROFF(ir_u.sp.ir_holemask)), C1, 0, TYP_NONE }, { "count", FLDT_UINT8D, OI(ROFF(ir_u.sp.ir_count)), C1, 0, TYP_NONE }, { "freecount", FLDT_INT8D, OI(ROFF(ir_u.sp.ir_freecount)), C1, 0, TYP_NONE }, { "free", FLDT_INOFREE, OI(ROFF(ir_free)), C1, 0, TYP_NONE }, { NULL } }; #undef ROFF /* * Allocation btrees. */ const field_t bnobt_hfld[] = { { "", FLDT_BNOBT, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t bnobt_crc_hfld[] = { { "", FLDT_BNOBT_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) const field_t bnobt_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_BNOBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_BNOBT }, { "recs", FLDT_BNOBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_BNOBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BNOBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BNOBT }, { NULL } }; const field_t bnobt_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_BNOBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_BNOBT }, { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_BNOBT }, { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_BNOBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_BNOBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_BNOBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_BNOBT }, { NULL } }; #undef OFF #define KOFF(f) bitize(offsetof(xfs_alloc_key_t, ar_ ## f)) const field_t bnobt_key_flds[] = { { "startblock", FLDT_AGBLOCK, OI(KOFF(startblock)), C1, 0, TYP_DATA }, { "blockcount", FLDT_EXTLEN, OI(KOFF(blockcount)), C1, 0, TYP_NONE }, { NULL } }; #undef KOFF #define ROFF(f) bitize(offsetof(xfs_alloc_rec_t, ar_ ## f)) const field_t bnobt_rec_flds[] = { { "startblock", FLDT_AGBLOCK, OI(ROFF(startblock)), C1, 0, TYP_DATA }, { "blockcount", FLDT_EXTLEN, OI(ROFF(blockcount)), C1, 0, TYP_NONE }, { NULL } }; #undef ROFF const field_t cntbt_hfld[] = { { "", FLDT_CNTBT, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t cntbt_crc_hfld[] = { { "", FLDT_CNTBT_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) const field_t cntbt_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_CNTBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_CNTBT }, { "recs", FLDT_CNTBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_CNTBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_CNTBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_CNTBT }, { NULL } }; const field_t cntbt_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_CNTBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_CNTBT }, { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_CNTBT }, { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_CNTBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_CNTBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_CNTBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_CNTBT }, { NULL } }; #undef OFF #define KOFF(f) bitize(offsetof(xfs_alloc_key_t, ar_ ## f)) const field_t cntbt_key_flds[] = { { "blockcount", FLDT_EXTLEN, OI(KOFF(blockcount)), C1, 0, TYP_NONE }, { "startblock", FLDT_AGBLOCK, OI(KOFF(startblock)), C1, 0, TYP_DATA }, { NULL } }; #undef KOFF #define ROFF(f) bitize(offsetof(xfs_alloc_rec_t, ar_ ## f)) const field_t cntbt_rec_flds[] = { { "startblock", FLDT_AGBLOCK, OI(ROFF(startblock)), C1, 0, TYP_DATA }, { "blockcount", FLDT_EXTLEN, OI(ROFF(blockcount)), C1, 0, TYP_NONE }, { NULL } }; #undef ROFF /* RMAP btree blocks */ const field_t rmapbt_crc_hfld[] = { { "", FLDT_RMAPBT_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) const field_t rmapbt_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_RMAPBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_RMAPBT }, { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_RMAPBT }, { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_RMAPBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_RMAPBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_RMAPBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RMAPBT }, { NULL } }; #undef OFF #define KOFF(f) bitize(offsetof(struct xfs_rmap_key, rm_ ## f)) #define RMAPBK_STARTBLOCK_BITOFF 0 #define RMAPBK_OWNER_BITOFF (RMAPBK_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN) #define RMAPBK_ATTRFLAG_BITOFF (RMAPBK_OWNER_BITOFF + RMAPBT_OWNER_BITLEN) #define RMAPBK_BMBTFLAG_BITOFF (RMAPBK_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN) #define RMAPBK_EXNTFLAG_BITOFF (RMAPBK_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN) #define RMAPBK_UNUSED_OFFSET_BITOFF (RMAPBK_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN) #define RMAPBK_OFFSET_BITOFF (RMAPBK_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) #define HI_KOFF(f) bitize(sizeof(struct xfs_rmap_key) + offsetof(struct xfs_rmap_key, rm_ ## f)) #define RMAPBK_STARTBLOCKHI_BITOFF (bitize(sizeof(struct xfs_rmap_key))) #define RMAPBK_OWNERHI_BITOFF (RMAPBK_STARTBLOCKHI_BITOFF + RMAPBT_STARTBLOCK_BITLEN) #define RMAPBK_ATTRFLAGHI_BITOFF (RMAPBK_OWNERHI_BITOFF + RMAPBT_OWNER_BITLEN) #define RMAPBK_BMBTFLAGHI_BITOFF (RMAPBK_ATTRFLAGHI_BITOFF + RMAPBT_ATTRFLAG_BITLEN) #define RMAPBK_EXNTFLAGHI_BITOFF (RMAPBK_BMBTFLAGHI_BITOFF + RMAPBT_BMBTFLAG_BITLEN) #define RMAPBK_UNUSED_OFFSETHI_BITOFF (RMAPBK_EXNTFLAGHI_BITOFF + RMAPBT_EXNTFLAG_BITLEN) #define RMAPBK_OFFSETHI_BITOFF (RMAPBK_UNUSED_OFFSETHI_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) const field_t rmapbt_key_flds[] = { { "startblock", FLDT_AGBLOCK, OI(KOFF(startblock)), C1, 0, TYP_DATA }, { "owner", FLDT_INT64D, OI(KOFF(owner)), C1, 0, TYP_NONE }, { "offset", FLDT_RFILEOFFD, OI(RMAPBK_OFFSET_BITOFF), C1, 0, TYP_NONE }, { "attrfork", FLDT_RATTRFORKFLG, OI(RMAPBK_ATTRFLAG_BITOFF), C1, 0, TYP_NONE }, { "bmbtblock", FLDT_RBMBTFLG, OI(RMAPBK_BMBTFLAG_BITOFF), C1, 0, TYP_NONE }, { "startblock_hi", FLDT_AGBLOCK, OI(HI_KOFF(startblock)), C1, 0, TYP_DATA }, { "owner_hi", FLDT_INT64D, OI(HI_KOFF(owner)), C1, 0, TYP_NONE }, { "offset_hi", FLDT_RFILEOFFD, OI(RMAPBK_OFFSETHI_BITOFF), C1, 0, TYP_NONE }, { "attrfork_hi", FLDT_RATTRFORKFLG, OI(RMAPBK_ATTRFLAGHI_BITOFF), C1, 0, TYP_NONE }, { "bmbtblock_hi", FLDT_RBMBTFLG, OI(RMAPBK_BMBTFLAGHI_BITOFF), C1, 0, TYP_NONE }, { NULL } }; #undef HI_KOFF #undef KOFF #define ROFF(f) bitize(offsetof(struct xfs_rmap_rec, rm_ ## f)) #define RMAPBT_STARTBLOCK_BITOFF 0 #define RMAPBT_BLOCKCOUNT_BITOFF (RMAPBT_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN) #define RMAPBT_OWNER_BITOFF (RMAPBT_BLOCKCOUNT_BITOFF + RMAPBT_BLOCKCOUNT_BITLEN) #define RMAPBT_ATTRFLAG_BITOFF (RMAPBT_OWNER_BITOFF + RMAPBT_OWNER_BITLEN) #define RMAPBT_BMBTFLAG_BITOFF (RMAPBT_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN) #define RMAPBT_EXNTFLAG_BITOFF (RMAPBT_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN) #define RMAPBT_UNUSED_OFFSET_BITOFF (RMAPBT_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN) #define RMAPBT_OFFSET_BITOFF (RMAPBT_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) const field_t rmapbt_rec_flds[] = { { "startblock", FLDT_AGBLOCK, OI(RMAPBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA }, { "blockcount", FLDT_REXTLEN, OI(RMAPBT_BLOCKCOUNT_BITOFF), C1, 0, TYP_NONE }, { "owner", FLDT_INT64D, OI(RMAPBT_OWNER_BITOFF), C1, 0, TYP_NONE }, { "offset", FLDT_RFILEOFFD, OI(RMAPBT_OFFSET_BITOFF), C1, 0, TYP_NONE }, { "extentflag", FLDT_REXTFLG, OI(RMAPBT_EXNTFLAG_BITOFF), C1, 0, TYP_NONE }, { "attrfork", FLDT_RATTRFORKFLG, OI(RMAPBT_ATTRFLAG_BITOFF), C1, 0, TYP_NONE }, { "bmbtblock", FLDT_RBMBTFLG, OI(RMAPBT_BMBTFLAG_BITOFF), C1, 0, TYP_NONE }, { NULL } }; #undef ROFF /* refcount btree blocks */ const field_t refcbt_crc_hfld[] = { { "", FLDT_REFCBT_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) const field_t refcbt_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_REFCBT }, { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_REFCBT }, { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_REFCBT }, { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, { "recs", FLDT_REFCBTREC, btblock_rec_offset, btblock_rec_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "keys", FLDT_REFCBTKEY, btblock_key_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "ptrs", FLDT_REFCBTPTR, btblock_ptr_offset, btblock_key_count, FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_REFCBT }, { NULL } }; #undef OFF #define REFCNTBT_COWFLAG_BITOFF 0 #define REFCNTBT_STARTBLOCK_BITOFF (REFCNTBT_COWFLAG_BITOFF + REFCNTBT_COWFLAG_BITLEN) #define KOFF(f) bitize(offsetof(struct xfs_refcount_key, rc_ ## f)) const field_t refcbt_key_flds[] = { { "startblock", FLDT_CAGBLOCK, OI(REFCNTBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA }, { "cowflag", FLDT_CCOWFLG, OI(REFCNTBT_COWFLAG_BITOFF), C1, 0, TYP_DATA }, { NULL } }; #undef KOFF #define ROFF(f) bitize(offsetof(struct xfs_refcount_rec, rc_ ## f)) const field_t refcbt_rec_flds[] = { { "startblock", FLDT_CAGBLOCK, OI(REFCNTBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA }, { "blockcount", FLDT_EXTLEN, OI(ROFF(blockcount)), C1, 0, TYP_NONE }, { "refcount", FLDT_UINT32D, OI(ROFF(refcount)), C1, 0, TYP_DATA }, { "cowflag", FLDT_CCOWFLG, OI(REFCNTBT_COWFLAG_BITOFF), C1, 0, TYP_DATA }, { NULL } }; #undef ROFF xfsprogs-4.9.0+nmu1ubuntu2/db/btblock.h0000644000000000000000000000504413063067167014660 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field bmapbta_flds[]; extern const struct field bmapbta_hfld[]; extern const struct field bmapbta_crc_flds[]; extern const struct field bmapbta_crc_hfld[]; extern const struct field bmapbta_key_flds[]; extern const struct field bmapbta_rec_flds[]; extern const struct field bmapbtd_flds[]; extern const struct field bmapbtd_hfld[]; extern const struct field bmapbtd_crc_flds[]; extern const struct field bmapbtd_crc_hfld[]; extern const struct field bmapbtd_key_flds[]; extern const struct field bmapbtd_rec_flds[]; extern const struct field inobt_flds[]; extern const struct field inobt_hfld[]; extern const struct field inobt_crc_flds[]; extern const struct field inobt_spcrc_flds[]; extern const struct field inobt_crc_hfld[]; extern const struct field inobt_spcrc_hfld[]; extern const struct field inobt_key_flds[]; extern const struct field inobt_rec_flds[]; extern const struct field inobt_sprec_flds[]; extern const struct field bnobt_flds[]; extern const struct field bnobt_hfld[]; extern const struct field bnobt_crc_flds[]; extern const struct field bnobt_crc_hfld[]; extern const struct field bnobt_key_flds[]; extern const struct field bnobt_rec_flds[]; extern const struct field cntbt_flds[]; extern const struct field cntbt_hfld[]; extern const struct field cntbt_crc_flds[]; extern const struct field cntbt_crc_hfld[]; extern const struct field cntbt_key_flds[]; extern const struct field cntbt_rec_flds[]; extern const struct field rmapbt_crc_flds[]; extern const struct field rmapbt_crc_hfld[]; extern const struct field rmapbt_key_flds[]; extern const struct field rmapbt_rec_flds[]; extern const struct field refcbt_crc_flds[]; extern const struct field refcbt_crc_hfld[]; extern const struct field refcbt_key_flds[]; extern const struct field refcbt_rec_flds[]; extern int btblock_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/check.c0000644000000000000000000036004313063067170014305 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include #include "bmap.h" #include "check.h" #include "command.h" #include "io.h" #include "type.h" #include "fprint.h" #include "faddr.h" #include "field.h" #include "sb.h" #include "output.h" #include "init.h" #include "malloc.h" #include "dir2.h" typedef enum { IS_USER_QUOTA, IS_PROJECT_QUOTA, IS_GROUP_QUOTA, } qtype_t; typedef enum { DBM_UNKNOWN, DBM_AGF, DBM_AGFL, DBM_AGI, DBM_ATTR, DBM_BTBMAPA, DBM_BTBMAPD, DBM_BTBNO, DBM_BTCNT, DBM_BTINO, DBM_DATA, DBM_DIR, DBM_FREE1, DBM_FREE2, DBM_FREELIST, DBM_INODE, DBM_LOG, DBM_MISSING, DBM_QUOTA, DBM_RTBITMAP, DBM_RTDATA, DBM_RTFREE, DBM_RTSUM, DBM_SB, DBM_SYMLINK, DBM_BTFINO, DBM_BTRMAP, DBM_BTREFC, DBM_RLDATA, DBM_COWDATA, DBM_NDBM } dbm_t; typedef struct inodata { struct inodata *next; nlink_t link_set; nlink_t link_add; char isdir:1; char isreflink:1; char security; char ilist; xfs_ino_t ino; struct inodata *parent; char *name; } inodata_t; #define MIN_INODATA_HASH_SIZE 256 #define MAX_INODATA_HASH_SIZE 65536 #define INODATA_AVG_HASH_LENGTH 8 typedef struct qinfo { xfs_qcnt_t bc; xfs_qcnt_t ic; xfs_qcnt_t rc; } qinfo_t; #define QDATA_HASH_SIZE 256 typedef struct qdata { struct qdata *next; xfs_dqid_t id; qinfo_t count; qinfo_t dq; } qdata_t; typedef struct blkent { xfs_fileoff_t startoff; int nblks; xfs_fsblock_t blks[1]; } blkent_t; #define BLKENT_SIZE(n) \ (offsetof(blkent_t, blks) + (sizeof(xfs_fsblock_t) * (n))) typedef struct blkmap { int naents; int nents; blkent_t *ents[1]; } blkmap_t; #define BLKMAP_SIZE(n) \ (offsetof(blkmap_t, ents) + (sizeof(blkent_t *) * (n))) typedef struct freetab { int naents; int nents; xfs_dir2_data_off_t ents[1]; } freetab_t; #define FREETAB_SIZE(n) \ (offsetof(freetab_t, ents) + (sizeof(xfs_dir2_data_off_t) * (n))) typedef struct dirhash { struct dirhash *next; __u32 hashval; __u32 address; int seen; } dirhash_t; #define DIR_HASH_SIZE 1024 #define DIR_HASH_FUNC(h,a) (((h) ^ (a)) % DIR_HASH_SIZE) static xfs_extlen_t agffreeblks; static xfs_extlen_t agflongest; static __uint64_t agf_aggr_freeblks; /* aggregate count over all */ static __uint32_t agfbtreeblks; static int lazycount; static xfs_agino_t agicount; static xfs_agino_t agifreecount; static xfs_fsblock_t *blist; static int blist_size; static char **dbmap; /* really dbm_t:8 */ static dirhash_t **dirhash; static int error; static __uint64_t fdblocks; static __uint64_t frextents; static __uint64_t icount; static __uint64_t ifree; static inodata_t ***inodata; static int inodata_hash_size; static inodata_t ***inomap; static int nflag; static int pflag; static int tflag; static qdata_t **qpdata; static int qpdo; static qdata_t **qudata; static int qudo; static qdata_t **qgdata; static int qgdo; static unsigned sbversion; static int sbver_err; static int serious_error; static int sflag; static xfs_suminfo_t *sumcompute; static xfs_suminfo_t *sumfile; static const char *typename[] = { "unknown", "agf", "agfl", "agi", "attr", "btbmapa", "btbmapd", "btbno", "btcnt", "btino", "data", "dir", "free1", "free2", "freelist", "inode", "log", "missing", "quota", "rtbitmap", "rtdata", "rtfree", "rtsum", "sb", "symlink", "btfino", "btrmap", "btrefcnt", "rldata", NULL }; static int verbose; #define CHECK_BLIST(b) (blist_size && check_blist(b)) #define CHECK_BLISTA(a,b) \ (blist_size && check_blist(XFS_AGB_TO_FSB(mp, a, b))) typedef void (*scan_lbtree_f_t)(struct xfs_btree_block *block, int level, dbm_t type, xfs_fsblock_t bno, inodata_t *id, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int isroot, typnm_t btype); typedef void (*scan_sbtree_f_t)(struct xfs_btree_block *block, int level, xfs_agf_t *agf, xfs_agblock_t bno, int isroot); static void add_blist(xfs_fsblock_t bno); static void add_ilist(xfs_ino_t ino); static void addlink_inode(inodata_t *id); static void addname_inode(inodata_t *id, char *name, int namelen); static void addparent_inode(inodata_t *id, xfs_ino_t parent); static void blkent_append(blkent_t **entp, xfs_fsblock_t b, xfs_extlen_t c); static blkent_t *blkent_new(xfs_fileoff_t o, xfs_fsblock_t b, xfs_extlen_t c); static void blkent_prepend(blkent_t **entp, xfs_fsblock_t b, xfs_extlen_t c); static blkmap_t *blkmap_alloc(xfs_extnum_t); static void blkmap_free(blkmap_t *blkmap); static xfs_fsblock_t blkmap_get(blkmap_t *blkmap, xfs_fileoff_t o); static int blkmap_getn(blkmap_t *blkmap, xfs_fileoff_t o, int nb, bmap_ext_t **bmpp); static void blkmap_grow(blkmap_t **blkmapp, blkent_t **entp, blkent_t *newent); static xfs_fileoff_t blkmap_next_off(blkmap_t *blkmap, xfs_fileoff_t o, int *t); static void blkmap_set_blk(blkmap_t **blkmapp, xfs_fileoff_t o, xfs_fsblock_t b); static void blkmap_set_ext(blkmap_t **blkmapp, xfs_fileoff_t o, xfs_fsblock_t b, xfs_extlen_t c); static void blkmap_shrink(blkmap_t *blkmap, blkent_t **entp); static int blockfree_f(int argc, char **argv); static int blockget_f(int argc, char **argv); static int blocktrash_f(int argc, char **argv); static int blockuse_f(int argc, char **argv); static int check_blist(xfs_fsblock_t bno); static void check_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type, int ignore_reflink); static int check_inomap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, xfs_ino_t c_ino); static void check_linkcounts(xfs_agnumber_t agno); static int check_range(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len); static void check_rdbmap(xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type); static int check_rinomap(xfs_rfsblock_t bno, xfs_extlen_t len, xfs_ino_t c_ino); static void check_rootdir(void); static int check_rrange(xfs_rfsblock_t bno, xfs_extlen_t len); static void check_set_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type1, dbm_t type2, xfs_agnumber_t c_agno, xfs_agblock_t c_agbno); static void check_set_rdbmap(xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type1, dbm_t type2); static void check_summary(void); static void checknot_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, int typemask); static void checknot_rdbmap(xfs_rfsblock_t bno, xfs_extlen_t len, int typemask); static void dir_hash_add(xfs_dahash_t hash, xfs_dir2_dataptr_t addr); static void dir_hash_check(inodata_t *id, int v); static void dir_hash_done(void); static void dir_hash_init(void); static int dir_hash_see(xfs_dahash_t hash, xfs_dir2_dataptr_t addr); static inodata_t *find_inode(xfs_ino_t ino, int add); static void free_inodata(xfs_agnumber_t agno); static int init(int argc, char **argv); static char *inode_name(xfs_ino_t ino, inodata_t **ipp); static int ncheck_f(int argc, char **argv); static char *prepend_path(char *oldpath, char *parent); static xfs_ino_t process_block_dir_v2(blkmap_t *blkmap, int *dot, int *dotdot, inodata_t *id); static void process_bmbt_reclist(xfs_bmbt_rec_t *rp, int numrecs, dbm_t type, inodata_t *id, xfs_rfsblock_t *tot, blkmap_t **blkmapp); static void process_btinode(inodata_t *id, xfs_dinode_t *dip, dbm_t type, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int whichfork); static xfs_ino_t process_data_dir_v2(int *dot, int *dotdot, inodata_t *id, int v, xfs_dablk_t dabno, freetab_t **freetabp); static xfs_dir2_data_free_t *process_data_dir_v2_freefind( struct xfs_dir2_data_hdr *data, struct xfs_dir2_data_unused *dup); static void process_dir(xfs_dinode_t *dip, blkmap_t *blkmap, inodata_t *id); static int process_dir_v2(xfs_dinode_t *dip, blkmap_t *blkmap, int *dot, int *dotdot, inodata_t *id, xfs_ino_t *parent); static void process_exinode(inodata_t *id, xfs_dinode_t *dip, dbm_t type, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int whichfork); static void process_inode(xfs_agf_t *agf, xfs_agino_t agino, xfs_dinode_t *dip, int isfree); static void process_lclinode(inodata_t *id, xfs_dinode_t *dip, dbm_t type, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int whichfork); static xfs_ino_t process_leaf_node_dir_v2(blkmap_t *blkmap, int *dot, int *dotdot, inodata_t *id, xfs_fsize_t dirsize); static void process_leaf_node_dir_v2_free(inodata_t *id, int v, xfs_dablk_t dbno, freetab_t *freetab); static void process_leaf_node_dir_v2_int(inodata_t *id, int v, xfs_dablk_t dbno, freetab_t *freetab); static void process_quota(qtype_t qtype, inodata_t *id, blkmap_t *blkmap); static void process_rtbitmap(blkmap_t *blkmap); static void process_rtsummary(blkmap_t *blkmap); static xfs_ino_t process_sf_dir_v2(xfs_dinode_t *dip, int *dot, int *dotdot, inodata_t *id); static void quota_add(xfs_dqid_t *p, xfs_dqid_t *g, xfs_dqid_t *u, int dq, xfs_qcnt_t bc, xfs_qcnt_t ic, xfs_qcnt_t rc); static void quota_add1(qdata_t **qt, xfs_dqid_t id, int dq, xfs_qcnt_t bc, xfs_qcnt_t ic, xfs_qcnt_t rc); static void quota_check(char *s, qdata_t **qt); static void quota_init(void); static void scan_ag(xfs_agnumber_t agno); static void scan_freelist(xfs_agf_t *agf); static void scan_lbtree(xfs_fsblock_t root, int nlevels, scan_lbtree_f_t func, dbm_t type, inodata_t *id, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int isroot, typnm_t btype); static void scan_sbtree(xfs_agf_t *agf, xfs_agblock_t root, int nlevels, int isroot, scan_sbtree_f_t func, typnm_t btype); static void scanfunc_bmap(struct xfs_btree_block *block, int level, dbm_t type, xfs_fsblock_t bno, inodata_t *id, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int isroot, typnm_t btype); static void scanfunc_bno(struct xfs_btree_block *block, int level, xfs_agf_t *agf, xfs_agblock_t bno, int isroot); static void scanfunc_cnt(struct xfs_btree_block *block, int level, xfs_agf_t *agf, xfs_agblock_t bno, int isroot); static void scanfunc_ino(struct xfs_btree_block *block, int level, xfs_agf_t *agf, xfs_agblock_t bno, int isroot); static void scanfunc_fino(struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot); static void scanfunc_rmap(struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot); static void scanfunc_refcnt(struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot); static void set_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type, xfs_agnumber_t c_agno, xfs_agblock_t c_agbno); static void set_inomap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, inodata_t *id); static void set_rdbmap(xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type); static void set_rinomap(xfs_rfsblock_t bno, xfs_extlen_t len, inodata_t *id); static void setlink_inode(inodata_t *id, nlink_t nlink, int isdir, int security); static const cmdinfo_t blockfree_cmd = { "blockfree", NULL, blockfree_f, 0, 0, 0, NULL, N_("free block usage information"), NULL }; static const cmdinfo_t blockget_cmd = { "blockget", "check", blockget_f, 0, -1, 0, N_("[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..."), N_("get block usage and check consistency"), NULL }; static const cmdinfo_t blocktrash_cmd = { "blocktrash", NULL, blocktrash_f, 0, -1, 0, N_("[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ..."), N_("trash randomly selected block(s)"), NULL }; static const cmdinfo_t blockuse_cmd = { "blockuse", NULL, blockuse_f, 0, 3, 0, N_("[-n] [-c blockcount]"), N_("print usage for current block(s)"), NULL }; static const cmdinfo_t ncheck_cmd = { "ncheck", NULL, ncheck_f, 0, -1, 0, N_("[-s] [-i ino] ..."), N_("print inode-name pairs"), NULL }; static void add_blist( xfs_fsblock_t bno) { blist_size++; blist = xrealloc(blist, blist_size * sizeof(bno)); blist[blist_size - 1] = bno; } static void add_ilist( xfs_ino_t ino) { inodata_t *id; id = find_inode(ino, 1); if (id == NULL) { dbprintf(_("-i %lld bad inode number\n"), ino); return; } id->ilist = 1; } static void addlink_inode( inodata_t *id) { id->link_add++; if (verbose || id->ilist) dbprintf(_("inode %lld add link, now %u\n"), id->ino, id->link_add); } static void addname_inode( inodata_t *id, char *name, int namelen) { if (!nflag || id->name) return; id->name = xmalloc(namelen + 1); memcpy(id->name, name, namelen); id->name[namelen] = '\0'; } static void addparent_inode( inodata_t *id, xfs_ino_t parent) { inodata_t *pid; pid = find_inode(parent, 1); id->parent = pid; if (verbose || id->ilist || (pid && pid->ilist)) dbprintf(_("inode %lld parent %lld\n"), id->ino, parent); } static void blkent_append( blkent_t **entp, xfs_fsblock_t b, xfs_extlen_t c) { blkent_t *ent; int i; ent = *entp; *entp = ent = xrealloc(ent, BLKENT_SIZE(c + ent->nblks)); for (i = 0; i < c; i++) ent->blks[ent->nblks + i] = b + i; ent->nblks += c; } static blkent_t * blkent_new( xfs_fileoff_t o, xfs_fsblock_t b, xfs_extlen_t c) { blkent_t *ent; int i; ent = xmalloc(BLKENT_SIZE(c)); ent->nblks = c; ent->startoff = o; for (i = 0; i < c; i++) ent->blks[i] = b + i; return ent; } static void blkent_prepend( blkent_t **entp, xfs_fsblock_t b, xfs_extlen_t c) { int i; blkent_t *newent; blkent_t *oldent; oldent = *entp; newent = xmalloc(BLKENT_SIZE(oldent->nblks + c)); newent->nblks = oldent->nblks + c; newent->startoff = oldent->startoff - c; for (i = 0; i < c; i++) newent->blks[i] = b + c; for (; i < oldent->nblks + c; i++) newent->blks[i] = oldent->blks[i - c]; xfree(oldent); *entp = newent; } static blkmap_t * blkmap_alloc( xfs_extnum_t nex) { blkmap_t *blkmap; if (nex < 1) nex = 1; blkmap = xmalloc(BLKMAP_SIZE(nex)); blkmap->naents = nex; blkmap->nents = 0; return blkmap; } static void blkmap_free( blkmap_t *blkmap) { blkent_t **entp; xfs_extnum_t i; for (i = 0, entp = blkmap->ents; i < blkmap->nents; i++, entp++) xfree(*entp); xfree(blkmap); } static xfs_fsblock_t blkmap_get( blkmap_t *blkmap, xfs_fileoff_t o) { blkent_t *ent; blkent_t **entp; int i; for (i = 0, entp = blkmap->ents; i < blkmap->nents; i++, entp++) { ent = *entp; if (o >= ent->startoff && o < ent->startoff + ent->nblks) return ent->blks[o - ent->startoff]; } return NULLFSBLOCK; } static int blkmap_getn( blkmap_t *blkmap, xfs_fileoff_t o, int nb, bmap_ext_t **bmpp) { bmap_ext_t *bmp; blkent_t *ent; xfs_fileoff_t ento; blkent_t **entp; int i; int nex; for (i = nex = 0, bmp = NULL, entp = blkmap->ents; i < blkmap->nents; i++, entp++) { ent = *entp; if (ent->startoff >= o + nb) break; if (ent->startoff + ent->nblks <= o) continue; for (ento = ent->startoff; ento < ent->startoff + ent->nblks && ento < o + nb; ento++) { if (ento < o) continue; if (bmp && bmp[nex - 1].startoff + bmp[nex - 1].blockcount == ento && bmp[nex - 1].startblock + bmp[nex - 1].blockcount == ent->blks[ento - ent->startoff]) bmp[nex - 1].blockcount++; else { bmp = realloc(bmp, ++nex * sizeof(*bmp)); bmp[nex - 1].startoff = ento; bmp[nex - 1].startblock = ent->blks[ento - ent->startoff]; bmp[nex - 1].blockcount = 1; bmp[nex - 1].flag = 0; } } } *bmpp = bmp; return nex; } static void blkmap_grow( blkmap_t **blkmapp, blkent_t **entp, blkent_t *newent) { blkmap_t *blkmap; int i; int idx; blkmap = *blkmapp; idx = (int)(entp - blkmap->ents); if (blkmap->naents == blkmap->nents) { blkmap = xrealloc(blkmap, BLKMAP_SIZE(blkmap->nents + 1)); *blkmapp = blkmap; blkmap->naents++; } for (i = blkmap->nents; i > idx; i--) blkmap->ents[i] = blkmap->ents[i - 1]; blkmap->ents[idx] = newent; blkmap->nents++; } static xfs_fileoff_t blkmap_last_off( blkmap_t *blkmap) { blkent_t *ent; if (!blkmap->nents) return NULLFILEOFF; ent = blkmap->ents[blkmap->nents - 1]; return ent->startoff + ent->nblks; } static xfs_fileoff_t blkmap_next_off( blkmap_t *blkmap, xfs_fileoff_t o, int *t) { blkent_t *ent; blkent_t **entp; if (!blkmap->nents) return NULLFILEOFF; if (o == NULLFILEOFF) { *t = 0; ent = blkmap->ents[0]; return ent->startoff; } entp = &blkmap->ents[*t]; ent = *entp; if (o < ent->startoff + ent->nblks - 1) return o + 1; entp++; if (entp >= &blkmap->ents[blkmap->nents]) return NULLFILEOFF; (*t)++; ent = *entp; return ent->startoff; } static void blkmap_set_blk( blkmap_t **blkmapp, xfs_fileoff_t o, xfs_fsblock_t b) { blkmap_t *blkmap; blkent_t *ent; blkent_t **entp; blkent_t *nextent; blkmap = *blkmapp; for (entp = blkmap->ents; entp < &blkmap->ents[blkmap->nents]; entp++) { ent = *entp; if (o < ent->startoff - 1) { ent = blkent_new(o, b, 1); blkmap_grow(blkmapp, entp, ent); return; } if (o == ent->startoff - 1) { blkent_prepend(entp, b, 1); return; } if (o >= ent->startoff && o < ent->startoff + ent->nblks) { ent->blks[o - ent->startoff] = b; return; } if (o > ent->startoff + ent->nblks) continue; blkent_append(entp, b, 1); if (entp == &blkmap->ents[blkmap->nents - 1]) return; ent = *entp; nextent = entp[1]; if (ent->startoff + ent->nblks < nextent->startoff) return; blkent_append(entp, nextent->blks[0], nextent->nblks); blkmap_shrink(blkmap, &entp[1]); return; } ent = blkent_new(o, b, 1); blkmap_grow(blkmapp, entp, ent); } static void blkmap_set_ext( blkmap_t **blkmapp, xfs_fileoff_t o, xfs_fsblock_t b, xfs_extlen_t c) { blkmap_t *blkmap; blkent_t *ent; blkent_t **entp; xfs_extnum_t i; blkmap = *blkmapp; if (!blkmap->nents) { blkmap->ents[0] = blkent_new(o, b, c); blkmap->nents = 1; return; } entp = &blkmap->ents[blkmap->nents - 1]; ent = *entp; if (ent->startoff + ent->nblks == o) { blkent_append(entp, b, c); return; } if (ent->startoff + ent->nblks < o) { ent = blkent_new(o, b, c); blkmap_grow(blkmapp, &blkmap->ents[blkmap->nents], ent); return; } for (i = 0; i < c; i++) blkmap_set_blk(blkmapp, o + i, b + i); } static void blkmap_shrink( blkmap_t *blkmap, blkent_t **entp) { int i; int idx; xfree(*entp); idx = (int)(entp - blkmap->ents); for (i = idx + 1; i < blkmap->nents; i++) blkmap->ents[i] = blkmap->ents[i - 1]; blkmap->nents--; } /* ARGSUSED */ static int blockfree_f( int argc, char **argv) { xfs_agnumber_t c; int rt; if (!dbmap) { dbprintf(_("block usage information not allocated\n")); return 0; } rt = mp->m_sb.sb_rextents != 0; for (c = 0; c < mp->m_sb.sb_agcount; c++) { xfree(dbmap[c]); xfree(inomap[c]); free_inodata(c); } if (rt) { xfree(dbmap[c]); xfree(inomap[c]); xfree(sumcompute); xfree(sumfile); sumcompute = sumfile = NULL; } xfree(dbmap); xfree(inomap); xfree(inodata); dbmap = NULL; inomap = NULL; inodata = NULL; return 0; } /* * Check consistency of xfs filesystem contents. */ static int blockget_f( int argc, char **argv) { xfs_agnumber_t agno; int oldprefix; int sbyell; if (dbmap) { dbprintf(_("already have block usage information\n")); return 0; } if (!init(argc, argv)) { if (serious_error) exitcode = 3; else exitcode = 1; return 0; } oldprefix = dbprefix; dbprefix |= pflag; for (agno = 0, sbyell = 0; agno < mp->m_sb.sb_agcount; agno++) { scan_ag(agno); if (sbver_err > 4 && !sbyell && sbver_err >= agno) { sbyell = 1; dbprintf(_("WARNING: this may be a newer XFS " "filesystem.\n")); } } if (blist_size) { xfree(blist); blist = NULL; blist_size = 0; } if (serious_error) { exitcode = 2; dbprefix = oldprefix; return 0; } check_rootdir(); /* * Check that there are no blocks either * a) unaccounted for or * b) bno-free but not cnt-free */ if (!tflag) { /* are we in test mode, faking out freespace? */ for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) checknot_dbmap(agno, 0, mp->m_sb.sb_agblocks, (1 << DBM_UNKNOWN) | (1 << DBM_FREE1)); } for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) check_linkcounts(agno); if (mp->m_sb.sb_rblocks) { checknot_rdbmap(0, (xfs_extlen_t)(mp->m_sb.sb_rextents * mp->m_sb.sb_rextsize), 1 << DBM_UNKNOWN); check_summary(); } if (mp->m_sb.sb_icount != icount) { if (!sflag) dbprintf(_("sb_icount %lld, counted %lld\n"), mp->m_sb.sb_icount, icount); error++; } if (mp->m_sb.sb_ifree != ifree) { if (!sflag) dbprintf(_("sb_ifree %lld, counted %lld\n"), mp->m_sb.sb_ifree, ifree); error++; } if (mp->m_sb.sb_fdblocks != fdblocks) { if (!sflag) dbprintf(_("sb_fdblocks %lld, counted %lld\n"), mp->m_sb.sb_fdblocks, fdblocks); error++; } if (lazycount && mp->m_sb.sb_fdblocks != agf_aggr_freeblks) { if (!sflag) dbprintf(_("sb_fdblocks %lld, aggregate AGF count %lld\n"), mp->m_sb.sb_fdblocks, agf_aggr_freeblks); error++; } if (mp->m_sb.sb_frextents != frextents) { if (!sflag) dbprintf(_("sb_frextents %lld, counted %lld\n"), mp->m_sb.sb_frextents, frextents); error++; } if (mp->m_sb.sb_bad_features2 != 0 && mp->m_sb.sb_bad_features2 != mp->m_sb.sb_features2) { if (!sflag) dbprintf(_("sb_features2 (0x%x) not same as " "sb_bad_features2 (0x%x)\n"), mp->m_sb.sb_features2, mp->m_sb.sb_bad_features2); error++; } if ((sbversion & XFS_SB_VERSION_ATTRBIT) && !xfs_sb_version_hasattr(&mp->m_sb)) { if (!sflag) dbprintf(_("sb versionnum missing attr bit %x\n"), XFS_SB_VERSION_ATTRBIT); error++; } if ((sbversion & XFS_SB_VERSION_QUOTABIT) && !xfs_sb_version_hasquota(&mp->m_sb)) { if (!sflag) dbprintf(_("sb versionnum missing quota bit %x\n"), XFS_SB_VERSION_QUOTABIT); error++; } if (!(sbversion & XFS_SB_VERSION_ALIGNBIT) && xfs_sb_version_hasalign(&mp->m_sb)) { if (!sflag) dbprintf(_("sb versionnum extra align bit %x\n"), XFS_SB_VERSION_ALIGNBIT); error++; } if (qudo) quota_check("user", qudata); if (qpdo) quota_check("project", qpdata); if (qgdo) quota_check("group", qgdata); if (sbver_err > mp->m_sb.sb_agcount / 2) dbprintf(_("WARNING: this may be a newer XFS filesystem.\n")); if (error) exitcode = 3; dbprefix = oldprefix; return 0; } typedef struct ltab { int min; int max; } ltab_t; static void blocktrash_b( int bit_offset, dbm_t type, ltab_t *ltabp, int mode) { int bit; int bitno; char *buf; int byte; int len; int mask; int newbit; const struct xfs_buf_ops *stashed_ops; static char *modestr[] = { N_("zeroed"), N_("set"), N_("flipped"), N_("randomized") }; xfs_agnumber_t agno; xfs_agblock_t agbno; agno = XFS_FSB_TO_AGNO(mp, XFS_DADDR_TO_FSB(mp, iocur_top->bb)); agbno = XFS_FSB_TO_AGBNO(mp, XFS_DADDR_TO_FSB(mp, iocur_top->bb)); if (iocur_top->len == 0) { dbprintf(_("zero-length block %u/%u buffer to trash??\n"), agno, agbno); return; } len = (int)((random() % (ltabp->max - ltabp->min + 1)) + ltabp->min); /* * bit_offset >= 0: start fuzzing at this exact bit_offset. * bit_offset < 0: pick an offset at least as high at -(bit_offset + 1). */ if (bit_offset < 0) { bit_offset = -(bit_offset + 1); bit_offset += (int)(random() % (int)((iocur_top->len - bit_offset) * NBBY)); } if (bit_offset + len >= iocur_top->len * NBBY) len = (iocur_top->len * NBBY) - bit_offset; newbit = 0; stashed_ops = iocur_top->bp->b_ops; iocur_top->bp->b_ops = NULL; if ((buf = iocur_top->data) == NULL) { dbprintf(_("can't read block %u/%u for trashing\n"), agno, agbno); return; } for (bitno = 0; bitno < len; bitno++) { bit = (bit_offset + bitno) % (mp->m_sb.sb_blocksize * NBBY); byte = bit / NBBY; bit %= NBBY; mask = 1 << bit; switch (mode) { case 0: newbit = 0; break; case 1: newbit = 1; break; case 2: newbit = (buf[byte] & mask) == 0; break; case 3: newbit = (int)random() & 1; break; } if (newbit) buf[byte] |= mask; else buf[byte] &= ~mask; } write_cur(); iocur_top->bp->b_ops = stashed_ops; printf(_("blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n"), agno, agbno, typename[type], len, len == 1 ? "" : "s", bit_offset / NBBY, bit_offset % NBBY, modestr[mode]); } int blocktrash_f( int argc, char **argv) { xfs_agblock_t agbno; xfs_agnumber_t agno; xfs_rfsblock_t bi; xfs_rfsblock_t blocks; int c; int count; int done; int goodmask; int i; ltab_t *lentab; int lentablen; int max; int min; int mode; struct timeval now; char *p; xfs_rfsblock_t randb; uint seed; int sopt; int tmask; bool this_block = false; int bit_offset = -1; optind = 0; count = 1; min = 1; max = 128 * NBBY; mode = 2; gettimeofday(&now, NULL); seed = (unsigned int)(now.tv_sec ^ now.tv_usec); sopt = 0; tmask = 0; goodmask = (1 << DBM_AGF) | (1 << DBM_AGFL) | (1 << DBM_AGI) | (1 << DBM_ATTR) | (1 << DBM_BTBMAPA) | (1 << DBM_BTBMAPD) | (1 << DBM_BTBNO) | (1 << DBM_BTCNT) | (1 << DBM_BTINO) | (1 << DBM_DIR) | (1 << DBM_INODE) | (1 << DBM_LOG) | (1 << DBM_QUOTA) | (1 << DBM_RTBITMAP) | (1 << DBM_RTSUM) | (1 << DBM_SYMLINK) | (1 << DBM_BTFINO) | (1 << DBM_BTRMAP) | (1 << DBM_BTREFC) | (1 << DBM_SB); while ((c = getopt(argc, argv, "0123n:o:s:t:x:y:z")) != EOF) { switch (c) { case '0': mode = 0; break; case '1': mode = 1; break; case '2': mode = 2; break; case '3': mode = 3; break; case 'n': count = (int)strtol(optarg, &p, 0); if (*p != '\0' || count <= 0) { dbprintf(_("bad blocktrash count %s\n"), optarg); return 0; } break; case 'o': { int relative = 0; if (optarg[0] == '+') { optarg++; relative = 1; } bit_offset = (int)strtol(optarg, &p, 0); if (*p != '\0' || bit_offset < 0) { dbprintf(_("bad blocktrash offset %s\n"), optarg); return 0; } if (relative) bit_offset = -bit_offset - 1; break; } case 's': seed = (uint)strtoul(optarg, &p, 0); sopt = 1; break; case 't': for (i = 0; typename[i]; i++) { if (strcmp(typename[i], optarg) == 0) break; } if (!typename[i] || (((1 << i) & goodmask) == 0)) { dbprintf(_("bad blocktrash type %s\n"), optarg); return 0; } tmask |= 1 << i; break; case 'x': min = (int)strtol(optarg, &p, 0); if (*p != '\0' || min <= 0 || min > mp->m_sb.sb_blocksize * NBBY) { dbprintf(_("bad blocktrash min %s\n"), optarg); return 0; } break; case 'y': max = (int)strtol(optarg, &p, 0); if (*p != '\0' || max <= 0 || max > mp->m_sb.sb_blocksize * NBBY) { dbprintf(_("bad blocktrash max %s\n"), optarg); return 0; } break; case 'z': this_block = true; break; default: dbprintf(_("bad option for blocktrash command\n")); return 0; } } if (!this_block && !dbmap) { dbprintf(_("must run blockget first\n")); return 0; } if (this_block && iocur_sp == 0) { dbprintf(_("nothing on stack\n")); return 0; } if (min > max) { dbprintf(_("bad min/max for blocktrash command\n")); return 0; } if (tmask == 0) tmask = goodmask & ~((1 << DBM_LOG) | (1 << DBM_SB)); lentab = xmalloc(sizeof(ltab_t)); lentab->min = lentab->max = min; lentablen = 1; for (i = min + 1; i <= max; i++) { if ((i & (i - 1)) == 0) { lentab = xrealloc(lentab, sizeof(ltab_t) * (lentablen + 1)); lentab[lentablen].min = lentab[lentablen].max = i; lentablen++; } else lentab[lentablen - 1].max = i; } if (!sopt) dbprintf(_("blocktrash: seed %u\n"), seed); srandom(seed); if (this_block) { blocktrash_b(bit_offset, DBM_UNKNOWN, &lentab[random() % lentablen], mode); goto out; } for (blocks = 0, agno = 0; agno < mp->m_sb.sb_agcount; agno++) { for (agbno = 0, p = dbmap[agno]; agbno < mp->m_sb.sb_agblocks; agbno++, p++) { if ((1 << *p) & tmask) blocks++; } } if (blocks == 0) { dbprintf(_("blocktrash: no matching blocks\n")); goto out; } for (i = 0; i < count; i++) { randb = (xfs_rfsblock_t)((((__int64_t)random() << 32) | random()) % blocks); for (bi = 0, agno = 0, done = 0; !done && agno < mp->m_sb.sb_agcount; agno++) { for (agbno = 0, p = dbmap[agno]; agbno < mp->m_sb.sb_agblocks; agbno++, p++) { if (!((1 << *p) & tmask)) continue; if (bi++ < randb) continue; push_cur(); set_cur(NULL, XFS_AGB_TO_DADDR(mp, agno, agbno), blkbb, DB_RING_IGN, NULL); blocktrash_b(bit_offset, (dbm_t)*p, &lentab[random() % lentablen], mode); pop_cur(); done = 1; break; } } } out: xfree(lentab); return 0; } int blockuse_f( int argc, char **argv) { xfs_agblock_t agbno; xfs_agnumber_t agno; int c; int count; xfs_agblock_t end; xfs_fsblock_t fsb; inodata_t *i; char *p; int shownames; if (!dbmap) { dbprintf(_("must run blockget first\n")); return 0; } optind = 0; shownames = 0; fsb = XFS_DADDR_TO_FSB(mp, iocur_top->off >> BBSHIFT); agno = XFS_FSB_TO_AGNO(mp, fsb); end = agbno = XFS_FSB_TO_AGBNO(mp, fsb); while ((c = getopt(argc, argv, "c:n")) != EOF) { switch (c) { case 'c': count = (int)strtol(optarg, &p, 0); end = agbno + count - 1; if (*p != '\0' || count <= 0 || end >= mp->m_sb.sb_agblocks) { dbprintf(_("bad blockuse count %s\n"), optarg); return 0; } break; case 'n': if (!nflag) { dbprintf(_("must run blockget -n first\n")); return 0; } shownames = 1; break; default: dbprintf(_("bad option for blockuse command\n")); return 0; } } while (agbno <= end) { p = &dbmap[agno][agbno]; i = inomap[agno][agbno]; dbprintf(_("block %llu (%u/%u) type %s"), (xfs_fsblock_t)XFS_AGB_TO_FSB(mp, agno, agbno), agno, agbno, typename[(dbm_t)*p]); if (i) { dbprintf(_(" inode %lld"), i->ino); if (shownames && (p = inode_name(i->ino, NULL))) { dbprintf(" %s", p); xfree(p); } } dbprintf("\n"); agbno++; } return 0; } static int check_blist( xfs_fsblock_t bno) { int i; for (i = 0; i < blist_size; i++) { if (blist[i] == bno) return 1; } return 0; } static void check_dbmap( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type, int ignore_reflink) { xfs_extlen_t i; char *p; dbm_t d; for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { d = (dbm_t)*p; if (ignore_reflink && (d == DBM_UNKNOWN || d == DBM_DATA || d == DBM_RLDATA)) continue; if ((dbm_t)*p != type) { if (!sflag || CHECK_BLISTA(agno, agbno + i)) { dbprintf(_("block %u/%u expected type %s got " "%s\n"), agno, agbno + i, typename[type], typename[(dbm_t)*p]); } error++; } } } void check_init(void) { add_command(&blockfree_cmd); add_command(&blockget_cmd); if (expert_mode) add_command(&blocktrash_cmd); add_command(&blockuse_cmd); add_command(&ncheck_cmd); } static int check_inomap( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, xfs_ino_t c_ino) { xfs_extlen_t i; inodata_t **idp; int rval; if (!check_range(agno, agbno, len)) { dbprintf(_("blocks %u/%u..%u claimed by inode %lld\n"), agno, agbno, agbno + len - 1, c_ino); return 0; } for (i = 0, rval = 1, idp = &inomap[agno][agbno]; i < len; i++, idp++) { if (*idp && !(*idp)->isreflink) { if (!sflag || (*idp)->ilist || CHECK_BLISTA(agno, agbno + i)) dbprintf(_("block %u/%u claimed by inode %lld, " "previous inum %lld\n"), agno, agbno + i, c_ino, (*idp)->ino); error++; rval = 0; } } return rval; } static void check_linkcounts( xfs_agnumber_t agno) { inodata_t *ep; inodata_t **ht; int idx; char *path; ht = inodata[agno]; for (idx = 0; idx < inodata_hash_size; ht++, idx++) { ep = *ht; while (ep) { if (ep->link_set != ep->link_add || ep->link_set == 0) { path = inode_name(ep->ino, NULL); if (!path && ep->link_add) path = xstrdup("?"); if (!sflag || ep->ilist) { if (ep->link_add) dbprintf(_("link count mismatch " "for inode %lld (name " "%s), nlink %d, " "counted %d\n"), ep->ino, path, ep->link_set, ep->link_add); else if (ep->link_set) dbprintf(_("disconnected inode " "%lld, nlink %d\n"), ep->ino, ep->link_set); else dbprintf(_("allocated inode %lld " "has 0 link count\n"), ep->ino); } if (path) xfree(path); error++; } else if (verbose || ep->ilist) { path = inode_name(ep->ino, NULL); if (path) { dbprintf(_("inode %lld name %s\n"), ep->ino, path); xfree(path); } } ep = ep->next; } } } static int check_range( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len) { xfs_extlen_t i; xfs_agblock_t low = 0; xfs_agblock_t high = 0; int valid_range = 0; int cur, prev = 0; if (agno >= mp->m_sb.sb_agcount || agbno + len - 1 >= mp->m_sb.sb_agblocks) { for (i = 0; i < len; i++) { cur = !sflag || CHECK_BLISTA(agno, agbno + i) ? 1 : 0; if (cur == 1 && prev == 0) { low = high = agbno + i; valid_range = 1; } else if (cur == 0 && prev == 0) { /* Do nothing */ } else if (cur == 0 && prev == 1) { if (low == high) { dbprintf(_("block %u/%u out of range\n"), agno, low); } else { dbprintf(_("blocks %u/%u..%u " "out of range\n"), agno, low, high); } valid_range = 0; } else if (cur == 1 && prev == 1) { high = agbno + i; } prev = cur; } if (valid_range) { if (low == high) { dbprintf(_("block %u/%u out of range\n"), agno, low); } else { dbprintf(_("blocks %u/%u..%u " "out of range\n"), agno, low, high); } } error++; return 0; } return 1; } static void check_rdbmap( xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type) { xfs_extlen_t i; char *p; for (i = 0, p = &dbmap[mp->m_sb.sb_agcount][bno]; i < len; i++, p++) { if ((dbm_t)*p != type) { if (!sflag || CHECK_BLIST(bno + i)) dbprintf(_("rtblock %llu expected type %s got " "%s\n"), bno + i, typename[type], typename[(dbm_t)*p]); error++; } } } static int check_rinomap( xfs_rfsblock_t bno, xfs_extlen_t len, xfs_ino_t c_ino) { xfs_extlen_t i; inodata_t **idp; int rval; if (!check_rrange(bno, len)) { dbprintf(_("rtblocks %llu..%llu claimed by inode %lld\n"), bno, bno + len - 1, c_ino); return 0; } for (i = 0, rval = 1, idp = &inomap[mp->m_sb.sb_agcount][bno]; i < len; i++, idp++) { if (*idp) { if (!sflag || (*idp)->ilist || CHECK_BLIST(bno + i)) dbprintf(_("rtblock %llu claimed by inode %lld, " "previous inum %lld\n"), bno + i, c_ino, (*idp)->ino); error++; rval = 0; } } return rval; } static void check_rootdir(void) { inodata_t *id; id = find_inode(mp->m_sb.sb_rootino, 0); if (id == NULL) { if (!sflag) dbprintf(_("root inode %lld is missing\n"), mp->m_sb.sb_rootino); error++; } else if (!id->isdir) { if (!sflag || id->ilist) dbprintf(_("root inode %lld is not a directory\n"), mp->m_sb.sb_rootino); error++; } } static int check_rrange( xfs_rfsblock_t bno, xfs_extlen_t len) { xfs_extlen_t i; if (bno + len - 1 >= mp->m_sb.sb_rblocks) { for (i = 0; i < len; i++) { if (!sflag || CHECK_BLIST(bno + i)) dbprintf(_("rtblock %llu out of range\n"), bno + i); } error++; return 0; } return 1; } /* * We don't check the accuracy of reference counts -- all we do is ensure * that a data block never crosses with non-data blocks. repair can check * those kinds of things. * * So with that in mind, if we're setting a block to be data or rldata, * don't complain so long as the block is currently unknown, data, or rldata. * Don't let blocks downgrade from rldata -> data. */ static bool is_reflink( dbm_t type2) { if (!xfs_sb_version_hasreflink(&mp->m_sb)) return false; if (type2 == DBM_DATA || type2 == DBM_RLDATA) return true; return false; } static void check_set_dbmap( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type1, dbm_t type2, xfs_agnumber_t c_agno, xfs_agblock_t c_agbno) { xfs_extlen_t i; int mayprint; char *p; if (!check_range(agno, agbno, len)) { dbprintf(_("blocks %u/%u..%u claimed by block %u/%u\n"), agno, agbno, agbno + len - 1, c_agno, c_agbno); return; } check_dbmap(agno, agbno, len, type1, is_reflink(type2)); mayprint = verbose | blist_size; for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { if (*p == DBM_RLDATA && type2 == DBM_DATA) ; /* do nothing */ else if (*p == DBM_DATA && type2 == DBM_DATA) *p = (char)DBM_RLDATA; else *p = (char)type2; if (mayprint && (verbose || CHECK_BLISTA(agno, agbno + i))) dbprintf(_("setting block %u/%u to %s\n"), agno, agbno + i, typename[type2]); } } static void check_set_rdbmap( xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type1, dbm_t type2) { xfs_extlen_t i; int mayprint; char *p; if (!check_rrange(bno, len)) return; check_rdbmap(bno, len, type1); mayprint = verbose | blist_size; for (i = 0, p = &dbmap[mp->m_sb.sb_agcount][bno]; i < len; i++, p++) { *p = (char)type2; if (mayprint && (verbose || CHECK_BLIST(bno + i))) dbprintf(_("setting rtblock %llu to %s\n"), bno + i, typename[type2]); } } static void check_summary(void) { xfs_rfsblock_t bno; xfs_suminfo_t *csp; xfs_suminfo_t *fsp; int log; csp = sumcompute; fsp = sumfile; for (log = 0; log < mp->m_rsumlevels; log++) { for (bno = 0; bno < mp->m_sb.sb_rbmblocks; bno++, csp++, fsp++) { if (*csp != *fsp) { if (!sflag) dbprintf(_("rt summary mismatch, size %d " "block %llu, file: %d, " "computed: %d\n"), log, bno, *fsp, *csp); error++; } } } } static void checknot_dbmap( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, int typemask) { xfs_extlen_t i; char *p; if (!check_range(agno, agbno, len)) return; for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { if ((1 << *p) & typemask) { if (!sflag || CHECK_BLISTA(agno, agbno + i)) dbprintf(_("block %u/%u type %s not expected\n"), agno, agbno + i, typename[(dbm_t)*p]); error++; } } } static void checknot_rdbmap( xfs_rfsblock_t bno, xfs_extlen_t len, int typemask) { xfs_extlen_t i; char *p; if (!check_rrange(bno, len)) return; for (i = 0, p = &dbmap[mp->m_sb.sb_agcount][bno]; i < len; i++, p++) { if ((1 << *p) & typemask) { if (!sflag || CHECK_BLIST(bno + i)) dbprintf(_("rtblock %llu type %s not expected\n"), bno + i, typename[(dbm_t)*p]); error++; } } } static void dir_hash_add( xfs_dahash_t hash, xfs_dir2_dataptr_t addr) { int i; dirhash_t *p; i = DIR_HASH_FUNC(hash, addr); p = malloc(sizeof(*p)); p->next = dirhash[i]; dirhash[i] = p; p->hashval = hash; p->address = addr; p->seen = 0; } static void dir_hash_check( inodata_t *id, int v) { int i; dirhash_t *p; for (i = 0; i < DIR_HASH_SIZE; i++) { for (p = dirhash[i]; p; p = p->next) { if (p->seen) continue; if (!sflag || id->ilist || v) dbprintf(_("dir ino %lld missing leaf entry for " "%x/%x\n"), id->ino, p->hashval, p->address); error++; } } } static void dir_hash_done(void) { int i; dirhash_t *n; dirhash_t *p; for (i = 0; i < DIR_HASH_SIZE; i++) { for (p = dirhash[i]; p; p = n) { n = p->next; free(p); } dirhash[i] = NULL; } } static void dir_hash_init(void) { if (!dirhash) dirhash = calloc(DIR_HASH_SIZE, sizeof(*dirhash)); } static int dir_hash_see( xfs_dahash_t hash, xfs_dir2_dataptr_t addr) { int i; dirhash_t *p; i = DIR_HASH_FUNC(hash, addr); for (p = dirhash[i]; p; p = p->next) { if (p->hashval == hash && p->address == addr) { if (p->seen) return 1; p->seen = 1; return 0; } } return -1; } static inodata_t * find_inode( xfs_ino_t ino, int add) { xfs_agino_t agino; xfs_agnumber_t agno; inodata_t *ent; inodata_t **htab; xfs_agino_t ih; agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); if (agno >= mp->m_sb.sb_agcount || XFS_AGINO_TO_INO(mp, agno, agino) != ino) return NULL; htab = inodata[agno]; ih = agino % inodata_hash_size; ent = htab[ih]; while (ent) { if (ent->ino == ino) return ent; ent = ent->next; } if (!add) return NULL; ent = xcalloc(1, sizeof(*ent)); ent->ino = ino; ent->next = htab[ih]; htab[ih] = ent; return ent; } static void free_inodata( xfs_agnumber_t agno) { inodata_t *hp; inodata_t **ht; int i; inodata_t *next; ht = inodata[agno]; for (i = 0; i < inodata_hash_size; i++) { hp = ht[i]; while (hp) { next = hp->next; if (hp->name) xfree(hp->name); xfree(hp); hp = next; } } xfree(ht); } static int init( int argc, char **argv) { xfs_fsblock_t bno; int c; xfs_ino_t ino; int rt; serious_error = 0; if (mp->m_sb.sb_magicnum != XFS_SB_MAGIC) { dbprintf(_("bad superblock magic number %x, giving up\n"), mp->m_sb.sb_magicnum); serious_error = 1; return 0; } if (!sb_logcheck()) return 0; rt = mp->m_sb.sb_rextents != 0; dbmap = xmalloc((mp->m_sb.sb_agcount + rt) * sizeof(*dbmap)); inomap = xmalloc((mp->m_sb.sb_agcount + rt) * sizeof(*inomap)); inodata = xmalloc(mp->m_sb.sb_agcount * sizeof(*inodata)); inodata_hash_size = (int)MAX(MIN(mp->m_sb.sb_icount / (INODATA_AVG_HASH_LENGTH * mp->m_sb.sb_agcount), MAX_INODATA_HASH_SIZE), MIN_INODATA_HASH_SIZE); for (c = 0; c < mp->m_sb.sb_agcount; c++) { dbmap[c] = xcalloc(mp->m_sb.sb_agblocks, sizeof(**dbmap)); inomap[c] = xcalloc(mp->m_sb.sb_agblocks, sizeof(**inomap)); inodata[c] = xcalloc(inodata_hash_size, sizeof(**inodata)); } if (rt) { dbmap[c] = xcalloc(mp->m_sb.sb_rblocks, sizeof(**dbmap)); inomap[c] = xcalloc(mp->m_sb.sb_rblocks, sizeof(**inomap)); sumfile = xcalloc(mp->m_rsumsize, 1); sumcompute = xcalloc(mp->m_rsumsize, 1); } nflag = sflag = tflag = verbose = optind = 0; while ((c = getopt(argc, argv, "b:i:npstv")) != EOF) { switch (c) { case 'b': bno = strtoll(optarg, NULL, 10); add_blist(bno); break; case 'i': ino = strtoll(optarg, NULL, 10); add_ilist(ino); break; case 'n': nflag = 1; break; case 'p': pflag = 1; break; case 's': sflag = 1; break; case 't': tflag = 1; break; case 'v': verbose = 1; break; default: dbprintf(_("bad option for blockget command\n")); return 0; } } error = sbver_err = serious_error = 0; fdblocks = frextents = icount = ifree = 0; sbversion = XFS_SB_VERSION_4; /* * Note that inoalignmt == 0 is valid when fsb size is large enough for * at least one full inode record per block. Check this case explicitly. */ if (mp->m_sb.sb_inoalignmt || (xfs_sb_version_hasalign(&mp->m_sb) && mp->m_sb.sb_inopblock >= XFS_INODES_PER_CHUNK)) sbversion |= XFS_SB_VERSION_ALIGNBIT; if ((mp->m_sb.sb_uquotino && mp->m_sb.sb_uquotino != NULLFSINO) || (mp->m_sb.sb_gquotino && mp->m_sb.sb_gquotino != NULLFSINO) || (mp->m_sb.sb_pquotino && mp->m_sb.sb_pquotino != NULLFSINO)) sbversion |= XFS_SB_VERSION_QUOTABIT; quota_init(); return 1; } static char * inode_name( xfs_ino_t ino, inodata_t **ipp) { inodata_t *id; char *npath; char *path; id = find_inode(ino, 0); if (ipp) *ipp = id; if (id == NULL) return NULL; if (id->name == NULL) return NULL; path = xstrdup(id->name); while (id->parent) { id = id->parent; if (id->name == NULL) break; npath = prepend_path(path, id->name); xfree(path); path = npath; } return path; } static int ncheck_f( int argc, char **argv) { xfs_agnumber_t agno; int c; inodata_t *hp; inodata_t **ht; int i; inodata_t *id; xfs_ino_t *ilist; int ilist_size; xfs_ino_t *ilp; xfs_ino_t ino; char *p; int security; if (!inodata || !nflag) { dbprintf(_("must run blockget -n first\n")); return 0; } security = optind = ilist_size = 0; ilist = NULL; while ((c = getopt(argc, argv, "i:s")) != EOF) { switch (c) { case 'i': ino = strtoll(optarg, NULL, 10); ilist = xrealloc(ilist, (ilist_size + 1) * sizeof(*ilist)); ilist[ilist_size++] = ino; break; case 's': security = 1; break; default: dbprintf(_("bad option -%c for ncheck command\n"), c); xfree(ilist); return 0; } } if (ilist) { for (ilp = ilist; ilp < &ilist[ilist_size]; ilp++) { ino = *ilp; if ((p = inode_name(ino, &hp))) { dbprintf("%11llu %s", ino, p); if (hp->isdir) dbprintf("/."); dbprintf("\n"); xfree(p); } } xfree(ilist); return 0; } for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { ht = inodata[agno]; for (i = 0; i < inodata_hash_size; i++) { hp = ht[i]; for (hp = ht[i]; hp; hp = hp->next) { ino = XFS_AGINO_TO_INO(mp, agno, hp->ino); p = inode_name(ino, &id); if (!p || !id) continue; if (!security || id->security) { dbprintf("%11llu %s", ino, p); if (hp->isdir) dbprintf("/."); dbprintf("\n"); } xfree(p); } } } return 0; } static char * prepend_path( char *oldpath, char *parent) { int len; char *path; len = (int)(strlen(oldpath) + strlen(parent) + 2); path = xmalloc(len); snprintf(path, len, "%s/%s", parent, oldpath); return path; } static xfs_ino_t process_block_dir_v2( blkmap_t *blkmap, int *dot, int *dotdot, inodata_t *id) { xfs_fsblock_t b; bbmap_t bbmap; bmap_ext_t *bmp; int nex; xfs_ino_t parent; int v; int x; nex = blkmap_getn(blkmap, 0, mp->m_dir_geo->fsbcount, &bmp); v = id->ilist || verbose; if (nex == 0) { if (!sflag || v) dbprintf(_("block 0 for directory inode %lld is " "missing\n"), id->ino); error++; return 0; } push_cur(); if (nex > 1) make_bbmap(&bbmap, nex, bmp); set_cur(&typtab[TYP_DIR2], XFS_FSB_TO_DADDR(mp, bmp->startblock), mp->m_dir_geo->fsbcount * blkbb, DB_RING_IGN, nex > 1 ? &bbmap : NULL); for (x = 0; !v && x < nex; x++) { for (b = bmp[x].startblock; !v && b < bmp[x].startblock + bmp[x].blockcount; b++) v = CHECK_BLIST(b); } free(bmp); if (iocur_top->data == NULL) { if (!sflag || id->ilist || v) dbprintf(_("can't read block 0 for directory inode " "%lld\n"), id->ino); error++; pop_cur(); return 0; } dir_hash_init(); parent = process_data_dir_v2(dot, dotdot, id, v, mp->m_dir_geo->datablk, NULL); dir_hash_check(id, v); dir_hash_done(); pop_cur(); return parent; } static void process_bmbt_reclist( xfs_bmbt_rec_t *rp, int numrecs, dbm_t type, inodata_t *id, xfs_rfsblock_t *tot, blkmap_t **blkmapp) { xfs_agblock_t agbno; xfs_agnumber_t agno; xfs_fsblock_t b; xfs_filblks_t c; xfs_filblks_t cp; int f; int i; xfs_agblock_t iagbno; xfs_agnumber_t iagno; xfs_fileoff_t o; xfs_fileoff_t op; xfs_fsblock_t s; int v; cp = op = 0; v = verbose || id->ilist; iagno = XFS_INO_TO_AGNO(mp, id->ino); iagbno = XFS_INO_TO_AGBNO(mp, id->ino); for (i = 0; i < numrecs; i++, rp++) { convert_extent(rp, &o, &s, &c, &f); if (v) dbprintf(_("inode %lld extent [%lld,%lld,%lld,%d]\n"), id->ino, o, s, c, f); if (!sflag && i > 0 && op + cp > o) dbprintf(_("bmap rec out of order, inode %lld entry %d\n"), id->ino, i); op = o; cp = c; if (type == DBM_RTDATA) { if (!sflag && s >= mp->m_sb.sb_rblocks) { dbprintf(_("inode %lld bad rt block number %lld, " "offset %lld\n"), id->ino, s, o); continue; } } else if (!sflag) { agno = XFS_FSB_TO_AGNO(mp, s); agbno = XFS_FSB_TO_AGBNO(mp, s); if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks) { dbprintf(_("inode %lld bad block number %lld " "[%d,%d], offset %lld\n"), id->ino, s, agno, agbno, o); continue; } if (agbno + c - 1 >= mp->m_sb.sb_agblocks) { dbprintf(_("inode %lld bad block number %lld " "[%d,%d], offset %lld\n"), id->ino, s + c - 1, agno, agbno + (xfs_agblock_t)c - 1, o); continue; } } if (blkmapp && *blkmapp) blkmap_set_ext(blkmapp, (xfs_fileoff_t)o, (xfs_fsblock_t)s, (xfs_extlen_t)c); if (type == DBM_RTDATA) { set_rdbmap((xfs_fsblock_t)s, (xfs_extlen_t)c, DBM_RTDATA); set_rinomap((xfs_fsblock_t)s, (xfs_extlen_t)c, id); for (b = (xfs_fsblock_t)s; blist_size && b < s + c; b++, o++) { if (CHECK_BLIST(b)) dbprintf(_("inode %lld block %lld at " "offset %lld\n"), id->ino, (xfs_fsblock_t)b, o); } } else { agno = XFS_FSB_TO_AGNO(mp, (xfs_fsblock_t)s); agbno = XFS_FSB_TO_AGBNO(mp, (xfs_fsblock_t)s); set_dbmap(agno, agbno, (xfs_extlen_t)c, type, iagno, iagbno); set_inomap(agno, agbno, (xfs_extlen_t)c, id); for (b = (xfs_fsblock_t)s; blist_size && b < s + c; b++, o++, agbno++) { if (CHECK_BLIST(b)) dbprintf(_("inode %lld block %lld at " "offset %lld\n"), id->ino, (xfs_fsblock_t)b, o); } } *tot += c; } } static void process_btinode( inodata_t *id, xfs_dinode_t *dip, dbm_t type, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int whichfork) { xfs_bmdr_block_t *dib; int i; xfs_bmbt_ptr_t *pp; dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); if (be16_to_cpu(dib->bb_level) >= XFS_BM_MAXLEVELS(mp, whichfork)) { if (!sflag || id->ilist) dbprintf(_("level for ino %lld %s fork bmap root too " "large (%u)\n"), id->ino, whichfork == XFS_DATA_FORK ? _("data") : _("attr"), be16_to_cpu(dib->bb_level)); error++; return; } if (be16_to_cpu(dib->bb_numrecs) > libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), be16_to_cpu(dib->bb_level) == 0)) { if (!sflag || id->ilist) dbprintf(_("numrecs for ino %lld %s fork bmap root too " "large (%u)\n"), id->ino, whichfork == XFS_DATA_FORK ? _("data") : _("attr"), be16_to_cpu(dib->bb_numrecs)); error++; return; } if (be16_to_cpu(dib->bb_level) == 0) { xfs_bmbt_rec_t *rp = XFS_BMDR_REC_ADDR(dib, 1); process_bmbt_reclist(rp, be16_to_cpu(dib->bb_numrecs), type, id, totd, blkmapp); *nex += be16_to_cpu(dib->bb_numrecs); return; } else { pp = XFS_BMDR_PTR_ADDR(dib, 1, libxfs_bmdr_maxrecs( XFS_DFORK_SIZE(dip, mp, whichfork), 0)); for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++) scan_lbtree(get_unaligned_be64(&pp[i]), be16_to_cpu(dib->bb_level), scanfunc_bmap, type, id, totd, toti, nex, blkmapp, 1, whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA); } if (*nex <= XFS_DFORK_SIZE(dip, mp, whichfork) / sizeof(xfs_bmbt_rec_t)) { if (!sflag || id->ilist) dbprintf(_("extent count for ino %lld %s fork too low " "(%d) for file format\n"), id->ino, whichfork == XFS_DATA_FORK ? _("data") : _("attr"), *nex); error++; } } static xfs_ino_t process_data_dir_v2( int *dot, int *dotdot, inodata_t *id, int v, xfs_dablk_t dabno, freetab_t **freetabp) { xfs_dir2_dataptr_t addr; xfs_dir2_data_free_t *bf; int bf_err; struct xfs_dir2_data_hdr *block; xfs_dir2_block_tail_t *btp = NULL; inodata_t *cid; int count; struct xfs_dir2_data_hdr *data; xfs_dir2_db_t db; xfs_dir2_data_entry_t *dep; xfs_dir2_data_free_t *dfp; xfs_dir2_data_unused_t *dup; char *endptr; int freeseen; freetab_t *freetab; int i; int lastfree; int lastfree_err; xfs_dir2_leaf_entry_t *lep = NULL; xfs_ino_t lino; xfs_ino_t parent = 0; char *ptr; int stale = 0; int tag_err; __be16 *tagp; struct xfs_name xname; data = iocur_top->data; block = iocur_top->data; if (be32_to_cpu(block->magic) != XFS_DIR2_BLOCK_MAGIC && be32_to_cpu(data->magic) != XFS_DIR2_DATA_MAGIC && be32_to_cpu(block->magic) != XFS_DIR3_BLOCK_MAGIC && be32_to_cpu(data->magic) != XFS_DIR3_DATA_MAGIC) { if (!sflag || v) dbprintf(_("bad directory data magic # %#x for dir ino " "%lld block %d\n"), be32_to_cpu(data->magic), id->ino, dabno); error++; return NULLFSINO; } db = xfs_dir2_da_to_db(mp->m_dir_geo, dabno); bf = M_DIROPS(mp)->data_bestfree_p(data); ptr = (char *)M_DIROPS(mp)->data_unused_p(data); if (be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC) { btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); lep = xfs_dir2_block_leaf_p(btp); endptr = (char *)lep; if (endptr <= ptr || endptr > (char *)btp) { endptr = (char *)data + mp->m_dir_geo->blksize; lep = NULL; if (!sflag || v) dbprintf(_("bad block directory tail for dir ino " "%lld\n"), id->ino); error++; } } else endptr = (char *)data + mp->m_dir_geo->blksize; bf_err = lastfree_err = tag_err = 0; count = lastfree = freeseen = 0; if (be16_to_cpu(bf[0].length) == 0) { bf_err += be16_to_cpu(bf[0].offset) != 0; freeseen |= 1 << 0; } if (be16_to_cpu(bf[1].length) == 0) { bf_err += be16_to_cpu(bf[1].offset) != 0; freeseen |= 1 << 1; } if (be16_to_cpu(bf[2].length) == 0) { bf_err += be16_to_cpu(bf[2].offset) != 0; freeseen |= 1 << 2; } bf_err += be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length); bf_err += be16_to_cpu(bf[1].length) < be16_to_cpu(bf[2].length); if (freetabp) { freetab = *freetabp; if (freetab->naents <= db) { *freetabp = freetab = realloc(freetab, FREETAB_SIZE(db + 1)); for (i = freetab->naents; i < db; i++) freetab->ents[i] = NULLDATAOFF; freetab->naents = db + 1; } if (freetab->nents < db + 1) freetab->nents = db + 1; freetab->ents[db] = be16_to_cpu(bf[0].length); } while (ptr < endptr) { dup = (xfs_dir2_data_unused_t *)ptr; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { lastfree_err += lastfree != 0; tagp = xfs_dir2_data_unused_tag_p(dup); if ((be16_to_cpu(dup->length) & (XFS_DIR2_DATA_ALIGN - 1)) || be16_to_cpu(dup->length) == 0 || (char *)tagp >= endptr) { if (!sflag || v) dbprintf(_("dir %lld block %d bad free " "entry at %d\n"), id->ino, dabno, (int)((char *)dup - (char *)data)); error++; break; } tag_err += be16_to_cpu(*tagp) != (char *)dup - (char *)data; dfp = process_data_dir_v2_freefind(data, dup); if (dfp) { i = (int)(dfp - bf); bf_err += (freeseen & (1 << i)) != 0; freeseen |= 1 << i; } else bf_err += be16_to_cpu(dup->length) > be16_to_cpu(bf[2].length); ptr += be16_to_cpu(dup->length); lastfree = 1; continue; } dep = (xfs_dir2_data_entry_t *)dup; if (dep->namelen == 0) { if (!sflag || v) dbprintf(_("dir %lld block %d zero length entry " "at %d\n"), id->ino, dabno, (int)((char *)dep - (char *)data)); error++; } tagp = M_DIROPS(mp)->data_entry_tag_p(dep); if ((char *)tagp >= endptr) { if (!sflag || v) dbprintf(_("dir %lld block %d bad entry at %d\n"), id->ino, dabno, (int)((char *)dep - (char *)data)); error++; break; } tag_err += be16_to_cpu(*tagp) != (char *)dep - (char *)data; addr = xfs_dir2_db_off_to_dataptr(mp->m_dir_geo, db, (char *)dep - (char *)data); xname.name = dep->name; xname.len = dep->namelen; dir_hash_add(mp->m_dirnameops->hashname(&xname), addr); ptr += M_DIROPS(mp)->data_entsize(dep->namelen); count++; lastfree = 0; lino = be64_to_cpu(dep->inumber); cid = find_inode(lino, 1); if (v) dbprintf(_("dir %lld block %d entry %*.*s %lld\n"), id->ino, dabno, dep->namelen, dep->namelen, dep->name, lino); if (cid) addlink_inode(cid); else { if (!sflag || v) dbprintf(_("dir %lld block %d entry %*.*s bad " "inode number %lld\n"), id->ino, dabno, dep->namelen, dep->namelen, dep->name, lino); error++; } if (dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.') { if (parent) { if (!sflag || v) dbprintf(_("multiple .. entries in dir " "%lld (%lld, %lld)\n"), id->ino, parent, lino); error++; } else parent = cid ? lino : NULLFSINO; (*dotdot)++; } else if (dep->namelen != 1 || dep->name[0] != '.') { if (cid != NULL) { if (!cid->parent) cid->parent = id; addname_inode(cid, (char *)dep->name, dep->namelen); } } else { if (lino != id->ino) { if (!sflag || v) dbprintf(_("dir %lld entry . inode " "number mismatch (%lld)\n"), id->ino, lino); error++; } (*dot)++; } } if (be32_to_cpu(data->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(data->magic) == XFS_DIR3_BLOCK_MAGIC) { endptr = (char *)data + mp->m_dir_geo->blksize; for (i = stale = 0; lep && i < be32_to_cpu(btp->count); i++) { if ((char *)&lep[i] >= endptr) { if (!sflag || v) dbprintf(_("dir %lld block %d bad count " "%u\n"), id->ino, dabno, be32_to_cpu(btp->count)); error++; break; } if (be32_to_cpu(lep[i].address) == XFS_DIR2_NULL_DATAPTR) stale++; else if (dir_hash_see(be32_to_cpu(lep[i].hashval), be32_to_cpu(lep[i].address))) { if (!sflag || v) dbprintf(_("dir %lld block %d extra leaf " "entry %x %x\n"), id->ino, dabno, be32_to_cpu(lep[i].hashval), be32_to_cpu(lep[i].address)); error++; } } } bf_err += freeseen != 7; if (bf_err) { if (!sflag || v) dbprintf(_("dir %lld block %d bad bestfree data\n"), id->ino, dabno); error++; } if ((be32_to_cpu(data->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(data->magic) == XFS_DIR3_BLOCK_MAGIC) && count != be32_to_cpu(btp->count) - be32_to_cpu(btp->stale)) { if (!sflag || v) dbprintf(_("dir %lld block %d bad block tail count %d " "(stale %d)\n"), id->ino, dabno, be32_to_cpu(btp->count), be32_to_cpu(btp->stale)); error++; } if ((be32_to_cpu(data->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(data->magic) == XFS_DIR2_BLOCK_MAGIC) && stale != be32_to_cpu(btp->stale)) { if (!sflag || v) dbprintf(_("dir %lld block %d bad stale tail count %d\n"), id->ino, dabno, be32_to_cpu(btp->stale)); error++; } if (lastfree_err) { if (!sflag || v) dbprintf(_("dir %lld block %d consecutive free entries\n"), id->ino, dabno); error++; } if (tag_err) { if (!sflag || v) dbprintf(_("dir %lld block %d entry/unused tag " "mismatch\n"), id->ino, dabno); error++; } return parent; } static xfs_dir2_data_free_t * process_data_dir_v2_freefind( struct xfs_dir2_data_hdr *data, xfs_dir2_data_unused_t *dup) { struct xfs_dir2_data_free *bf; struct xfs_dir2_data_free *dfp; xfs_dir2_data_aoff_t off; off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)data); bf = M_DIROPS(mp)->data_bestfree_p(data); if (be16_to_cpu(dup->length) < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length)) return NULL; for (dfp = bf; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) { if (be16_to_cpu(dfp->offset) == 0) return NULL; if (be16_to_cpu(dfp->offset) == off) return dfp; } return NULL; } static void process_dir( xfs_dinode_t *dip, blkmap_t *blkmap, inodata_t *id) { xfs_fsblock_t bno; int dot; int dotdot; xfs_ino_t parent; dot = dotdot = 0; if (process_dir_v2(dip, blkmap, &dot, &dotdot, id, &parent)) return; bno = XFS_INO_TO_FSB(mp, id->ino); if (dot == 0) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("no . entry for directory %lld\n"), id->ino); error++; } if (dotdot == 0) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("no .. entry for directory %lld\n"), id->ino); error++; } else if (parent == id->ino && id->ino != mp->m_sb.sb_rootino) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_(". and .. same for non-root directory %lld\n"), id->ino); error++; } else if (id->ino == mp->m_sb.sb_rootino && id->ino != parent) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("root directory %lld has .. %lld\n"), id->ino, parent); error++; } else if (parent != NULLFSINO && id->ino != parent) addparent_inode(id, parent); } static int process_dir_v2( xfs_dinode_t *dip, blkmap_t *blkmap, int *dot, int *dotdot, inodata_t *id, xfs_ino_t *parent) { xfs_fileoff_t last = 0; xfs_fsize_t size = be64_to_cpu(dip->di_size); if (blkmap) last = blkmap_last_off(blkmap); if (size <= XFS_DFORK_DSIZE(dip, mp) && dip->di_format == XFS_DINODE_FMT_LOCAL) *parent = process_sf_dir_v2(dip, dot, dotdot, id); else if (last == mp->m_dir_geo->fsbcount && (dip->di_format == XFS_DINODE_FMT_EXTENTS || dip->di_format == XFS_DINODE_FMT_BTREE)) *parent = process_block_dir_v2(blkmap, dot, dotdot, id); else if (last >= mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount && (dip->di_format == XFS_DINODE_FMT_EXTENTS || dip->di_format == XFS_DINODE_FMT_BTREE)) *parent = process_leaf_node_dir_v2(blkmap, dot, dotdot, id, size); else { dbprintf(_("bad size (%lld) or format (%d) for directory inode " "%lld\n"), size, dip->di_format, id->ino); error++; return 1; } return 0; } /* ARGSUSED */ static void process_exinode( inodata_t *id, xfs_dinode_t *dip, dbm_t type, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int whichfork) { xfs_bmbt_rec_t *rp; rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork); *nex = XFS_DFORK_NEXTENTS(dip, whichfork); if (*nex < 0 || *nex > XFS_DFORK_SIZE(dip, mp, whichfork) / sizeof(xfs_bmbt_rec_t)) { if (!sflag || id->ilist) dbprintf(_("bad number of extents %d for inode %lld\n"), *nex, id->ino); error++; return; } process_bmbt_reclist(rp, *nex, type, id, totd, blkmapp); } static void process_inode( xfs_agf_t *agf, xfs_agino_t agino, xfs_dinode_t *dip, int isfree) { blkmap_t *blkmap; xfs_fsblock_t bno = 0; struct xfs_inode xino; inodata_t *id = NULL; xfs_ino_t ino; xfs_extnum_t nextents = 0; int security; xfs_rfsblock_t totblocks; xfs_rfsblock_t totdblocks = 0; xfs_rfsblock_t totiblocks = 0; dbm_t type; xfs_extnum_t anextents = 0; xfs_rfsblock_t atotdblocks = 0; xfs_rfsblock_t atotiblocks = 0; xfs_qcnt_t bc = 0; xfs_qcnt_t ic = 0; xfs_qcnt_t rc = 0; xfs_dqid_t dqprid; int v = 0; mode_t mode; static char okfmts[] = { 0, /* type 0 unused */ 1 << XFS_DINODE_FMT_DEV, /* FIFO */ 1 << XFS_DINODE_FMT_DEV, /* CHR */ 0, /* type 3 unused */ (1 << XFS_DINODE_FMT_LOCAL) | (1 << XFS_DINODE_FMT_EXTENTS) | (1 << XFS_DINODE_FMT_BTREE), /* DIR */ 0, /* type 5 unused */ 1 << XFS_DINODE_FMT_DEV, /* BLK */ 0, /* type 7 unused */ (1 << XFS_DINODE_FMT_EXTENTS) | (1 << XFS_DINODE_FMT_BTREE), /* REG */ 0, /* type 9 unused */ (1 << XFS_DINODE_FMT_LOCAL) | (1 << XFS_DINODE_FMT_EXTENTS), /* LNK */ 0, /* type 11 unused */ 1 << XFS_DINODE_FMT_DEV, /* SOCK */ 0, /* type 13 unused */ 1 << XFS_DINODE_FMT_UUID, /* MNT */ 0 /* type 15 unused */ }; static char *fmtnames[] = { "dev", "local", "extents", "btree", "uuid" }; libxfs_inode_from_disk(&xino, dip); ino = XFS_AGINO_TO_INO(mp, be32_to_cpu(agf->agf_seqno), agino); if (!isfree) { id = find_inode(ino, 1); bno = XFS_INO_TO_FSB(mp, ino); blkmap = NULL; } v = (!sflag || (id && id->ilist) || CHECK_BLIST(bno)); if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) { if (isfree || v) dbprintf(_("bad magic number %#x for inode %lld\n"), be16_to_cpu(dip->di_magic), ino); error++; return; } if (!libxfs_dinode_good_version(mp, xino.i_d.di_version)) { if (isfree || v) dbprintf(_("bad version number %#x for inode %lld\n"), xino.i_d.di_version, ino); error++; return; } if (isfree) { if (xino.i_d.di_nblocks != 0) { if (v) dbprintf(_("bad nblocks %lld for free inode " "%lld\n"), xino.i_d.di_nblocks, ino); error++; } if (dip->di_nlink != 0) { if (v) dbprintf(_("bad nlink %d for free inode %lld\n"), be32_to_cpu(dip->di_nlink), ino); error++; } if (dip->di_mode != 0) { if (v) dbprintf(_("bad mode %#o for free inode %lld\n"), be16_to_cpu(dip->di_mode), ino); error++; } return; } if (be32_to_cpu(dip->di_next_unlinked) != NULLAGINO) { if (v) dbprintf(_("bad next unlinked %#x for inode %lld\n"), be32_to_cpu(dip->di_next_unlinked), ino); error++; } /* * di_mode is a 16-bit uint so no need to check the < 0 case */ mode = be16_to_cpu(dip->di_mode); if ((((mode & S_IFMT) >> 12) > 15) || (!(okfmts[(mode & S_IFMT) >> 12] & (1 << xino.i_d.di_format)))) { if (v) dbprintf(_("bad format %d for inode %lld type %#o\n"), xino.i_d.di_format, id->ino, mode & S_IFMT); error++; return; } if ((unsigned int)XFS_DFORK_ASIZE(dip, mp) >= XFS_LITINO(mp, xino.i_d.di_version)) { if (v) dbprintf(_("bad fork offset %d for inode %lld\n"), xino.i_d.di_forkoff, id->ino); error++; return; } if ((unsigned int)xino.i_d.di_aformat > XFS_DINODE_FMT_BTREE) { if (v) dbprintf(_("bad attribute format %d for inode %lld\n"), xino.i_d.di_aformat, id->ino); error++; return; } if (verbose || (id && id->ilist) || CHECK_BLIST(bno)) dbprintf(_("inode %lld mode %#o fmt %s " "afmt %s " "nex %d anex %d nblk %lld sz %lld%s%s%s%s%s%s%s\n"), id->ino, mode, fmtnames[(int)xino.i_d.di_format], fmtnames[(int)xino.i_d.di_aformat], xino.i_d.di_nextents, xino.i_d.di_anextents, xino.i_d.di_nblocks, xino.i_d.di_size, xino.i_d.di_flags & XFS_DIFLAG_REALTIME ? " rt" : "", xino.i_d.di_flags & XFS_DIFLAG_PREALLOC ? " pre" : "", xino.i_d.di_flags & XFS_DIFLAG_IMMUTABLE? " imm" : "", xino.i_d.di_flags & XFS_DIFLAG_APPEND ? " app" : "", xino.i_d.di_flags & XFS_DIFLAG_SYNC ? " syn" : "", xino.i_d.di_flags & XFS_DIFLAG_NOATIME ? " noa" : "", xino.i_d.di_flags & XFS_DIFLAG_NODUMP ? " nod" : ""); security = 0; switch (mode & S_IFMT) { case S_IFDIR: type = DBM_DIR; if (xino.i_d.di_format == XFS_DINODE_FMT_LOCAL) break; blkmap = blkmap_alloc(xino.i_d.di_nextents); break; case S_IFREG: if (xino.i_d.di_flags & XFS_DIFLAG_REALTIME) type = DBM_RTDATA; else if (id->ino == mp->m_sb.sb_rbmino) { type = DBM_RTBITMAP; blkmap = blkmap_alloc(xino.i_d.di_nextents); addlink_inode(id); } else if (id->ino == mp->m_sb.sb_rsumino) { type = DBM_RTSUM; blkmap = blkmap_alloc(xino.i_d.di_nextents); addlink_inode(id); } else if (id->ino == mp->m_sb.sb_uquotino || id->ino == mp->m_sb.sb_gquotino || id->ino == mp->m_sb.sb_pquotino) { type = DBM_QUOTA; blkmap = blkmap_alloc(xino.i_d.di_nextents); addlink_inode(id); } else type = DBM_DATA; if (mode & (S_ISUID | S_ISGID)) security = 1; break; case S_IFLNK: type = DBM_SYMLINK; break; default: security = 1; type = DBM_UNKNOWN; break; } id->isreflink = !!(xino.i_d.di_flags2 & XFS_DIFLAG2_REFLINK); setlink_inode(id, VFS_I(&xino)->i_nlink, type == DBM_DIR, security); switch (xino.i_d.di_format) { case XFS_DINODE_FMT_LOCAL: process_lclinode(id, dip, type, &totdblocks, &totiblocks, &nextents, &blkmap, XFS_DATA_FORK); break; case XFS_DINODE_FMT_EXTENTS: process_exinode(id, dip, type, &totdblocks, &totiblocks, &nextents, &blkmap, XFS_DATA_FORK); break; case XFS_DINODE_FMT_BTREE: process_btinode(id, dip, type, &totdblocks, &totiblocks, &nextents, &blkmap, XFS_DATA_FORK); break; } if (XFS_DFORK_Q(dip)) { sbversion |= XFS_SB_VERSION_ATTRBIT; switch (xino.i_d.di_aformat) { case XFS_DINODE_FMT_LOCAL: process_lclinode(id, dip, DBM_ATTR, &atotdblocks, &atotiblocks, &anextents, NULL, XFS_ATTR_FORK); break; case XFS_DINODE_FMT_EXTENTS: process_exinode(id, dip, DBM_ATTR, &atotdblocks, &atotiblocks, &anextents, NULL, XFS_ATTR_FORK); break; case XFS_DINODE_FMT_BTREE: process_btinode(id, dip, DBM_ATTR, &atotdblocks, &atotiblocks, &anextents, NULL, XFS_ATTR_FORK); break; } } if (qgdo || qpdo || qudo) { switch (type) { case DBM_DATA: case DBM_DIR: case DBM_RTBITMAP: case DBM_RTSUM: case DBM_SYMLINK: case DBM_UNKNOWN: bc = totdblocks + totiblocks + atotdblocks + atotiblocks; ic = 1; break; case DBM_RTDATA: bc = totiblocks + atotdblocks + atotiblocks; rc = totdblocks; ic = 1; break; default: break; } if (ic) { dqprid = xfs_get_projid(&xino.i_d); /* dquot ID is u32 */ quota_add(&dqprid, &xino.i_d.di_gid, &xino.i_d.di_uid, 0, bc, ic, rc); } } totblocks = totdblocks + totiblocks + atotdblocks + atotiblocks; if (totblocks != xino.i_d.di_nblocks) { if (v) dbprintf(_("bad nblocks %lld for inode %lld, counted " "%lld\n"), xino.i_d.di_nblocks, id->ino, totblocks); error++; } if (nextents != xino.i_d.di_nextents) { if (v) dbprintf(_("bad nextents %d for inode %lld, counted %d\n"), xino.i_d.di_nextents, id->ino, nextents); error++; } if (anextents != xino.i_d.di_anextents) { if (v) dbprintf(_("bad anextents %d for inode %lld, counted " "%d\n"), xino.i_d.di_anextents, id->ino, anextents); error++; } if (type == DBM_DIR) process_dir(dip, blkmap, id); else if (type == DBM_RTBITMAP) process_rtbitmap(blkmap); else if (type == DBM_RTSUM) process_rtsummary(blkmap); /* * If the CHKD flag is not set, this can legitimately contain garbage; * xfs_repair may have cleared that bit. */ else if (type == DBM_QUOTA) { if (id->ino == mp->m_sb.sb_uquotino && (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) && (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD)) process_quota(IS_USER_QUOTA, id, blkmap); else if (id->ino == mp->m_sb.sb_gquotino && (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) && (mp->m_sb.sb_qflags & XFS_GQUOTA_CHKD)) process_quota(IS_GROUP_QUOTA, id, blkmap); else if (id->ino == mp->m_sb.sb_pquotino && (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) && (mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD)) process_quota(IS_PROJECT_QUOTA, id, blkmap); } if (blkmap) blkmap_free(blkmap); } /* ARGSUSED */ static void process_lclinode( inodata_t *id, xfs_dinode_t *dip, dbm_t type, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int whichfork) { xfs_attr_shortform_t *asf; xfs_fsblock_t bno; bno = XFS_INO_TO_FSB(mp, id->ino); if (whichfork == XFS_DATA_FORK && be64_to_cpu(dip->di_size) > XFS_DFORK_DSIZE(dip, mp)) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("local inode %lld data is too large (size " "%lld)\n"), id->ino, be64_to_cpu(dip->di_size)); error++; } else if (whichfork == XFS_ATTR_FORK) { asf = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); if (be16_to_cpu(asf->hdr.totsize) > XFS_DFORK_ASIZE(dip, mp)) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("local inode %lld attr is too large " "(size %d)\n"), id->ino, be16_to_cpu(asf->hdr.totsize)); error++; } } } static xfs_ino_t process_leaf_node_dir_v2( blkmap_t *blkmap, int *dot, int *dotdot, inodata_t *id, xfs_fsize_t dirsize) { xfs_fsblock_t b; bbmap_t bbmap; bmap_ext_t *bmp; xfs_fileoff_t dbno; freetab_t *freetab; int i; xfs_ino_t lino; int nex; xfs_ino_t parent; int t = 0; int v; int v2; int x; v2 = verbose || id->ilist; v = parent = 0; dbno = NULLFILEOFF; freetab = malloc(FREETAB_SIZE(dirsize / mp->m_dir_geo->blksize)); freetab->naents = (int)(dirsize / mp->m_dir_geo->blksize); freetab->nents = 0; for (i = 0; i < freetab->naents; i++) freetab->ents[i] = NULLDATAOFF; dir_hash_init(); while ((dbno = blkmap_next_off(blkmap, dbno, &t)) != NULLFILEOFF) { nex = blkmap_getn(blkmap, dbno, mp->m_dir_geo->fsbcount, &bmp); ASSERT(nex > 0); for (v = v2, x = 0; !v && x < nex; x++) { for (b = bmp[x].startblock; !v && b < bmp[x].startblock + bmp[x].blockcount; b++) v = CHECK_BLIST(b); } if (v) dbprintf(_("dir inode %lld block %u=%llu\n"), id->ino, (__uint32_t)dbno, (xfs_fsblock_t)bmp->startblock); push_cur(); if (nex > 1) make_bbmap(&bbmap, nex, bmp); set_cur(&typtab[TYP_DIR2], XFS_FSB_TO_DADDR(mp, bmp->startblock), mp->m_dir_geo->fsbcount * blkbb, DB_RING_IGN, nex > 1 ? &bbmap : NULL); free(bmp); if (iocur_top->data == NULL) { if (!sflag || v) dbprintf(_("can't read block %u for directory " "inode %lld\n"), (__uint32_t)dbno, id->ino); error++; pop_cur(); dbno += mp->m_dir_geo->fsbcount - 1; continue; } if (dbno < mp->m_dir_geo->leafblk) { lino = process_data_dir_v2(dot, dotdot, id, v, (xfs_dablk_t)dbno, &freetab); if (lino) { if (parent) { if (!sflag || v) dbprintf(_("multiple .. entries " "in dir %lld\n"), id->ino); error++; } else parent = lino; } } else if (dbno < mp->m_dir_geo->freeblk) { process_leaf_node_dir_v2_int(id, v, (xfs_dablk_t)dbno, freetab); } else { process_leaf_node_dir_v2_free(id, v, (xfs_dablk_t)dbno, freetab); } pop_cur(); dbno += mp->m_dir_geo->fsbcount - 1; } dir_hash_check(id, v); dir_hash_done(); for (i = 0; i < freetab->nents; i++) { if (freetab->ents[i] != NULLDATAOFF) { if (!sflag || v) dbprintf(_("missing free index for data block %d " "in dir ino %lld\n"), xfs_dir2_db_to_da(mp->m_dir_geo, i), id->ino); error++; } } free(freetab); return parent; } static void process_leaf_node_dir_v3_free( inodata_t *id, int v, xfs_dablk_t dabno, freetab_t *freetab) { xfs_dir2_data_off_t ent; struct xfs_dir3_free *free; int i; int maxent; int used; free = iocur_top->data; maxent = M_DIROPS(mp)->free_max_bests(mp->m_dir_geo); if (be32_to_cpu(free->hdr.firstdb) != xfs_dir2_da_to_db(mp->m_dir_geo, dabno - mp->m_dir_geo->freeblk) * maxent) { if (!sflag || v) dbprintf(_("bad free block firstdb %d for dir ino %lld " "block %d\n"), be32_to_cpu(free->hdr.firstdb), id->ino, dabno); error++; return; } if (be32_to_cpu(free->hdr.nvalid) > maxent || be32_to_cpu(free->hdr.nused) > maxent || be32_to_cpu(free->hdr.nused) > be32_to_cpu(free->hdr.nvalid)) { if (!sflag || v) dbprintf(_("bad free block nvalid/nused %d/%d for dir " "ino %lld block %d\n"), be32_to_cpu(free->hdr.nvalid), be32_to_cpu(free->hdr.nused), id->ino, dabno); error++; return; } for (used = i = 0; i < be32_to_cpu(free->hdr.nvalid); i++) { if (freetab->nents <= be32_to_cpu(free->hdr.firstdb) + i) ent = NULLDATAOFF; else ent = freetab->ents[be32_to_cpu(free->hdr.firstdb) + i]; if (ent != be16_to_cpu(free->bests[i])) { if (!sflag || v) dbprintf(_("bad free block ent %d is %d should " "be %d for dir ino %lld block %d\n"), i, be16_to_cpu(free->bests[i]), ent, id->ino, dabno); error++; } if (be16_to_cpu(free->bests[i]) != NULLDATAOFF) used++; if (ent != NULLDATAOFF) freetab->ents[be32_to_cpu(free->hdr.firstdb) + i] = NULLDATAOFF; } if (used != be32_to_cpu(free->hdr.nused)) { if (!sflag || v) dbprintf(_("bad free block nused %d should be %d for dir " "ino %lld block %d\n"), be32_to_cpu(free->hdr.nused), used, id->ino, dabno); error++; } } static void process_leaf_node_dir_v2_free( inodata_t *id, int v, xfs_dablk_t dabno, freetab_t *freetab) { xfs_dir2_data_off_t ent; xfs_dir2_free_t *free; int i; int maxent; int used; free = iocur_top->data; if (be32_to_cpu(free->hdr.magic) != XFS_DIR2_FREE_MAGIC && be32_to_cpu(free->hdr.magic) != XFS_DIR3_FREE_MAGIC) { if (!sflag || v) dbprintf(_("bad free block magic # %#x for dir ino %lld " "block %d\n"), be32_to_cpu(free->hdr.magic), id->ino, dabno); error++; return; } if (be32_to_cpu(free->hdr.magic) == XFS_DIR3_FREE_MAGIC) { process_leaf_node_dir_v3_free(id, v, dabno, freetab); return; } maxent = M_DIROPS(mp)->free_max_bests(mp->m_dir_geo); if (be32_to_cpu(free->hdr.firstdb) != xfs_dir2_da_to_db(mp->m_dir_geo, dabno - mp->m_dir_geo->freeblk) * maxent) { if (!sflag || v) dbprintf(_("bad free block firstdb %d for dir ino %lld " "block %d\n"), be32_to_cpu(free->hdr.firstdb), id->ino, dabno); error++; return; } if (be32_to_cpu(free->hdr.nvalid) > maxent || be32_to_cpu(free->hdr.nvalid) < 0 || be32_to_cpu(free->hdr.nused) > maxent || be32_to_cpu(free->hdr.nused) < 0 || be32_to_cpu(free->hdr.nused) > be32_to_cpu(free->hdr.nvalid)) { if (!sflag || v) dbprintf(_("bad free block nvalid/nused %d/%d for dir " "ino %lld block %d\n"), be32_to_cpu(free->hdr.nvalid), be32_to_cpu(free->hdr.nused), id->ino, dabno); error++; return; } for (used = i = 0; i < be32_to_cpu(free->hdr.nvalid); i++) { if (freetab->nents <= be32_to_cpu(free->hdr.firstdb) + i) ent = NULLDATAOFF; else ent = freetab->ents[be32_to_cpu(free->hdr.firstdb) + i]; if (ent != be16_to_cpu(free->bests[i])) { if (!sflag || v) dbprintf(_("bad free block ent %d is %d should " "be %d for dir ino %lld block %d\n"), i, be16_to_cpu(free->bests[i]), ent, id->ino, dabno); error++; } if (be16_to_cpu(free->bests[i]) != NULLDATAOFF) used++; if (ent != NULLDATAOFF) freetab->ents[be32_to_cpu(free->hdr.firstdb) + i] = NULLDATAOFF; } if (used != be32_to_cpu(free->hdr.nused)) { if (!sflag || v) dbprintf(_("bad free block nused %d should be %d for dir " "ino %lld block %d\n"), be32_to_cpu(free->hdr.nused), used, id->ino, dabno); error++; } } /* * Get address of the bestcount field in the single-leaf block. */ static inline int xfs_dir3_leaf_ents_count(struct xfs_dir2_leaf *lp) { if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp; return be16_to_cpu(lp3->hdr.count); } return be16_to_cpu(lp->hdr.count); } static void process_leaf_node_dir_v2_int( inodata_t *id, int v, xfs_dablk_t dabno, freetab_t *freetab) { int i; __be16 *lbp; xfs_dir2_leaf_t *leaf; struct xfs_dir3_leaf *leaf3 = NULL; xfs_dir2_leaf_entry_t *lep; xfs_dir2_leaf_tail_t *ltp; xfs_da_intnode_t *node; int stale; struct xfs_da3_icnode_hdr nodehdr; leaf = iocur_top->data; switch (be16_to_cpu(leaf->hdr.info.magic)) { case XFS_DIR3_LEAF1_MAGIC: case XFS_DIR3_LEAFN_MAGIC: case XFS_DA3_NODE_MAGIC: leaf3 = iocur_top->data; break; } switch (be16_to_cpu(leaf->hdr.info.magic)) { case XFS_DIR2_LEAF1_MAGIC: case XFS_DIR3_LEAF1_MAGIC: if (be32_to_cpu(leaf->hdr.info.forw) || be32_to_cpu(leaf->hdr.info.back)) { if (!sflag || v) dbprintf(_("bad leaf block forw/back pointers " "%d/%d for dir ino %lld block %d\n"), be32_to_cpu(leaf->hdr.info.forw), be32_to_cpu(leaf->hdr.info.back), id->ino, dabno); error++; } if (dabno != mp->m_dir_geo->leafblk) { if (!sflag || v) dbprintf(_("single leaf block for dir ino %lld " "block %d should be at block %d\n"), id->ino, dabno, (xfs_dablk_t)mp->m_dir_geo->leafblk); error++; } ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); lbp = xfs_dir2_leaf_bests_p(ltp); for (i = 0; i < be32_to_cpu(ltp->bestcount); i++) { if (freetab->nents <= i || freetab->ents[i] != be16_to_cpu(lbp[i])) { if (!sflag || v) dbprintf(_("bestfree %d for dir ino %lld " "block %d doesn't match table " "value %d\n"), freetab->nents <= i ? NULLDATAOFF : freetab->ents[i], id->ino, xfs_dir2_db_to_da(mp->m_dir_geo, i), be16_to_cpu(lbp[i])); } if (freetab->nents > i) freetab->ents[i] = NULLDATAOFF; } break; case XFS_DIR2_LEAFN_MAGIC: case XFS_DIR3_LEAFN_MAGIC: /* if it's at the root location then we can check the * pointers are null XXX */ break; case XFS_DA_NODE_MAGIC: case XFS_DA3_NODE_MAGIC: node = iocur_top->data; M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node); if (nodehdr.level < 1 || nodehdr.level > XFS_DA_NODE_MAXDEPTH) { if (!sflag || v) dbprintf(_("bad node block level %d for dir ino " "%lld block %d\n"), nodehdr.level, id->ino, dabno); error++; } return; default: if (!sflag || v) dbprintf(_("bad directory data magic # %#x for dir ino " "%lld block %d\n"), be16_to_cpu(leaf->hdr.info.magic), id->ino, dabno); error++; return; } lep = M_DIROPS(mp)->leaf_ents_p(leaf); for (i = stale = 0; i < xfs_dir3_leaf_ents_count(leaf); i++) { if (be32_to_cpu(lep[i].address) == XFS_DIR2_NULL_DATAPTR) stale++; else if (dir_hash_see(be32_to_cpu(lep[i].hashval), be32_to_cpu(lep[i].address))) { if (!sflag || v) dbprintf(_("dir %lld block %d extra leaf entry " "%x %x\n"), id->ino, dabno, be32_to_cpu(lep[i].hashval), be32_to_cpu(lep[i].address)); error++; } } if (leaf3 && stale != be16_to_cpu(leaf3->hdr.stale)) { if (!sflag || v) dbprintf(_("dir3 %lld block %d stale mismatch " "%d/%d\n"), id->ino, dabno, stale, be16_to_cpu(leaf3->hdr.stale)); error++; } else if (!leaf && stale != be16_to_cpu(leaf->hdr.stale)) { if (!sflag || v) dbprintf(_("dir %lld block %d stale mismatch " "%d/%d\n"), id->ino, dabno, stale, be16_to_cpu(leaf->hdr.stale)); error++; } } static void process_quota( qtype_t qtype, inodata_t *id, blkmap_t *blkmap) { xfs_fsblock_t bno; int cb; xfs_dqblk_t *dqb; xfs_dqid_t dqid; u_int8_t exp_flags = 0; uint i; uint perblock; xfs_fileoff_t qbno; char *s = NULL; int scicb; int t = 0; switch (qtype) { case IS_USER_QUOTA: s = "user"; exp_flags = XFS_DQ_USER; break; case IS_PROJECT_QUOTA: s = "project"; exp_flags = XFS_DQ_PROJ; break; case IS_GROUP_QUOTA: s = "group"; exp_flags = XFS_DQ_GROUP; break; default: ASSERT(0); } perblock = (uint)(mp->m_sb.sb_blocksize / sizeof(*dqb)); dqid = 0; qbno = NULLFILEOFF; while ((qbno = blkmap_next_off(blkmap, qbno, &t)) != NULLFILEOFF) { bno = blkmap_get(blkmap, qbno); dqid = (xfs_dqid_t)qbno * perblock; cb = CHECK_BLIST(bno); scicb = !sflag || id->ilist || cb; push_cur(); set_cur(&typtab[TYP_DQBLK], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_IGN, NULL); if ((dqb = iocur_top->data) == NULL) { if (scicb) dbprintf(_("can't read block %lld for %s quota " "inode (fsblock %lld)\n"), (xfs_fileoff_t)qbno, s, (xfs_fsblock_t)bno); error++; pop_cur(); continue; } for (i = 0; i < perblock; i++, dqid++, dqb++) { if (verbose || id->ilist || cb) dbprintf(_("%s dqblk %lld entry %d id %u bc " "%lld ic %lld rc %lld\n"), s, (xfs_fileoff_t)qbno, i, dqid, be64_to_cpu(dqb->dd_diskdq.d_bcount), be64_to_cpu(dqb->dd_diskdq.d_icount), be64_to_cpu(dqb->dd_diskdq.d_rtbcount)); if (be16_to_cpu(dqb->dd_diskdq.d_magic) != XFS_DQUOT_MAGIC) { if (scicb) dbprintf(_("bad magic number %#x for %s " "dqblk %lld entry %d id %u\n"), be16_to_cpu(dqb->dd_diskdq.d_magic), s, (xfs_fileoff_t)qbno, i, dqid); error++; continue; } if (dqb->dd_diskdq.d_version != XFS_DQUOT_VERSION) { if (scicb) dbprintf(_("bad version number %#x for " "%s dqblk %lld entry %d id " "%u\n"), dqb->dd_diskdq.d_version, s, (xfs_fileoff_t)qbno, i, dqid); error++; continue; } if (dqb->dd_diskdq.d_flags != exp_flags) { if (scicb) dbprintf(_("bad flags %#x for %s dqblk " "%lld entry %d id %u\n"), dqb->dd_diskdq.d_flags, s, (xfs_fileoff_t)qbno, i, dqid); error++; continue; } if (be32_to_cpu(dqb->dd_diskdq.d_id) != dqid) { if (scicb) dbprintf(_("bad id %u for %s dqblk %lld " "entry %d id %u\n"), be32_to_cpu(dqb->dd_diskdq.d_id), s, (xfs_fileoff_t)qbno, i, dqid); error++; continue; } quota_add((qtype == IS_PROJECT_QUOTA) ? &dqid : NULL, (qtype == IS_GROUP_QUOTA) ? &dqid : NULL, (qtype == IS_USER_QUOTA) ? &dqid : NULL, 1, be64_to_cpu(dqb->dd_diskdq.d_bcount), be64_to_cpu(dqb->dd_diskdq.d_icount), be64_to_cpu(dqb->dd_diskdq.d_rtbcount)); } pop_cur(); } } static void process_rtbitmap( blkmap_t *blkmap) { int bit; int bitsperblock; xfs_fileoff_t bmbno; xfs_fsblock_t bno; xfs_rtblock_t extno; int len; int log; int offs; int prevbit; xfs_rfsblock_t rtbno; int start_bmbno; int start_bit; int t; xfs_rtword_t *words; bitsperblock = mp->m_sb.sb_blocksize * NBBY; bit = extno = prevbit = start_bmbno = start_bit = 0; bmbno = NULLFILEOFF; while ((bmbno = blkmap_next_off(blkmap, bmbno, &t)) != NULLFILEOFF) { bno = blkmap_get(blkmap, bmbno); if (bno == NULLFSBLOCK) { if (!sflag) dbprintf(_("block %lld for rtbitmap inode is " "missing\n"), (xfs_fileoff_t)bmbno); error++; continue; } push_cur(); set_cur(&typtab[TYP_RTBITMAP], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_IGN, NULL); if ((words = iocur_top->data) == NULL) { if (!sflag) dbprintf(_("can't read block %lld for rtbitmap " "inode\n"), (xfs_fileoff_t)bmbno); error++; pop_cur(); continue; } for (bit = 0; bit < bitsperblock && extno < mp->m_sb.sb_rextents; bit++, extno++) { if (xfs_isset(words, bit)) { rtbno = extno * mp->m_sb.sb_rextsize; set_rdbmap(rtbno, mp->m_sb.sb_rextsize, DBM_RTFREE); frextents++; if (prevbit == 0) { start_bmbno = (int)bmbno; start_bit = bit; prevbit = 1; } } else if (prevbit == 1) { len = ((int)bmbno - start_bmbno) * bitsperblock + (bit - start_bit); log = XFS_RTBLOCKLOG(len); offs = XFS_SUMOFFS(mp, log, start_bmbno); sumcompute[offs]++; prevbit = 0; } } pop_cur(); if (extno == mp->m_sb.sb_rextents) break; } if (prevbit == 1) { len = ((int)bmbno - start_bmbno) * bitsperblock + (bit - start_bit); log = XFS_RTBLOCKLOG(len); offs = XFS_SUMOFFS(mp, log, start_bmbno); sumcompute[offs]++; } } static void process_rtsummary( blkmap_t *blkmap) { xfs_fsblock_t bno; char *bytes; xfs_fileoff_t sumbno; int t; sumbno = NULLFILEOFF; while ((sumbno = blkmap_next_off(blkmap, sumbno, &t)) != NULLFILEOFF) { bno = blkmap_get(blkmap, sumbno); if (bno == NULLFSBLOCK) { if (!sflag) dbprintf(_("block %lld for rtsummary inode is " "missing\n"), (xfs_fileoff_t)sumbno); error++; continue; } push_cur(); set_cur(&typtab[TYP_RTSUMMARY], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_IGN, NULL); if ((bytes = iocur_top->data) == NULL) { if (!sflag) dbprintf(_("can't read block %lld for rtsummary " "inode\n"), (xfs_fileoff_t)sumbno); error++; pop_cur(); continue; } memcpy((char *)sumfile + sumbno * mp->m_sb.sb_blocksize, bytes, mp->m_sb.sb_blocksize); pop_cur(); } } static xfs_ino_t process_sf_dir_v2( xfs_dinode_t *dip, int *dot, int *dotdot, inodata_t *id) { inodata_t *cid; int i; int i8; xfs_ino_t lino; int offset; struct xfs_dir2_sf_hdr *sf; xfs_dir2_sf_entry_t *sfe; int v; sf = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); addlink_inode(id); v = verbose || id->ilist; if (v) dbprintf(_("dir %lld entry . %lld\n"), id->ino, id->ino); (*dot)++; sfe = xfs_dir2_sf_firstentry(sf); offset = M_DIROPS(mp)->data_first_offset; for (i = sf->count - 1, i8 = 0; i >= 0; i--) { if ((intptr_t)sfe + M_DIROPS(mp)->sf_entsize(sf, sfe->namelen) - (intptr_t)sf > be64_to_cpu(dip->di_size)) { if (!sflag) dbprintf(_("dir %llu bad size in entry at %d\n"), id->ino, (int)((char *)sfe - (char *)sf)); error++; break; } lino = M_DIROPS(mp)->sf_get_ino(sf, sfe); if (lino > XFS_DIR2_MAX_SHORT_INUM) i8++; cid = find_inode(lino, 1); if (cid == NULL) { if (!sflag) dbprintf(_("dir %lld entry %*.*s bad inode " "number %lld\n"), id->ino, sfe->namelen, sfe->namelen, sfe->name, lino); error++; } else { addlink_inode(cid); if (!cid->parent) cid->parent = id; addname_inode(cid, (char *)sfe->name, sfe->namelen); } if (v) dbprintf(_("dir %lld entry %*.*s offset %d %lld\n"), id->ino, sfe->namelen, sfe->namelen, sfe->name, xfs_dir2_sf_get_offset(sfe), lino); if (xfs_dir2_sf_get_offset(sfe) < offset) { if (!sflag) dbprintf(_("dir %lld entry %*.*s bad offset %d\n"), id->ino, sfe->namelen, sfe->namelen, sfe->name, xfs_dir2_sf_get_offset(sfe)); error++; } offset = xfs_dir2_sf_get_offset(sfe) + M_DIROPS(mp)->sf_entsize(sf, sfe->namelen); sfe = M_DIROPS(mp)->sf_nextentry(sf, sfe); } if (i < 0 && (intptr_t)sfe - (intptr_t)sf != be64_to_cpu(dip->di_size)) { if (!sflag) dbprintf(_("dir %llu size is %lld, should be %u\n"), id->ino, be64_to_cpu(dip->di_size), (uint)((char *)sfe - (char *)sf)); error++; } if (offset + (sf->count + 2) * sizeof(xfs_dir2_leaf_entry_t) + sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize) { if (!sflag) dbprintf(_("dir %llu offsets too high\n"), id->ino); error++; } lino = M_DIROPS(mp)->sf_get_parent_ino(sf); if (lino > XFS_DIR2_MAX_SHORT_INUM) i8++; cid = find_inode(lino, 1); if (cid) addlink_inode(cid); else { if (!sflag) dbprintf(_("dir %lld entry .. bad inode number %lld\n"), id->ino, lino); error++; } if (v) dbprintf(_("dir %lld entry .. %lld\n"), id->ino, lino); if (i8 != sf->i8count) { if (!sflag) dbprintf(_("dir %lld i8count mismatch is %d should be " "%d\n"), id->ino, sf->i8count, i8); error++; } (*dotdot)++; return cid ? lino : NULLFSINO; } static void quota_add( xfs_dqid_t *prjid, xfs_dqid_t *grpid, xfs_dqid_t *usrid, int dq, xfs_qcnt_t bc, xfs_qcnt_t ic, xfs_qcnt_t rc) { if (qudo && usrid != NULL) quota_add1(qudata, *usrid, dq, bc, ic, rc); if (qgdo && grpid != NULL) quota_add1(qgdata, *grpid, dq, bc, ic, rc); if (qpdo && prjid != NULL) quota_add1(qpdata, *prjid, dq, bc, ic, rc); } static void quota_add1( qdata_t **qt, xfs_dqid_t id, int dq, xfs_qcnt_t bc, xfs_qcnt_t ic, xfs_qcnt_t rc) { qdata_t *qe; int qh; qinfo_t *qi; qh = (int)(id % QDATA_HASH_SIZE); qe = qt[qh]; while (qe) { if (qe->id == id) { qi = dq ? &qe->dq : &qe->count; qi->bc += bc; qi->ic += ic; qi->rc += rc; return; } qe = qe->next; } qe = xmalloc(sizeof(*qe)); qe->id = id; qi = dq ? &qe->dq : &qe->count; qi->bc = bc; qi->ic = ic; qi->rc = rc; qi = dq ? &qe->count : &qe->dq; qi->bc = qi->ic = qi->rc = 0; qe->next = qt[qh]; qt[qh] = qe; } static void quota_check( char *s, qdata_t **qt) { int i; qdata_t *next; qdata_t *qp; for (i = 0; i < QDATA_HASH_SIZE; i++) { qp = qt[i]; while (qp) { next = qp->next; if (qp->count.bc != qp->dq.bc || qp->count.ic != qp->dq.ic || qp->count.rc != qp->dq.rc) { if (!sflag) { dbprintf(_("%s quota id %u, have/exp"), s, qp->id); if (qp->count.bc != qp->dq.bc) dbprintf(_(" bc %lld/%lld"), qp->dq.bc, qp->count.bc); if (qp->count.ic != qp->dq.ic) dbprintf(_(" ic %lld/%lld"), qp->dq.ic, qp->count.ic); if (qp->count.rc != qp->dq.rc) dbprintf(_(" rc %lld/%lld"), qp->dq.rc, qp->count.rc); dbprintf("\n"); } error++; } xfree(qp); qp = next; } } xfree(qt); } static void quota_init(void) { qudo = mp->m_sb.sb_uquotino != 0 && mp->m_sb.sb_uquotino != NULLFSINO && (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) && (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD); qgdo = mp->m_sb.sb_gquotino != 0 && mp->m_sb.sb_gquotino != NULLFSINO && (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) && (mp->m_sb.sb_qflags & XFS_GQUOTA_CHKD); qpdo = mp->m_sb.sb_pquotino != 0 && mp->m_sb.sb_pquotino != NULLFSINO && (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) && (mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD); if (qudo) qudata = xcalloc(QDATA_HASH_SIZE, sizeof(qdata_t *)); if (qgdo) qgdata = xcalloc(QDATA_HASH_SIZE, sizeof(qdata_t *)); if (qpdo) qpdata = xcalloc(QDATA_HASH_SIZE, sizeof(qdata_t *)); } static void scan_ag( xfs_agnumber_t agno) { xfs_agf_t *agf; xfs_agi_t *agi; int i; xfs_sb_t tsb; xfs_sb_t *sb = &tsb; agffreeblks = agflongest = 0; agfbtreeblks = -2; agicount = agifreecount = 0; push_cur(); /* 1 pushed */ set_cur(&typtab[TYP_SB], XFS_AG_DADDR(mp, agno, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if (!iocur_top->data) { dbprintf(_("can't read superblock for ag %u\n"), agno); serious_error++; goto pop1_out; } libxfs_sb_from_disk(sb, iocur_top->data); if (sb->sb_magicnum != XFS_SB_MAGIC) { if (!sflag) dbprintf(_("bad sb magic # %#x in ag %u\n"), sb->sb_magicnum, agno); error++; } if (!xfs_sb_good_version(sb)) { if (!sflag) dbprintf(_("bad sb version # %#x in ag %u\n"), sb->sb_versionnum, agno); error++; sbver_err++; } if (!lazycount && xfs_sb_version_haslazysbcount(sb)) { lazycount = 1; } if (agno == 0 && sb->sb_inprogress != 0) { if (!sflag) dbprintf(_("mkfs not completed successfully\n")); error++; } set_dbmap(agno, XFS_SB_BLOCK(mp), 1, DBM_SB, agno, XFS_SB_BLOCK(mp)); if (sb->sb_logstart && XFS_FSB_TO_AGNO(mp, sb->sb_logstart) == agno) set_dbmap(agno, XFS_FSB_TO_AGBNO(mp, sb->sb_logstart), sb->sb_logblocks, DBM_LOG, agno, XFS_SB_BLOCK(mp)); push_cur(); /* 2 pushed */ set_cur(&typtab[TYP_AGF], XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if ((agf = iocur_top->data) == NULL) { dbprintf(_("can't read agf block for ag %u\n"), agno); serious_error++; goto pop2_out; } if (be32_to_cpu(agf->agf_magicnum) != XFS_AGF_MAGIC) { if (!sflag) dbprintf(_("bad agf magic # %#x in ag %u\n"), be32_to_cpu(agf->agf_magicnum), agno); error++; } if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum))) { if (!sflag) dbprintf(_("bad agf version # %#x in ag %u\n"), be32_to_cpu(agf->agf_versionnum), agno); error++; } if (XFS_SB_BLOCK(mp) != XFS_AGF_BLOCK(mp)) set_dbmap(agno, XFS_AGF_BLOCK(mp), 1, DBM_AGF, agno, XFS_SB_BLOCK(mp)); if (sb->sb_agblocks > be32_to_cpu(agf->agf_length)) set_dbmap(agno, be32_to_cpu(agf->agf_length), sb->sb_agblocks - be32_to_cpu(agf->agf_length), DBM_MISSING, agno, XFS_SB_BLOCK(mp)); push_cur(); /* 3 pushed */ set_cur(&typtab[TYP_AGI], XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if ((agi = iocur_top->data) == NULL) { dbprintf(_("can't read agi block for ag %u\n"), agno); serious_error++; goto pop3_out; } if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) { if (!sflag) dbprintf(_("bad agi magic # %#x in ag %u\n"), be32_to_cpu(agi->agi_magicnum), agno); error++; } if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) { if (!sflag) dbprintf(_("bad agi version # %#x in ag %u\n"), be32_to_cpu(agi->agi_versionnum), agno); error++; } if (XFS_SB_BLOCK(mp) != XFS_AGI_BLOCK(mp) && XFS_AGF_BLOCK(mp) != XFS_AGI_BLOCK(mp)) set_dbmap(agno, XFS_AGI_BLOCK(mp), 1, DBM_AGI, agno, XFS_SB_BLOCK(mp)); scan_freelist(agf); fdblocks--; scan_sbtree(agf, be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]), be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]), 1, scanfunc_bno, TYP_BNOBT); fdblocks--; scan_sbtree(agf, be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]), be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]), 1, scanfunc_cnt, TYP_CNTBT); if (agf->agf_roots[XFS_BTNUM_RMAP]) { scan_sbtree(agf, be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]), be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]), 1, scanfunc_rmap, TYP_RMAPBT); } if (agf->agf_refcount_root) { scan_sbtree(agf, be32_to_cpu(agf->agf_refcount_root), be32_to_cpu(agf->agf_refcount_level), 1, scanfunc_refcnt, TYP_REFCBT); } scan_sbtree(agf, be32_to_cpu(agi->agi_root), be32_to_cpu(agi->agi_level), 1, scanfunc_ino, TYP_INOBT); if (agi->agi_free_root) { scan_sbtree(agf, be32_to_cpu(agi->agi_free_root), be32_to_cpu(agi->agi_free_level), 1, scanfunc_fino, TYP_FINOBT); } if (be32_to_cpu(agf->agf_freeblks) != agffreeblks) { if (!sflag) dbprintf(_("agf_freeblks %u, counted %u in ag %u\n"), be32_to_cpu(agf->agf_freeblks), agffreeblks, agno); error++; } if (be32_to_cpu(agf->agf_longest) != agflongest) { if (!sflag) dbprintf(_("agf_longest %u, counted %u in ag %u\n"), be32_to_cpu(agf->agf_longest), agflongest, agno); error++; } if (lazycount && be32_to_cpu(agf->agf_btreeblks) != agfbtreeblks) { if (!sflag) dbprintf(_("agf_btreeblks %u, counted %u in ag %u\n"), be32_to_cpu(agf->agf_btreeblks), agfbtreeblks, agno); error++; } agf_aggr_freeblks += agffreeblks + agfbtreeblks; if (be32_to_cpu(agi->agi_count) != agicount) { if (!sflag) dbprintf(_("agi_count %u, counted %u in ag %u\n"), be32_to_cpu(agi->agi_count), agicount, agno); error++; } if (be32_to_cpu(agi->agi_freecount) != agifreecount) { if (!sflag) dbprintf(_("agi_freecount %u, counted %u in ag %u\n"), be32_to_cpu(agi->agi_freecount), agifreecount, agno); error++; } for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) { if (be32_to_cpu(agi->agi_unlinked[i]) != NULLAGINO) { if (!sflag) { xfs_agino_t agino=be32_to_cpu(agi->agi_unlinked[i]); dbprintf(_("agi unlinked bucket %d is %u in ag " "%u (inode=%lld)\n"), i, agino, agno, XFS_AGINO_TO_INO(mp, agno, agino)); } error++; } } pop3_out: pop_cur(); pop2_out: pop_cur(); pop1_out: pop_cur(); } static void scan_freelist( xfs_agf_t *agf) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); xfs_agfl_t *agfl; xfs_agblock_t bno; uint count; int i; __be32 *freelist; if (XFS_SB_BLOCK(mp) != XFS_AGFL_BLOCK(mp) && XFS_AGF_BLOCK(mp) != XFS_AGFL_BLOCK(mp) && XFS_AGI_BLOCK(mp) != XFS_AGFL_BLOCK(mp)) set_dbmap(seqno, XFS_AGFL_BLOCK(mp), 1, DBM_AGFL, seqno, XFS_SB_BLOCK(mp)); if (be32_to_cpu(agf->agf_flcount) == 0) return; push_cur(); set_cur(&typtab[TYP_AGFL], XFS_AG_DADDR(mp, seqno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if ((agfl = iocur_top->data) == NULL) { dbprintf(_("can't read agfl block for ag %u\n"), seqno); serious_error++; pop_cur(); return; } i = be32_to_cpu(agf->agf_flfirst); /* verify agf values before proceeding */ if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp) || be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) { dbprintf(_("agf %d freelist blocks bad, skipping " "freelist scan\n"), i); pop_cur(); return; } /* open coded XFS_BUF_TO_AGFL_BNO */ freelist = xfs_sb_version_hascrc(&((mp)->m_sb)) ? &agfl->agfl_bno[0] : (__be32 *)agfl; count = 0; for (;;) { bno = be32_to_cpu(freelist[i]); set_dbmap(seqno, bno, 1, DBM_FREELIST, seqno, XFS_AGFL_BLOCK(mp)); count++; if (i == be32_to_cpu(agf->agf_fllast)) break; if (++i == XFS_AGFL_SIZE(mp)) i = 0; } if (count != be32_to_cpu(agf->agf_flcount)) { if (!sflag) dbprintf(_("freeblk count %u != flcount %u in ag %u\n"), count, be32_to_cpu(agf->agf_flcount), seqno); error++; } fdblocks += count; agf_aggr_freeblks += count; pop_cur(); } static void scan_lbtree( xfs_fsblock_t root, int nlevels, scan_lbtree_f_t func, dbm_t type, inodata_t *id, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int isroot, typnm_t btype) { push_cur(); set_cur(&typtab[btype], XFS_FSB_TO_DADDR(mp, root), blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { if (!sflag) dbprintf(_("can't read btree block %u/%u\n"), XFS_FSB_TO_AGNO(mp, root), XFS_FSB_TO_AGBNO(mp, root)); error++; pop_cur(); return; } (*func)(iocur_top->data, nlevels - 1, type, root, id, totd, toti, nex, blkmapp, isroot, btype); pop_cur(); } static void scan_sbtree( xfs_agf_t *agf, xfs_agblock_t root, int nlevels, int isroot, scan_sbtree_f_t func, typnm_t btype) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); push_cur(); set_cur(&typtab[btype], XFS_AGB_TO_DADDR(mp, seqno, root), blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { if (!sflag) dbprintf(_("can't read btree block %u/%u\n"), seqno, root); error++; pop_cur(); return; } (*func)(iocur_top->data, nlevels - 1, agf, root, isroot); pop_cur(); } static void scanfunc_bmap( struct xfs_btree_block *block, int level, dbm_t type, xfs_fsblock_t bno, inodata_t *id, xfs_rfsblock_t *totd, xfs_rfsblock_t *toti, xfs_extnum_t *nex, blkmap_t **blkmapp, int isroot, typnm_t btype) { xfs_agblock_t agbno; xfs_agnumber_t agno; int i; xfs_bmbt_ptr_t *pp; xfs_bmbt_rec_t *rp; agno = XFS_FSB_TO_AGNO(mp, bno); agbno = XFS_FSB_TO_AGBNO(mp, bno); if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC && be32_to_cpu(block->bb_magic) != XFS_BMAP_CRC_MAGIC) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("bad magic # %#x in inode %lld bmbt block " "%u/%u\n"), be32_to_cpu(block->bb_magic), id->ino, agno, agbno); error++; } if (be16_to_cpu(block->bb_level) != level) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("expected level %d got %d in inode %lld bmbt " "block %u/%u\n"), level, be16_to_cpu(block->bb_level), id->ino, agno, agbno); error++; } set_dbmap(agno, agbno, 1, type, agno, agbno); set_inomap(agno, agbno, 1, id); (*toti)++; if (level == 0) { if (be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[0] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_bmap_dmnr[0])) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) " "in inode %lld bmap block %lld\n"), be16_to_cpu(block->bb_numrecs), mp->m_bmap_dmnr[0], mp->m_bmap_dmxr[0], id->ino, (xfs_fsblock_t)bno); error++; return; } rp = XFS_BMBT_REC_ADDR(mp, block, 1); *nex += be16_to_cpu(block->bb_numrecs); process_bmbt_reclist(rp, be16_to_cpu(block->bb_numrecs), type, id, totd, blkmapp); return; } if (be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[1] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_bmap_dmnr[1])) { if (!sflag || id->ilist || CHECK_BLIST(bno)) dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " "inode %lld bmap block %lld\n"), be16_to_cpu(block->bb_numrecs), mp->m_bmap_dmnr[1], mp->m_bmap_dmxr[1], id->ino, (xfs_fsblock_t)bno); error++; return; } pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[0]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_lbtree(be64_to_cpu(pp[i]), level, scanfunc_bmap, type, id, totd, toti, nex, blkmapp, 0, btype); } static void scanfunc_bno( struct xfs_btree_block *block, int level, xfs_agf_t *agf, xfs_agblock_t bno, int isroot) { int i; xfs_alloc_ptr_t *pp; xfs_alloc_rec_t *rp; xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); xfs_agblock_t lastblock; if (be32_to_cpu(block->bb_magic) != XFS_ABTB_MAGIC && be32_to_cpu(block->bb_magic) != XFS_ABTB_CRC_MAGIC) { dbprintf(_("bad magic # %#x in btbno block %u/%u\n"), be32_to_cpu(block->bb_magic), seqno, bno); serious_error++; return; } fdblocks++; agfbtreeblks++; if (be16_to_cpu(block->bb_level) != level) { if (!sflag) dbprintf(_("expected level %d got %d in btbno block " "%u/%u\n"), level, be16_to_cpu(block->bb_level), seqno, bno); error++; } set_dbmap(seqno, bno, 1, DBM_BTBNO, seqno, bno); if (level == 0) { if (be16_to_cpu(block->bb_numrecs) > mp->m_alloc_mxr[0] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_alloc_mnr[0])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " "btbno block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_alloc_mnr[0], mp->m_alloc_mxr[0], seqno, bno); serious_error++; return; } rp = XFS_ALLOC_REC_ADDR(mp, block, 1); lastblock = 0; for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { set_dbmap(seqno, be32_to_cpu(rp[i].ar_startblock), be32_to_cpu(rp[i].ar_blockcount), DBM_FREE1, seqno, bno); if (be32_to_cpu(rp[i].ar_startblock) <= lastblock) { dbprintf(_( "out-of-order bno btree record %d (%u %u) block %u/%u\n"), i, be32_to_cpu(rp[i].ar_startblock), be32_to_cpu(rp[i].ar_blockcount), be32_to_cpu(agf->agf_seqno), bno); serious_error++; } else { lastblock = be32_to_cpu(rp[i].ar_startblock); } } return; } if (be16_to_cpu(block->bb_numrecs) > mp->m_alloc_mxr[1] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_alloc_mnr[1])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in btbno block " "%u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_alloc_mnr[1], mp->m_alloc_mxr[1], seqno, bno); serious_error++; return; } pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_bno, TYP_BNOBT); } static void scanfunc_cnt( struct xfs_btree_block *block, int level, xfs_agf_t *agf, xfs_agblock_t bno, int isroot) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int i; xfs_alloc_ptr_t *pp; xfs_alloc_rec_t *rp; xfs_extlen_t lastcount; if (be32_to_cpu(block->bb_magic) != XFS_ABTC_MAGIC && be32_to_cpu(block->bb_magic) != XFS_ABTC_CRC_MAGIC) { dbprintf(_("bad magic # %#x in btcnt block %u/%u\n"), be32_to_cpu(block->bb_magic), seqno, bno); serious_error++; return; } fdblocks++; agfbtreeblks++; if (be16_to_cpu(block->bb_level) != level) { if (!sflag) dbprintf(_("expected level %d got %d in btcnt block " "%u/%u\n"), level, be16_to_cpu(block->bb_level), seqno, bno); error++; } set_dbmap(seqno, bno, 1, DBM_BTCNT, seqno, bno); if (level == 0) { if (be16_to_cpu(block->bb_numrecs) > mp->m_alloc_mxr[0] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_alloc_mnr[0])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " "btbno block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_alloc_mnr[0], mp->m_alloc_mxr[0], seqno, bno); serious_error++; return; } rp = XFS_ALLOC_REC_ADDR(mp, block, 1); lastcount = 0; for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { check_set_dbmap(seqno, be32_to_cpu(rp[i].ar_startblock), be32_to_cpu(rp[i].ar_blockcount), DBM_FREE1, DBM_FREE2, seqno, bno); fdblocks += be32_to_cpu(rp[i].ar_blockcount); agffreeblks += be32_to_cpu(rp[i].ar_blockcount); if (be32_to_cpu(rp[i].ar_blockcount) > agflongest) agflongest = be32_to_cpu(rp[i].ar_blockcount); if (be32_to_cpu(rp[i].ar_blockcount) < lastcount) { dbprintf(_( "out-of-order cnt btree record %d (%u %u) block %u/%u\n"), i, be32_to_cpu(rp[i].ar_startblock), be32_to_cpu(rp[i].ar_blockcount), be32_to_cpu(agf->agf_seqno), bno); } else { lastcount = be32_to_cpu(rp[i].ar_blockcount); } } return; } if (be16_to_cpu(block->bb_numrecs) > mp->m_alloc_mxr[1] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_alloc_mnr[1])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in btbno block " "%u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_alloc_mnr[1], mp->m_alloc_mxr[1], seqno, bno); serious_error++; return; } pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_cnt, TYP_CNTBT); } static void scanfunc_ino( struct xfs_btree_block *block, int level, xfs_agf_t *agf, xfs_agblock_t bno, int isroot) { xfs_agino_t agino; xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int i; int isfree; int j; int freecount; int nfree; int off; xfs_inobt_ptr_t *pp; xfs_inobt_rec_t *rp; xfs_agblock_t agbno; xfs_agblock_t end_agbno; struct xfs_dinode *dip; int blks_per_buf; int inodes_per_buf; int ioff; if (xfs_sb_version_hassparseinodes(&mp->m_sb)) blks_per_buf = xfs_icluster_size_fsb(mp); else blks_per_buf = mp->m_ialloc_blks; inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, XFS_INODES_PER_CHUNK); if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC && be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) { dbprintf(_("bad magic # %#x in inobt block %u/%u\n"), be32_to_cpu(block->bb_magic), seqno, bno); serious_error++; return; } if (be16_to_cpu(block->bb_level) != level) { if (!sflag) dbprintf(_("expected level %d got %d in inobt block " "%u/%u\n"), level, be16_to_cpu(block->bb_level), seqno, bno); error++; } set_dbmap(seqno, bno, 1, DBM_BTINO, seqno, bno); if (level == 0) { if (be16_to_cpu(block->bb_numrecs) > mp->m_inobt_mxr[0] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_inobt_mnr[0])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " "inobt block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_inobt_mnr[0], mp->m_inobt_mxr[0], seqno, bno); serious_error++; return; } rp = XFS_INOBT_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { agino = be32_to_cpu(rp[i].ir_startino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); off = XFS_AGINO_TO_OFFSET(mp, agino); end_agbno = agbno + mp->m_ialloc_blks; if (off == 0) { if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && mp->m_sb.sb_inoalignmt && (XFS_INO_TO_AGBNO(mp, agino) % mp->m_sb.sb_inoalignmt)) sbversion &= ~XFS_SB_VERSION_ALIGNBIT; } push_cur(); ioff = 0; nfree = 0; while (agbno < end_agbno && ioff < XFS_INODES_PER_CHUNK) { if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) goto next_buf; if (off < XFS_INODES_PER_CHUNK) set_dbmap(seqno, agbno, blks_per_buf, DBM_INODE, seqno, bno); icount += inodes_per_buf; agicount += inodes_per_buf; set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, seqno, agbno), XFS_FSB_TO_BB(mp, blks_per_buf), DB_RING_IGN, NULL); if (iocur_top->data == NULL) { if (!sflag) dbprintf(_("can't read inode block " "%u/%u\n"), seqno, agbno); error++; goto next_buf; } for (j = 0; j < inodes_per_buf; j++) { isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], ioff + j); if (isfree) nfree++; dip = (xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)); process_inode(agf, agino + ioff + j, dip, isfree); } next_buf: agbno += blks_per_buf; ioff += inodes_per_buf; } if (xfs_sb_version_hassparseinodes(&mp->m_sb)) freecount = rp[i].ir_u.sp.ir_freecount; else freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount); ifree += freecount; agifreecount += freecount; if (nfree != freecount) { if (!sflag) dbprintf(_("ir_freecount/free mismatch, " "inode chunk %u/%u, freecount " "%d nfree %d\n"), seqno, agino, freecount, nfree); error++; } pop_cur(); } return; } if (be16_to_cpu(block->bb_numrecs) > mp->m_inobt_mxr[1] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_inobt_mnr[1])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in inobt block " "%u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_inobt_mnr[1], mp->m_inobt_mxr[1], seqno, bno); serious_error++; return; } pp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_ino, TYP_INOBT); } static void scanfunc_fino( struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot) { xfs_agino_t agino; xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int i; int off; xfs_inobt_ptr_t *pp; struct xfs_inobt_rec *rp; xfs_agblock_t agbno; xfs_agblock_t end_agbno; int blks_per_buf; int inodes_per_buf; int ioff; if (xfs_sb_version_hassparseinodes(&mp->m_sb)) blks_per_buf = xfs_icluster_size_fsb(mp); else blks_per_buf = mp->m_ialloc_blks; inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, XFS_INODES_PER_CHUNK); if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC && be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) { dbprintf(_("bad magic # %#x in finobt block %u/%u\n"), be32_to_cpu(block->bb_magic), seqno, bno); serious_error++; return; } if (be16_to_cpu(block->bb_level) != level) { if (!sflag) dbprintf(_("expected level %d got %d in finobt block " "%u/%u\n"), level, be16_to_cpu(block->bb_level), seqno, bno); error++; } set_dbmap(seqno, bno, 1, DBM_BTFINO, seqno, bno); if (level == 0) { if (be16_to_cpu(block->bb_numrecs) > mp->m_inobt_mxr[0] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_inobt_mnr[0])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " "finobt block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_inobt_mnr[0], mp->m_inobt_mxr[0], seqno, bno); serious_error++; return; } rp = XFS_INOBT_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { agino = be32_to_cpu(rp[i].ir_startino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); off = XFS_AGINO_TO_OFFSET(mp, agino); end_agbno = agbno + mp->m_ialloc_blks; if (off == 0) { if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && mp->m_sb.sb_inoalignmt && (XFS_INO_TO_AGBNO(mp, agino) % mp->m_sb.sb_inoalignmt)) sbversion &= ~XFS_SB_VERSION_ALIGNBIT; } ioff = 0; while (agbno < end_agbno && ioff < XFS_INODES_PER_CHUNK) { if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) goto next_buf; check_set_dbmap(seqno, agbno, (xfs_extlen_t)MAX(1, inodes_per_buf >> mp->m_sb.sb_inopblog), DBM_INODE, DBM_INODE, seqno, bno); next_buf: agbno += blks_per_buf; ioff += inodes_per_buf; } } return; } if (be16_to_cpu(block->bb_numrecs) > mp->m_inobt_mxr[1] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_inobt_mnr[1])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in finobt block " "%u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_inobt_mnr[1], mp->m_inobt_mxr[1], seqno, bno); serious_error++; return; } pp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_fino, TYP_FINOBT); } static void scanfunc_rmap( struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int i; xfs_rmap_ptr_t *pp; struct xfs_rmap_rec *rp; xfs_agblock_t lastblock; if (be32_to_cpu(block->bb_magic) != XFS_RMAP_CRC_MAGIC) { dbprintf(_("bad magic # %#x in rmapbt block %u/%u\n"), be32_to_cpu(block->bb_magic), seqno, bno); serious_error++; return; } if (be16_to_cpu(block->bb_level) != level) { if (!sflag) dbprintf(_("expected level %d got %d in rmapbt block " "%u/%u\n"), level, be16_to_cpu(block->bb_level), seqno, bno); error++; } if (!isroot) { fdblocks++; agfbtreeblks++; } set_dbmap(seqno, bno, 1, DBM_BTRMAP, seqno, bno); if (level == 0) { if (be16_to_cpu(block->bb_numrecs) > mp->m_rmap_mxr[0] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_rmap_mnr[0])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " "rmapbt block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_rmap_mnr[0], mp->m_rmap_mxr[0], seqno, bno); serious_error++; return; } rp = XFS_RMAP_REC_ADDR(block, 1); lastblock = 0; for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { if (be32_to_cpu(rp[i].rm_startblock) < lastblock) { dbprintf(_( "out-of-order rmap btree record %d (%u %u) block %u/%u\n"), i, be32_to_cpu(rp[i].rm_startblock), be32_to_cpu(rp[i].rm_startblock), be32_to_cpu(agf->agf_seqno), bno); } else { lastblock = be32_to_cpu(rp[i].rm_startblock); } } return; } if (be16_to_cpu(block->bb_numrecs) > mp->m_rmap_mxr[1] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_rmap_mnr[1])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in rmapbt " "block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_rmap_mnr[1], mp->m_rmap_mxr[1], seqno, bno); serious_error++; return; } pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_rmap, TYP_RMAPBT); } static void scanfunc_refcnt( struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int i; xfs_refcount_ptr_t *pp; struct xfs_refcount_rec *rp; xfs_agblock_t lastblock; if (be32_to_cpu(block->bb_magic) != XFS_REFC_CRC_MAGIC) { dbprintf(_("bad magic # %#x in refcntbt block %u/%u\n"), be32_to_cpu(block->bb_magic), seqno, bno); serious_error++; return; } if (be16_to_cpu(block->bb_level) != level) { if (!sflag) dbprintf(_("expected level %d got %d in refcntbt block " "%u/%u\n"), level, be16_to_cpu(block->bb_level), seqno, bno); error++; } set_dbmap(seqno, bno, 1, DBM_BTREFC, seqno, bno); if (level == 0) { if (be16_to_cpu(block->bb_numrecs) > mp->m_refc_mxr[0] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_refc_mnr[0])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " "refcntbt block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_refc_mnr[0], mp->m_refc_mxr[0], seqno, bno); serious_error++; return; } rp = XFS_REFCOUNT_REC_ADDR(block, 1); lastblock = 0; for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { if (be32_to_cpu(rp[i].rc_refcount) == 1) { dbprintf(_( "leftover CoW extent (%u/%u) len %u\n"), seqno, be32_to_cpu(rp[i].rc_startblock), be32_to_cpu(rp[i].rc_blockcount)); set_dbmap(seqno, be32_to_cpu(rp[i].rc_startblock), be32_to_cpu(rp[i].rc_blockcount), DBM_COWDATA, seqno, bno); } else { set_dbmap(seqno, be32_to_cpu(rp[i].rc_startblock), be32_to_cpu(rp[i].rc_blockcount), DBM_RLDATA, seqno, bno); } if (be32_to_cpu(rp[i].rc_startblock) < lastblock) { dbprintf(_( "out-of-order refcnt btree record %d (%u %u) block %u/%u\n"), i, be32_to_cpu(rp[i].rc_startblock), be32_to_cpu(rp[i].rc_startblock), be32_to_cpu(agf->agf_seqno), bno); } else { lastblock = be32_to_cpu(rp[i].rc_startblock) + be32_to_cpu(rp[i].rc_blockcount); } } return; } if (be16_to_cpu(block->bb_numrecs) > mp->m_refc_mxr[1] || (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_refc_mnr[1])) { dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in refcntbt " "block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_refc_mnr[1], mp->m_refc_mxr[1], seqno, bno); serious_error++; return; } pp = XFS_REFCOUNT_PTR_ADDR(block, 1, mp->m_refc_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_refcnt, TYP_REFCBT); } static void set_dbmap( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type, xfs_agnumber_t c_agno, xfs_agblock_t c_agbno) { check_set_dbmap(agno, agbno, len, DBM_UNKNOWN, type, c_agno, c_agbno); } static void set_inomap( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, inodata_t *id) { xfs_extlen_t i; inodata_t **idp; int mayprint; if (!check_inomap(agno, agbno, len, id->ino)) return; mayprint = verbose | id->ilist | blist_size; for (i = 0, idp = &inomap[agno][agbno]; i < len; i++, idp++) { *idp = id; if (mayprint && (verbose || id->ilist || CHECK_BLISTA(agno, agbno + i))) dbprintf(_("setting inode to %lld for block %u/%u\n"), id->ino, agno, agbno + i); } } static void set_rdbmap( xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type) { check_set_rdbmap(bno, len, DBM_UNKNOWN, type); } static void set_rinomap( xfs_rfsblock_t bno, xfs_extlen_t len, inodata_t *id) { xfs_extlen_t i; inodata_t **idp; int mayprint; if (!check_rinomap(bno, len, id->ino)) return; mayprint = verbose | id->ilist | blist_size; for (i = 0, idp = &inomap[mp->m_sb.sb_agcount][bno]; i < len; i++, idp++) { *idp = id; if (mayprint && (verbose || id->ilist || CHECK_BLIST(bno + i))) dbprintf(_("setting inode to %lld for rtblock %llu\n"), id->ino, bno + i); } } static void setlink_inode( inodata_t *id, nlink_t nlink, int isdir, int security) { id->link_set = nlink; id->isdir = isdir; id->security = security; if (verbose || id->ilist) dbprintf(_("inode %lld nlink %u %s dir\n"), id->ino, nlink, isdir ? "is" : "not"); } xfsprogs-4.9.0+nmu1ubuntu2/db/check.h0000644000000000000000000000136613063067170014312 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void check_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/command.c0000644000000000000000000000605113063067167014650 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "addr.h" #include "attrset.h" #include "block.h" #include "bmap.h" #include "check.h" #include "command.h" #include "convert.h" #include "debug.h" #include "type.h" #include "echo.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "agf.h" #include "agfl.h" #include "agi.h" #include "frag.h" #include "freesp.h" #include "help.h" #include "hash.h" #include "inode.h" #include "input.h" #include "io.h" #include "logformat.h" #include "metadump.h" #include "output.h" #include "print.h" #include "quit.h" #include "sb.h" #include "write.h" #include "malloc.h" #include "dquot.h" #include "fsmap.h" #include "crc.h" cmdinfo_t *cmdtab; int ncmds; static int cmd_compare(const void *a, const void *b) { return strcmp(((const cmdinfo_t *)a)->name, ((const cmdinfo_t *)b)->name); } void add_command( const cmdinfo_t *ci) { cmdtab = xrealloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab)); cmdtab[ncmds - 1] = *ci; qsort(cmdtab, ncmds, sizeof(*cmdtab), cmd_compare); } int command( int argc, char **argv) { char *cmd; const cmdinfo_t *ct; cmd = argv[0]; ct = find_command(cmd); if (ct == NULL) { dbprintf(_("command %s not found\n"), cmd); return 0; } if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) { dbprintf(_("bad argument count %d to %s, expected "), argc-1, cmd); if (ct->argmax == -1) dbprintf(_("at least %d"), ct->argmin); else if (ct->argmin == ct->argmax) dbprintf("%d", ct->argmin); else dbprintf(_("between %d and %d"), ct->argmin, ct->argmax); dbprintf(_(" arguments\n")); return 0; } platform_getoptreset(); return ct->cfunc(argc, argv); } const cmdinfo_t * find_command( const char *cmd) { cmdinfo_t *ct; for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { if (strcmp(ct->name, cmd) == 0 || (ct->altname && strcmp(ct->altname, cmd) == 0)) return (const cmdinfo_t *)ct; } return NULL; } void init_commands(void) { addr_init(); agf_init(); agfl_init(); agi_init(); attrset_init(); block_init(); bmap_init(); check_init(); convert_init(); crc_init(); debug_init(); echo_init(); frag_init(); freesp_init(); fsmap_init(); help_init(); hash_init(); inode_init(); input_init(); logformat_init(); io_init(); metadump_init(); output_init(); print_init(); quit_init(); sb_init(); type_init(); write_init(); dquot_init(); } xfsprogs-4.9.0+nmu1ubuntu2/db/command.h0000644000000000000000000000233013063067170014643 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ typedef int (*cfunc_t)(int argc, char **argv); typedef void (*helpfunc_t)(void); typedef struct cmdinfo { const char *name; const char *altname; cfunc_t cfunc; int argmin; int argmax; int canpush; const char *args; const char *oneline; helpfunc_t help; } cmdinfo_t; extern cmdinfo_t *cmdtab; extern int ncmds; extern void add_command(const cmdinfo_t *ci); extern int command(int argc, char **argv); extern const cmdinfo_t *find_command(const char *cmd); extern void init_commands(void); xfsprogs-4.9.0+nmu1ubuntu2/db/convert.c0000644000000000000000000001776213063067170014717 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "convert.h" #include "output.h" #include "init.h" #define M(A) (1 << CT_ ## A) #define agblock_to_bytes(x) \ ((__uint64_t)(x) << mp->m_sb.sb_blocklog) #define agino_to_bytes(x) \ ((__uint64_t)(x) << mp->m_sb.sb_inodelog) #define agnumber_to_bytes(x) \ agblock_to_bytes((__uint64_t)(x) * mp->m_sb.sb_agblocks) #define daddr_to_bytes(x) \ ((__uint64_t)(x) << BBSHIFT) #define fsblock_to_bytes(x) \ (agnumber_to_bytes(XFS_FSB_TO_AGNO(mp, (x))) + \ agblock_to_bytes(XFS_FSB_TO_AGBNO(mp, (x)))) #define ino_to_bytes(x) \ (agnumber_to_bytes(XFS_INO_TO_AGNO(mp, (x))) + \ agino_to_bytes(XFS_INO_TO_AGINO(mp, (x)))) #define inoidx_to_bytes(x) \ ((__uint64_t)(x) << mp->m_sb.sb_inodelog) typedef enum { CT_NONE = -1, CT_AGBLOCK, /* xfs_agblock_t */ CT_AGINO, /* xfs_agino_t */ CT_AGNUMBER, /* xfs_agno_t */ CT_BBOFF, /* byte offset in daddr */ CT_BLKOFF, /* byte offset in fsb/agb */ CT_BYTE, /* byte in filesystem */ CT_DADDR, /* daddr_t */ CT_FSBLOCK, /* xfs_fsblock_t */ CT_INO, /* xfs_ino_t */ CT_INOIDX, /* index of inode in fsblock */ CT_INOOFF, /* byte offset in inode */ NCTS } ctype_t; typedef struct ctydesc { ctype_t ctype; int allowed; const char **names; } ctydesc_t; typedef union { xfs_agblock_t agblock; xfs_agino_t agino; xfs_agnumber_t agnumber; int bboff; int blkoff; __uint64_t byte; xfs_daddr_t daddr; xfs_fsblock_t fsblock; xfs_ino_t ino; int inoidx; int inooff; } cval_t; static __uint64_t bytevalue(ctype_t ctype, cval_t *val); static int convert_f(int argc, char **argv); static int getvalue(char *s, ctype_t ctype, cval_t *val); static ctype_t lookupcty(char *ctyname); static const char *agblock_names[] = { "agblock", "agbno", NULL }; static const char *agino_names[] = { "agino", "aginode", NULL }; static const char *agnumber_names[] = { "agnumber", "agno", NULL }; static const char *bboff_names[] = { "bboff", "daddroff", NULL }; static const char *blkoff_names[] = { "blkoff", "fsboff", "agboff", NULL }; static const char *byte_names[] = { "byte", "fsbyte", NULL }; static const char *daddr_names[] = { "daddr", "bb", NULL }; static const char *fsblock_names[] = { "fsblock", "fsb", "fsbno", NULL }; static const char *ino_names[] = { "ino", "inode", NULL }; static const char *inoidx_names[] = { "inoidx", "offset", NULL }; static const char *inooff_names[] = { "inooff", "inodeoff", NULL }; static const ctydesc_t ctydescs[NCTS] = { { CT_AGBLOCK, M(AGNUMBER)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF), agblock_names }, { CT_AGINO, M(AGNUMBER)|M(INOOFF), agino_names }, { CT_AGNUMBER, M(AGBLOCK)|M(AGINO)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF), agnumber_names }, { CT_BBOFF, M(AGBLOCK)|M(AGNUMBER)|M(DADDR)|M(FSBLOCK), bboff_names }, { CT_BLKOFF, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK), blkoff_names }, { CT_BYTE, 0, byte_names }, { CT_DADDR, M(BBOFF), daddr_names }, { CT_FSBLOCK, M(BBOFF)|M(BLKOFF)|M(INOIDX), fsblock_names }, { CT_INO, M(INOOFF), ino_names }, { CT_INOIDX, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK)|M(INOOFF), inoidx_names }, { CT_INOOFF, M(AGBLOCK)|M(AGINO)|M(AGNUMBER)|M(FSBLOCK)|M(INO)|M(INOIDX), inooff_names }, }; static const cmdinfo_t convert_cmd = { "convert", NULL, convert_f, 3, 9, 0, "type num [type num]... type", "convert from one address form to another", NULL }; static __uint64_t bytevalue(ctype_t ctype, cval_t *val) { switch (ctype) { case CT_AGBLOCK: return agblock_to_bytes(val->agblock); case CT_AGINO: return agino_to_bytes(val->agino); case CT_AGNUMBER: return agnumber_to_bytes(val->agnumber); case CT_BBOFF: return (__uint64_t)val->bboff; case CT_BLKOFF: return (__uint64_t)val->blkoff; case CT_BYTE: return val->byte; case CT_DADDR: return daddr_to_bytes(val->daddr); case CT_FSBLOCK: return fsblock_to_bytes(val->fsblock); case CT_INO: return ino_to_bytes(val->ino); case CT_INOIDX: return inoidx_to_bytes(val->inoidx); case CT_INOOFF: return (__uint64_t)val->inooff; case CT_NONE: case NCTS: break; } /* NOTREACHED */ return 0; } static int convert_f(int argc, char **argv) { ctype_t c; int conmask; cval_t cvals[NCTS] = {}; int i; int mask; __uint64_t v; ctype_t wtype; /* move past the "convert" command */ argc--; argv++; if ((argc % 2) != 1) { dbprintf(_("bad argument count %d to convert, expected 3,5,7,9 " "arguments\n"), argc); return 0; } if ((wtype = lookupcty(argv[argc - 1])) == CT_NONE) { dbprintf(_("unknown conversion type %s\n"), argv[argc - 1]); return 0; } for (i = mask = conmask = 0; i < (argc - 1) / 2; i++) { c = lookupcty(argv[i * 2]); if (c == CT_NONE) { dbprintf(_("unknown conversion type %s\n"), argv[i * 2]); return 0; } if (c == wtype) { dbprintf(_("result type same as argument\n")); return 0; } if (conmask & (1 << c)) { dbprintf(_("conflicting conversion type %s\n"), argv[i * 2]); return 0; } if (!getvalue(argv[i * 2 + 1], c, &cvals[c])) return 0; mask |= 1 << c; conmask |= ~ctydescs[c].allowed; } if (cur_agno != NULLAGNUMBER && (conmask & M(AGNUMBER)) == 0) { cvals[CT_AGNUMBER].agnumber = cur_agno; mask |= M(AGNUMBER); } v = 0; for (c = (ctype_t)0; c < NCTS; c++) { if (!(mask & (1 << c))) continue; v += bytevalue(c, &cvals[c]); } switch (wtype) { case CT_AGBLOCK: v = xfs_daddr_to_agbno(mp, v >> BBSHIFT); break; case CT_AGINO: v = (v >> mp->m_sb.sb_inodelog) % (mp->m_sb.sb_agblocks << mp->m_sb.sb_inopblog); break; case CT_AGNUMBER: v = xfs_daddr_to_agno(mp, v >> BBSHIFT); break; case CT_BBOFF: v &= BBMASK; break; case CT_BLKOFF: v &= mp->m_blockmask; break; case CT_BYTE: break; case CT_DADDR: v >>= BBSHIFT; break; case CT_FSBLOCK: v = XFS_DADDR_TO_FSB(mp, v >> BBSHIFT); break; case CT_INO: v = XFS_AGINO_TO_INO(mp, xfs_daddr_to_agno(mp, v >> BBSHIFT), (v >> mp->m_sb.sb_inodelog) % (mp->m_sb.sb_agblocks << mp->m_sb.sb_inopblog)); break; case CT_INOIDX: v = (v >> mp->m_sb.sb_inodelog) & (mp->m_sb.sb_inopblock - 1); break; case CT_INOOFF: v &= mp->m_sb.sb_inodesize - 1; break; case CT_NONE: case NCTS: /* NOTREACHED */ break; } dbprintf("0x%llx (%llu)\n", v, v); return 0; } void convert_init(void) { add_command(&convert_cmd); } static int getvalue(char *s, ctype_t ctype, cval_t *val) { char *p; __uint64_t v; v = strtoull(s, &p, 0); if (*p != '\0') { dbprintf(_("%s is not a number\n"), s); return 0; } switch (ctype) { case CT_AGBLOCK: val->agblock = (xfs_agblock_t)v; break; case CT_AGINO: val->agino = (xfs_agino_t)v; break; case CT_AGNUMBER: val->agnumber = (xfs_agnumber_t)v; break; case CT_BBOFF: val->bboff = (int)v; break; case CT_BLKOFF: val->blkoff = (int)v; break; case CT_BYTE: val->byte = (__uint64_t)v; break; case CT_DADDR: val->daddr = (xfs_daddr_t)v; break; case CT_FSBLOCK: val->fsblock = (xfs_fsblock_t)v; break; case CT_INO: val->ino = (xfs_ino_t)v; break; case CT_INOIDX: val->inoidx = (int)v; break; case CT_INOOFF: val->inooff = (int)v; break; case CT_NONE: case NCTS: /* NOTREACHED */ break; } return 1; } static ctype_t lookupcty(char *ctyname) { ctype_t cty; const char **name; for (cty = (ctype_t)0; cty < NCTS; cty++) { for (name = ctydescs[cty].names; *name; name++) { if (strcmp(ctyname, *name) == 0) return cty; } } return CT_NONE; } xfsprogs-4.9.0+nmu1ubuntu2/db/convert.h0000644000000000000000000000137013063067170014710 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void convert_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/crc.c0000644000000000000000000001040513033541503013763 0ustar /* * Copyright (c) 2016 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation. */ #include "libxfs.h" #include "addr.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "flist.h" #include "io.h" #include "init.h" #include "output.h" #include "bit.h" #include "print.h" static int crc_f(int argc, char **argv); static void crc_help(void); static const cmdinfo_t crc_cmd = { "crc", NULL, crc_f, 0, 1, 0, "[-i|-r|-v]", N_("manipulate crc values for V5 filesystem structures"), crc_help }; void crc_init(void) { if (xfs_sb_version_hascrc(&mp->m_sb)) add_command(&crc_cmd); } static void crc_help(void) { dbprintf(_( "\n" " 'crc' validates, invalidates, or recalculates the crc value for\n" " the current on-disk metadata structures in Version 5 filesystems.\n" "\n" " Usage: \"crc [-i|-r|-v]\"\n" "\n" )); } static int crc_f( int argc, char **argv) { const struct xfs_buf_ops *stashed_ops = NULL; extern char *progname; const field_t *fields; const ftattr_t *fa; flist_t *fl; int invalidate = 0; int recalculate = 0; int validate = 0; int c; if (cur_typ == NULL) { dbprintf(_("no current type\n")); return 0; } if (cur_typ->fields == NULL) { dbprintf(_("current type (%s) is not a structure\n"), cur_typ->name); return 0; } if (argc) while ((c = getopt(argc, argv, "irv")) != EOF) { switch (c) { case 'i': invalidate = 1; break; case 'r': recalculate = 1; break; case 'v': validate = 1; break; default: dbprintf(_("bad option for crc command\n")); return 0; } } else validate = 1; if (invalidate + recalculate + validate > 1) { dbprintf(_("crc command accepts only one option\n")); return 0; } if ((invalidate || recalculate) && ((x.isreadonly & LIBXFS_ISREADONLY) || !expert_mode)) { dbprintf(_("%s not in expert mode, writing disabled\n"), progname); return 0; } fields = cur_typ->fields; /* if we're a root field type, go down 1 layer to get field list */ if (fields->name[0] == '\0') { fa = &ftattrtab[fields->ftyp]; ASSERT(fa->ftyp == fields->ftyp); fields = fa->subfld; } /* Search for a CRC field */ fl = flist_find_ftyp(fields, FLDT_CRC); if (!fl) { dbprintf(_("No CRC field found for type %s\n"), cur_typ->name); return 0; } /* run down the field list and set offsets into the data */ if (!flist_parse(fields, fl, iocur_top->data, 0)) { flist_free(fl); dbprintf(_("parsing error\n")); return 0; } if (invalidate) { struct xfs_buf_ops nowrite_ops; flist_t *sfl; int bit_length; int parentoffset; int crc; sfl = fl; parentoffset = 0; while (sfl->child) { parentoffset = sfl->offset; sfl = sfl->child; } ASSERT(sfl->fld->ftyp == FLDT_CRC); bit_length = fsize(sfl->fld, iocur_top->data, parentoffset, 0); bit_length *= fcount(sfl->fld, iocur_top->data, parentoffset); crc = getbitval(iocur_top->data, sfl->offset, bit_length, BVUNSIGNED); /* Off by one.. */ crc = cpu_to_be32(crc + 1); setbitval(iocur_top->data, sfl->offset, bit_length, &crc); /* Temporarily remove write verifier to write a bad CRC */ stashed_ops = iocur_top->bp->b_ops; nowrite_ops.verify_read = stashed_ops->verify_read; nowrite_ops.verify_write = xfs_dummy_verify; iocur_top->bp->b_ops = &nowrite_ops; } if (invalidate || recalculate) { if (invalidate) dbprintf(_("Invalidating CRC:\n")); else dbprintf(_("Recalculating CRC:\n")); write_cur(); if (stashed_ops) iocur_top->bp->b_ops = stashed_ops; /* re-verify to get proper b_error state */ iocur_top->bp->b_ops->verify_read(iocur_top->bp); } else dbprintf(_("Verifying CRC:\n")); /* And show us what we've got! */ flist_print(fl); print_flist(fl); flist_free(fl); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/db/crc.h0000644000000000000000000000136313033541503013773 0ustar /* * Copyright (c) 2016 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation. */ struct field; extern void crc_init(void); extern void crc_struct(const field_t *fields, int argc, char **argv); xfsprogs-4.9.0+nmu1ubuntu2/db/debug.c0000644000000000000000000000244513063067170014315 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "debug.h" #include "output.h" static int debug_f(int argc, char **argv); static const cmdinfo_t debug_cmd = { "debug", NULL, debug_f, 0, 1, 0, N_("[flagbits]"), N_("set debug option bits"), NULL }; long debug_state; static int debug_f( int argc, char **argv) { char *p; if (argc > 1) { debug_state = strtol(argv[1], &p, 0); if (*p != '\0') { dbprintf(_("bad value for debug %s\n"), argv[1]); return 0; } } dbprintf("debug = %ld\n", debug_state); return 0; } void debug_init(void) { add_command(&debug_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/debug.h0000644000000000000000000000145013063067170014315 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define DEBUG_FLIST 0x1 extern long debug_state; extern void debug_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/dir2.c0000644000000000000000000007207113063067170014071 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "bit.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "dir2.h" #include "init.h" #include "output.h" static int dir2_block_hdr_count(void *obj, int startoff); static int dir2_block_leaf_count(void *obj, int startoff); static int dir2_block_leaf_offset(void *obj, int startoff, int idx); static int dir2_block_tail_count(void *obj, int startoff); static int dir2_block_tail_offset(void *obj, int startoff, int idx); static int dir2_block_u_count(void *obj, int startoff); static int dir2_block_u_offset(void *obj, int startoff, int idx); static int dir2_data_union_freetag_count(void *obj, int startoff); static int dir2_data_union_inumber_count(void *obj, int startoff); static int dir2_data_union_length_count(void *obj, int startoff); static int dir2_data_union_name_count(void *obj, int startoff); static int dir2_data_union_namelen_count(void *obj, int startoff); static int dir2_data_union_tag_count(void *obj, int startoff); static int dir2_data_union_tag_offset(void *obj, int startoff, int idx); static int dir2_data_hdr_count(void *obj, int startoff); static int dir2_data_u_count(void *obj, int startoff); static int dir2_data_u_offset(void *obj, int startoff, int idx); static int dir2_free_bests_count(void *obj, int startoff); static int dir2_free_hdr_count(void *obj, int startoff); static int dir2_leaf_bests_count(void *obj, int startoff); static int dir2_leaf_bests_offset(void *obj, int startoff, int idx); static int dir2_leaf_ents_count(void *obj, int startoff); static int dir2_leaf_hdr_count(void *obj, int startoff); static int dir2_leaf_tail_count(void *obj, int startoff); static int dir2_leaf_tail_offset(void *obj, int startoff, int idx); static int dir2_node_btree_count(void *obj, int startoff); static int dir2_node_hdr_count(void *obj, int startoff); const field_t dir2_hfld[] = { { "", FLDT_DIR2, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define BOFF(f) bitize(offsetof(struct xfs_dir2_data_hdr, f)) #define DOFF(f) bitize(offsetof(struct xfs_dir2_data_hdr, f)) #define FOFF(f) bitize(offsetof(struct xfs_dir2_free, f)) #define LOFF(f) bitize(offsetof(struct xfs_dir2_leaf, f)) #define NOFF(f) bitize(offsetof(struct xfs_da_intnode, f)) const field_t dir2_flds[] = { { "bhdr", FLDT_DIR2_DATA_HDR, OI(BOFF(magic)), dir2_block_hdr_count, FLD_COUNT, TYP_NONE }, { "bu", FLDT_DIR2_DATA_UNION, dir2_block_u_offset, dir2_block_u_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "bleaf", FLDT_DIR2_LEAF_ENTRY, dir2_block_leaf_offset, dir2_block_leaf_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "btail", FLDT_DIR2_BLOCK_TAIL, dir2_block_tail_offset, dir2_block_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "dhdr", FLDT_DIR2_DATA_HDR, OI(DOFF(magic)), dir2_data_hdr_count, FLD_COUNT, TYP_NONE }, { "du", FLDT_DIR2_DATA_UNION, dir2_data_u_offset, dir2_data_u_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "lhdr", FLDT_DIR2_LEAF_HDR, OI(LOFF(hdr)), dir2_leaf_hdr_count, FLD_COUNT, TYP_NONE }, { "lbests", FLDT_DIR2_DATA_OFF, dir2_leaf_bests_offset, dir2_leaf_bests_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "lents", FLDT_DIR2_LEAF_ENTRY, OI(LOFF(__ents)), dir2_leaf_ents_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "ltail", FLDT_DIR2_LEAF_TAIL, dir2_leaf_tail_offset, dir2_leaf_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "nhdr", FLDT_DA_NODE_HDR, OI(NOFF(hdr)), dir2_node_hdr_count, FLD_COUNT, TYP_NONE }, { "nbtree", FLDT_DA_NODE_ENTRY, OI(NOFF(__btree)), dir2_node_btree_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "fhdr", FLDT_DIR2_FREE_HDR, OI(FOFF(hdr)), dir2_free_hdr_count, FLD_COUNT, TYP_NONE }, { "fbests", FLDT_DIR2_DATA_OFFNZ, OI(FOFF(bests)), dir2_free_bests_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { NULL } }; #define BTOFF(f) bitize(offsetof(xfs_dir2_block_tail_t, f)) const field_t dir2_block_tail_flds[] = { { "count", FLDT_UINT32D, OI(BTOFF(count)), C1, 0, TYP_NONE }, { "stale", FLDT_UINT32D, OI(BTOFF(stale)), C1, 0, TYP_NONE }, { NULL } }; #define DFOFF(f) bitize(offsetof(xfs_dir2_data_free_t, f)) const field_t dir2_data_free_flds[] = { { "offset", FLDT_DIR2_DATA_OFF, OI(DFOFF(offset)), C1, 0, TYP_NONE }, { "length", FLDT_DIR2_DATA_OFF, OI(DFOFF(length)), C1, 0, TYP_NONE }, { NULL } }; #define DHOFF(f) bitize(offsetof(xfs_dir2_data_hdr_t, f)) const field_t dir2_data_hdr_flds[] = { { "magic", FLDT_UINT32X, OI(DHOFF(magic)), C1, 0, TYP_NONE }, { "bestfree", FLDT_DIR2_DATA_FREE, OI(DHOFF(bestfree)), CI(XFS_DIR2_DATA_FD_COUNT), FLD_ARRAY, TYP_NONE }, { NULL } }; #define DEOFF(f) bitize(offsetof(xfs_dir2_data_entry_t, f)) #define DUOFF(f) bitize(offsetof(xfs_dir2_data_unused_t, f)) const field_t dir2_data_union_flds[] = { { "freetag", FLDT_UINT16X, OI(DUOFF(freetag)), dir2_data_union_freetag_count, FLD_COUNT, TYP_NONE }, { "inumber", FLDT_INO, OI(DEOFF(inumber)), dir2_data_union_inumber_count, FLD_COUNT, TYP_INODE }, { "length", FLDT_DIR2_DATA_OFF, OI(DUOFF(length)), dir2_data_union_length_count, FLD_COUNT, TYP_NONE }, { "namelen", FLDT_UINT8D, OI(DEOFF(namelen)), dir2_data_union_namelen_count, FLD_COUNT, TYP_NONE }, { "name", FLDT_CHARNS, OI(DEOFF(name)), dir2_data_union_name_count, FLD_COUNT, TYP_NONE }, { "tag", FLDT_DIR2_DATA_OFF, dir2_data_union_tag_offset, dir2_data_union_tag_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, { NULL } }; #define LEOFF(f) bitize(offsetof(xfs_dir2_leaf_entry_t, f)) const field_t dir2_leaf_entry_flds[] = { { "hashval", FLDT_UINT32X, OI(LEOFF(hashval)), C1, 0, TYP_NONE }, { "address", FLDT_UINT32X, OI(LEOFF(address)), C1, 0, TYP_NONE }, { NULL } }; #define LHOFF(f) bitize(offsetof(xfs_dir2_leaf_hdr_t, f)) const field_t dir2_leaf_hdr_flds[] = { { "info", FLDT_DA_BLKINFO, OI(LHOFF(info)), C1, 0, TYP_NONE }, { "count", FLDT_UINT16D, OI(LHOFF(count)), C1, 0, TYP_NONE }, { "stale", FLDT_UINT16D, OI(LHOFF(stale)), C1, 0, TYP_NONE }, { NULL } }; #define LTOFF(f) bitize(offsetof(xfs_dir2_leaf_tail_t, f)) const field_t dir2_leaf_tail_flds[] = { { "bestcount", FLDT_UINT32D, OI(LTOFF(bestcount)), C1, 0, TYP_NONE }, { NULL } }; #define FHOFF(f) bitize(offsetof(xfs_dir2_free_hdr_t, f)) const field_t dir2_free_hdr_flds[] = { { "magic", FLDT_UINT32X, OI(FHOFF(magic)), C1, 0, TYP_NONE }, { "firstdb", FLDT_INT32D, OI(FHOFF(firstdb)), C1, 0, TYP_NONE }, { "nvalid", FLDT_INT32D, OI(FHOFF(nvalid)), C1, 0, TYP_NONE }, { "nused", FLDT_INT32D, OI(FHOFF(nused)), C1, 0, TYP_NONE }, { NULL } }; #define DBOFF(f) bitize(offsetof(xfs_da_blkinfo_t, f)) const field_t da_blkinfo_flds[] = { { "forw", FLDT_DIRBLOCK, OI(DBOFF(forw)), C1, 0, TYP_INODATA }, { "back", FLDT_DIRBLOCK, OI(DBOFF(back)), C1, 0, TYP_INODATA }, { "magic", FLDT_UINT16X, OI(DBOFF(magic)), C1, 0, TYP_NONE }, { "pad", FLDT_UINT16X, OI(DBOFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, { NULL } }; #define EOFF(f) bitize(offsetof(xfs_da_node_entry_t, f)) const field_t da_node_entry_flds[] = { { "hashval", FLDT_UINT32X, OI(EOFF(hashval)), C1, 0, TYP_NONE }, { "before", FLDT_DIRBLOCK, OI(EOFF(before)), C1, 0, TYP_INODATA }, { NULL } }; #define HOFF(f) bitize(offsetof(xfs_da_node_hdr_t, f)) const field_t da_node_hdr_flds[] = { { "info", FLDT_DA_BLKINFO, OI(HOFF(info)), C1, 0, TYP_NONE }, { "count", FLDT_UINT16D, OI(HOFF(__count)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(HOFF(__level)), C1, 0, TYP_NONE }, { NULL } }; /* * Worker functions shared between either dir2/dir3 or block/data formats */ static int __dir2_block_tail_offset( struct xfs_dir2_data_hdr *block, int startoff, int idx) { struct xfs_dir2_block_tail *btp; ASSERT(startoff == 0); ASSERT(idx == 0); btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); return bitize((int)((char *)btp - (char *)block)); } static int __dir2_data_entries_count( char *ptr, char *endptr) { int i; for (i = 0; ptr < endptr; i++) { struct xfs_dir2_data_entry *dep; struct xfs_dir2_data_unused *dup; dup = (xfs_dir2_data_unused_t *)ptr; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) ptr += be16_to_cpu(dup->length); else { dep = (xfs_dir2_data_entry_t *)ptr; ptr += M_DIROPS(mp)->data_entsize(dep->namelen); } } return i; } static char * __dir2_data_entry_offset( char *ptr, char *endptr, int idx) { int i; for (i = 0; i < idx; i++) { struct xfs_dir2_data_entry *dep; struct xfs_dir2_data_unused *dup; ASSERT(ptr < endptr); dup = (xfs_dir2_data_unused_t *)ptr; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) ptr += be16_to_cpu(dup->length); else { dep = (xfs_dir2_data_entry_t *)ptr; ptr += M_DIROPS(mp)->data_entsize(dep->namelen); } } return ptr; } /* * Block format functions */ static int dir2_block_hdr_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *block = obj; ASSERT(startoff == 0); return be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC; } static int dir3_block_hdr_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *block = obj; ASSERT(startoff == 0); return be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC; } static int dir2_block_leaf_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *block = obj; struct xfs_dir2_block_tail *btp; ASSERT(startoff == 0); if (be32_to_cpu(block->magic) != XFS_DIR2_BLOCK_MAGIC && be32_to_cpu(block->magic) != XFS_DIR3_BLOCK_MAGIC) return 0; btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); return be32_to_cpu(btp->count); } static int dir2_block_leaf_offset( void *obj, int startoff, int idx) { struct xfs_dir2_data_hdr *block = obj; struct xfs_dir2_block_tail *btp; struct xfs_dir2_leaf_entry *lep; ASSERT(startoff == 0); ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC); btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); lep = xfs_dir2_block_leaf_p(btp) + idx; return bitize((int)((char *)lep - (char *)block)); } static int dir2_block_tail_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *block = obj; ASSERT(startoff == 0); return be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC; } static int dir3_block_tail_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *block = obj; ASSERT(startoff == 0); return be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC; } static int dir2_block_tail_offset( void *obj, int startoff, int idx) { struct xfs_dir2_data_hdr *block = obj; ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC); return __dir2_block_tail_offset(block, startoff, idx); } static int dir2_block_u_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *block = obj; struct xfs_dir2_block_tail *btp; ASSERT(startoff == 0); if (be32_to_cpu(block->magic) != XFS_DIR2_BLOCK_MAGIC && be32_to_cpu(block->magic) != XFS_DIR3_BLOCK_MAGIC) return 0; btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); return __dir2_data_entries_count( (char *)M_DIROPS(mp)->data_unused_p(block), (char *)xfs_dir2_block_leaf_p(btp)); } static int dir2_block_u_offset( void *obj, int startoff, int idx) { struct xfs_dir2_data_hdr *block = obj; struct xfs_dir2_block_tail *btp; char *ptr; ASSERT(startoff == 0); ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC); btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); ptr = __dir2_data_entry_offset( (char *)M_DIROPS(mp)->data_unused_p(block), (char *)xfs_dir2_block_leaf_p(btp), idx); return bitize((int)(ptr - (char *)block)); } /* * Data block format functions */ static int dir2_data_union_freetag_count( void *obj, int startoff) { xfs_dir2_data_unused_t *dup; char *end; ASSERT(bitoffs(startoff) == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); end = (char *)&dup->freetag + sizeof(dup->freetag); return end <= (char *)obj + mp->m_dir_geo->blksize && be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG; } static int dir2_data_union_inumber_count( void *obj, int startoff) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; char *end; ASSERT(bitoffs(startoff) == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); dep = (xfs_dir2_data_entry_t *)dup; end = (char *)&dep->inumber + sizeof(dep->inumber); return end <= (char *)obj + mp->m_dir_geo->blksize && be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG; } static int dir2_data_union_length_count( void *obj, int startoff) { xfs_dir2_data_unused_t *dup; char *end; ASSERT(bitoffs(startoff) == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); end = (char *)&dup->length + sizeof(dup->length); return end <= (char *)obj + mp->m_dir_geo->blksize && be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG; } static int dir2_data_union_name_count( void *obj, int startoff) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; char *end; ASSERT(bitoffs(startoff) == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); dep = (xfs_dir2_data_entry_t *)dup; end = (char *)&dep->namelen + sizeof(dep->namelen); if (end >= (char *)obj + mp->m_dir_geo->blksize || be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) return 0; end = (char *)&dep->name[0] + dep->namelen; return end <= (char *)obj + mp->m_dir_geo->blksize ? dep->namelen : 0; } static int dir2_data_union_namelen_count( void *obj, int startoff) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; char *end; ASSERT(bitoffs(startoff) == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); dep = (xfs_dir2_data_entry_t *)dup; end = (char *)&dep->namelen + sizeof(dep->namelen); return end <= (char *)obj + mp->m_dir_geo->blksize && be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG; } static int dir2_data_union_tag_count( void *obj, int startoff) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; char *end; __be16 *tagp; ASSERT(bitoffs(startoff) == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); dep = (xfs_dir2_data_entry_t *)dup; end = (char *)&dup->freetag + sizeof(dup->freetag); if (end > (char *)obj + mp->m_dir_geo->blksize) return 0; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { end = (char *)&dup->length + sizeof(dup->length); if (end > (char *)obj + mp->m_dir_geo->blksize) return 0; tagp = xfs_dir2_data_unused_tag_p(dup); } else { end = (char *)&dep->namelen + sizeof(dep->namelen); if (end > (char *)obj + mp->m_dir_geo->blksize) return 0; tagp = M_DIROPS(mp)->data_entry_tag_p(dep); } end = (char *)tagp + sizeof(*tagp); return end <= (char *)obj + mp->m_dir_geo->blksize; } static int dir2_data_union_tag_offset( void *obj, int startoff, int idx) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) return bitize((int)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)dup)); dep = (xfs_dir2_data_entry_t *)dup; return bitize((int)((char *)M_DIROPS(mp)->data_entry_tag_p(dep) - (char *)dep)); } static int dir2_data_hdr_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *data = obj; ASSERT(startoff == 0); return be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC; } static int dir3_data_hdr_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *data = obj; ASSERT(startoff == 0); return be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC; } static int dir2_data_u_count( void *obj, int startoff) { struct xfs_dir2_data_hdr *data = obj; ASSERT(startoff == 0); if (be32_to_cpu(data->magic) != XFS_DIR2_DATA_MAGIC && be32_to_cpu(data->magic) != XFS_DIR3_DATA_MAGIC) return 0; return __dir2_data_entries_count( (char *)M_DIROPS(mp)->data_unused_p(data), (char *)data + mp->m_dir_geo->blksize); } static int dir2_data_u_offset( void *obj, int startoff, int idx) { struct xfs_dir2_data_hdr *data = obj; char *ptr; ASSERT(startoff == 0); ASSERT(be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC || be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC); ptr = __dir2_data_entry_offset( (char *)M_DIROPS(mp)->data_unused_p(data), (char *)data + mp->m_dir_geo->blksize, idx); return bitize((int)(ptr - (char *)data)); } int dir2_data_union_size( void *obj, int startoff, int idx) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) return bitize(be16_to_cpu(dup->length)); else { dep = (xfs_dir2_data_entry_t *)dup; return bitize(M_DIROPS(mp)->data_entsize(dep->namelen)); } } static int dir3_data_union_ftype_offset( void *obj, int startoff, int idx) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) return bitize((int)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)dup)); dep = (xfs_dir2_data_entry_t *)dup; return bitize((int)((char *)&dep->name[dep->namelen] - (char *)dep)); } /* * Free block functions */ static int dir2_free_bests_count( void *obj, int startoff) { struct xfs_dir2_free *free = obj; ASSERT(startoff == 0); if (be32_to_cpu(free->hdr.magic) != XFS_DIR2_FREE_MAGIC) return 0; return be32_to_cpu(free->hdr.nvalid); } static int dir3_free_bests_count( void *obj, int startoff) { struct xfs_dir3_free *free = obj; ASSERT(startoff == 0); if (be32_to_cpu(free->hdr.hdr.magic) != XFS_DIR3_FREE_MAGIC) return 0; return be32_to_cpu(free->hdr.nvalid); } static int dir2_free_hdr_count( void *obj, int startoff) { struct xfs_dir2_free *free = obj; ASSERT(startoff == 0); return be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC; } static int dir3_free_hdr_count( void *obj, int startoff) { struct xfs_dir3_free *free = obj; ASSERT(startoff == 0); return be32_to_cpu(free->hdr.hdr.magic) == XFS_DIR3_FREE_MAGIC; } /* * Leaf block functions */ static int dir2_leaf_bests_count( void *obj, int startoff) { struct xfs_dir2_leaf *leaf = obj; struct xfs_dir2_leaf_tail *ltp; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR3_LEAF1_MAGIC) return 0; ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); return be32_to_cpu(ltp->bestcount); } static int dir2_leaf_bests_offset( void *obj, int startoff, int idx) { struct xfs_dir2_leaf *leaf = obj; struct xfs_dir2_leaf_tail *ltp; __be16 *lbp; ASSERT(startoff == 0); ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR3_LEAF1_MAGIC); ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); lbp = xfs_dir2_leaf_bests_p(ltp) + idx; return bitize((int)((char *)lbp - (char *)leaf)); } static int dir2_leaf_ents_count( void *obj, int startoff) { struct xfs_dir2_leaf *leaf = obj; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAFN_MAGIC) return 0; return be16_to_cpu(leaf->hdr.count); } static int dir3_leaf_ents_count( void *obj, int startoff) { struct xfs_dir3_leaf *leaf = obj; ASSERT(startoff == 0); if (be16_to_cpu(leaf->hdr.info.hdr.magic) != XFS_DIR3_LEAF1_MAGIC && be16_to_cpu(leaf->hdr.info.hdr.magic) != XFS_DIR3_LEAFN_MAGIC) return 0; return be16_to_cpu(leaf->hdr.count); } static int dir2_leaf_hdr_count( void *obj, int startoff) { struct xfs_dir2_leaf *leaf = obj; ASSERT(startoff == 0); return be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC; } static int dir3_leaf_hdr_count( void *obj, int startoff) { struct xfs_dir3_leaf *leaf = obj; ASSERT(startoff == 0); return be16_to_cpu(leaf->hdr.info.hdr.magic) == XFS_DIR3_LEAF1_MAGIC || be16_to_cpu(leaf->hdr.info.hdr.magic) == XFS_DIR3_LEAFN_MAGIC; } static int dir2_leaf_tail_count( void *obj, int startoff) { struct xfs_dir2_leaf *leaf = obj; ASSERT(startoff == 0); return be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC; } static int dir3_leaf_tail_count( void *obj, int startoff) { struct xfs_dir3_leaf *leaf = obj; ASSERT(startoff == 0); return be16_to_cpu(leaf->hdr.info.hdr.magic) == XFS_DIR3_LEAF1_MAGIC; } static int dir2_leaf_tail_offset( void *obj, int startoff, int idx) { struct xfs_dir2_leaf *leaf = obj; struct xfs_dir2_leaf_tail *ltp; ASSERT(startoff == 0); ASSERT(idx == 0); ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR3_LEAF1_MAGIC); ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); return bitize((int)((char *)ltp - (char *)leaf)); } /* * Node format functions */ static int dir2_node_btree_count( void *obj, int startoff) { xfs_da_intnode_t *node = obj; ASSERT(startoff == 0); if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) return 0; return be16_to_cpu(node->hdr.__count); } static int dir3_node_btree_count( void *obj, int startoff) { struct xfs_da3_intnode *node = obj; ASSERT(startoff == 0); if (be16_to_cpu(node->hdr.info.hdr.magic) != XFS_DA3_NODE_MAGIC) return 0; return be16_to_cpu(node->hdr.__count); } static int dir2_node_hdr_count( void *obj, int startoff) { struct xfs_da_intnode *node = obj; ASSERT(startoff == 0); return be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC; } static int dir3_node_hdr_count( void *obj, int startoff) { struct xfs_da3_intnode *node = obj; ASSERT(startoff == 0); return be16_to_cpu(node->hdr.info.hdr.magic) == XFS_DA3_NODE_MAGIC; } int dir2_size( void *obj, int startoff, int idx) { return bitize(mp->m_dir_geo->blksize); } /* * CRC enabled structure definitions */ const field_t dir3_hfld[] = { { "", FLDT_DIR3, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define B3OFF(f) bitize(offsetof(struct xfs_dir3_data_hdr, f)) #define D3OFF(f) bitize(offsetof(struct xfs_dir3_data_hdr, f)) #define F3OFF(f) bitize(offsetof(struct xfs_dir3_free, f)) #define L3OFF(f) bitize(offsetof(struct xfs_dir3_leaf, f)) #define N3OFF(f) bitize(offsetof(struct xfs_da3_intnode, f)) const field_t dir3_flds[] = { { "bhdr", FLDT_DIR3_DATA_HDR, OI(B3OFF(hdr)), dir3_block_hdr_count, FLD_COUNT, TYP_NONE }, { "bu", FLDT_DIR3_DATA_UNION, dir2_block_u_offset, dir2_block_u_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "bleaf", FLDT_DIR2_LEAF_ENTRY, dir2_block_leaf_offset, dir2_block_leaf_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "btail", FLDT_DIR2_BLOCK_TAIL, dir2_block_tail_offset, dir3_block_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "dhdr", FLDT_DIR3_DATA_HDR, OI(D3OFF(hdr)), dir3_data_hdr_count, FLD_COUNT, TYP_NONE }, { "du", FLDT_DIR3_DATA_UNION, dir2_data_u_offset, dir2_data_u_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "lhdr", FLDT_DIR3_LEAF_HDR, OI(L3OFF(hdr)), dir3_leaf_hdr_count, FLD_COUNT, TYP_NONE }, { "lbests", FLDT_DIR2_DATA_OFF, dir2_leaf_bests_offset, dir2_leaf_bests_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "lents", FLDT_DIR2_LEAF_ENTRY, OI(L3OFF(__ents)), dir3_leaf_ents_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "ltail", FLDT_DIR2_LEAF_TAIL, dir2_leaf_tail_offset, dir3_leaf_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, { "nhdr", FLDT_DA3_NODE_HDR, OI(N3OFF(hdr)), dir3_node_hdr_count, FLD_COUNT, TYP_NONE }, { "nbtree", FLDT_DA_NODE_ENTRY, OI(N3OFF(__btree)), dir3_node_btree_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "fhdr", FLDT_DIR3_FREE_HDR, OI(F3OFF(hdr)), dir3_free_hdr_count, FLD_COUNT, TYP_NONE }, { "fbests", FLDT_DIR2_DATA_OFFNZ, OI(F3OFF(bests)), dir3_free_bests_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { NULL } }; #define D3EOFF(f) bitize(offsetof(xfs_dir2_data_entry_t, f)) #define D3UOFF(f) bitize(offsetof(xfs_dir2_data_unused_t, f)) const field_t dir3_data_union_flds[] = { { "freetag", FLDT_UINT16X, OI(D3UOFF(freetag)), dir2_data_union_freetag_count, FLD_COUNT, TYP_NONE }, { "inumber", FLDT_INO, OI(D3EOFF(inumber)), dir2_data_union_inumber_count, FLD_COUNT, TYP_INODE }, { "length", FLDT_DIR2_DATA_OFF, OI(D3UOFF(length)), dir2_data_union_length_count, FLD_COUNT, TYP_NONE }, { "namelen", FLDT_UINT8D, OI(D3EOFF(namelen)), dir2_data_union_namelen_count, FLD_COUNT, TYP_NONE }, { "name", FLDT_CHARNS, OI(D3EOFF(name)), dir2_data_union_name_count, FLD_COUNT, TYP_NONE }, { "filetype", FLDT_UINT8D, dir3_data_union_ftype_offset, C1, FLD_OFFSET, TYP_NONE }, { "tag", FLDT_DIR2_DATA_OFF, dir2_data_union_tag_offset, dir2_data_union_tag_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, { NULL } }; #define DBH3OFF(f) bitize(offsetof(struct xfs_dir3_blk_hdr, f)) const field_t dir3_blkhdr_flds[] = { { "magic", FLDT_UINT32X, OI(DBH3OFF(magic)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(DBH3OFF(crc)), C1, 0, TYP_NONE }, { "bno", FLDT_DFSBNO, OI(DBH3OFF(blkno)), C1, 0, TYP_BMAPBTD }, { "lsn", FLDT_UINT64X, OI(DBH3OFF(lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(DBH3OFF(uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_INO, OI(DBH3OFF(owner)), C1, 0, TYP_NONE }, { NULL } }; #define DH3OFF(f) bitize(offsetof(struct xfs_dir3_data_hdr, f)) const field_t dir3_data_hdr_flds[] = { { "hdr", FLDT_DIR3_BLKHDR, OI(DH3OFF(hdr)), C1, 0, TYP_NONE }, { "bestfree", FLDT_DIR2_DATA_FREE, OI(DH3OFF(best_free)), CI(XFS_DIR2_DATA_FD_COUNT), FLD_ARRAY, TYP_NONE }, { NULL } }; #define LH3OFF(f) bitize(offsetof(struct xfs_dir3_leaf_hdr, f)) const field_t dir3_leaf_hdr_flds[] = { { "info", FLDT_DA3_BLKINFO, OI(LH3OFF(info)), C1, 0, TYP_NONE }, { "count", FLDT_UINT16D, OI(LH3OFF(count)), C1, 0, TYP_NONE }, { "stale", FLDT_UINT16D, OI(LH3OFF(stale)), C1, 0, TYP_NONE }, { NULL } }; #define FH3OFF(f) bitize(offsetof(struct xfs_dir3_free_hdr, f)) const field_t dir3_free_hdr_flds[] = { { "hdr", FLDT_DIR3_BLKHDR, OI(FH3OFF(hdr)), C1, 0, TYP_NONE }, { "firstdb", FLDT_INT32D, OI(FH3OFF(firstdb)), C1, 0, TYP_NONE }, { "nvalid", FLDT_INT32D, OI(FH3OFF(nvalid)), C1, 0, TYP_NONE }, { "nused", FLDT_INT32D, OI(FH3OFF(nused)), C1, 0, TYP_NONE }, { NULL } }; #define DB3OFF(f) bitize(offsetof(struct xfs_da3_blkinfo, f)) const field_t da3_blkinfo_flds[] = { { "hdr", FLDT_DA_BLKINFO, OI(DB3OFF(hdr)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(DB3OFF(crc)), C1, 0, TYP_NONE }, { "bno", FLDT_DFSBNO, OI(DB3OFF(blkno)), C1, 0, TYP_BMAPBTD }, { "lsn", FLDT_UINT64X, OI(DB3OFF(lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(DB3OFF(uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_INO, OI(DB3OFF(owner)), C1, 0, TYP_NONE }, { NULL } }; #define H3OFF(f) bitize(offsetof(struct xfs_da3_node_hdr, f)) const field_t da3_node_hdr_flds[] = { { "info", FLDT_DA3_BLKINFO, OI(H3OFF(info)), C1, 0, TYP_NONE }, { "count", FLDT_UINT16D, OI(H3OFF(__count)), C1, 0, TYP_NONE }, { "level", FLDT_UINT16D, OI(H3OFF(__level)), C1, 0, TYP_NONE }, { "pad", FLDT_UINT32D, OI(H3OFF(__pad32)), C1, 0, TYP_NONE }, { NULL } }; /* * Special read verifier for directory buffers. Detect the magic number * appropriately and set the correct verifier and call it. */ static void xfs_dir3_db_read_verify( struct xfs_buf *bp) { __be32 magic32; __be16 magic16; magic32 = *(__be32 *)bp->b_addr; magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic; switch (magic32) { case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): bp->b_ops = &xfs_dir3_block_buf_ops; goto verify; case cpu_to_be32(XFS_DIR3_DATA_MAGIC): bp->b_ops = &xfs_dir3_data_buf_ops; goto verify; case cpu_to_be32(XFS_DIR3_FREE_MAGIC): bp->b_ops = &xfs_dir3_free_buf_ops; goto verify; default: break; } switch (magic16) { case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC): bp->b_ops = &xfs_dir3_leaf1_buf_ops; break; case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC): bp->b_ops = &xfs_dir3_leafn_buf_ops; break; case cpu_to_be16(XFS_DA3_NODE_MAGIC): bp->b_ops = &xfs_da3_node_buf_ops; break; default: dbprintf(_("Unknown directory buffer type!\n")); xfs_buf_ioerror(bp, -EFSCORRUPTED); return; } verify: bp->b_ops->verify_read(bp); } static void xfs_dir3_db_write_verify( struct xfs_buf *bp) { dbprintf(_("Writing unknown directory buffer type!\n")); xfs_buf_ioerror(bp, -EFSCORRUPTED); } const struct xfs_buf_ops xfs_dir3_db_buf_ops = { .name = "xfs_dir3", .verify_read = xfs_dir3_db_read_verify, .verify_write = xfs_dir3_db_write_verify, }; xfsprogs-4.9.0+nmu1ubuntu2/db/dir2.h0000644000000000000000000000377713063067170014105 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * common types across directory formats */ extern const field_t dir2_block_tail_flds[]; extern const field_t dir2_data_free_flds[]; extern const field_t dir2_data_union_flds[]; extern const field_t dir2_leaf_tail_flds[]; extern const field_t dir2_leaf_entry_flds[]; extern const field_t da_node_entry_flds[]; /* * dirv2 specific types */ extern const field_t dir2_flds[]; extern const field_t dir2_hfld[]; extern const field_t dir2_data_hdr_flds[]; extern const field_t dir2_free_hdr_flds[]; extern const field_t dir2_leaf_hdr_flds[]; extern const field_t da_blkinfo_flds[]; extern const field_t da_node_hdr_flds[]; /* * dirv3 specific types */ extern const field_t dir3_flds[]; extern const field_t dir3_hfld[]; extern const field_t dir3_blkhdr_flds[]; extern const field_t dir3_data_hdr_flds[]; extern const field_t dir3_free_hdr_flds[]; extern const field_t dir3_leaf_hdr_flds[]; extern const field_t dir3_data_union_flds[]; extern const field_t da3_blkinfo_flds[]; extern const field_t da3_node_hdr_flds[]; static inline uint8_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep) { return &(sfep)->name[(sfep)->namelen]; } extern int dir2_data_union_size(void *obj, int startoff, int idx); extern int dir2_size(void *obj, int startoff, int idx); extern const struct xfs_buf_ops xfs_dir3_db_buf_ops; xfsprogs-4.9.0+nmu1ubuntu2/db/dir2sf.c0000644000000000000000000001542713063067170014424 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "bit.h" #include "dir2.h" #include "dir2sf.h" #include "init.h" static int dir2_inou_i4_count(void *obj, int startoff); static int dir2_inou_i8_count(void *obj, int startoff); static int dir2_sf_entry_inumber_offset(void *obj, int startoff, int idx); static int dir2_sf_entry_name_count(void *obj, int startoff); static int dir2_sf_list_count(void *obj, int startoff); static int dir2_sf_list_offset(void *obj, int startoff, int idx); #define OFF(f) bitize(offsetof(struct xfs_dir2_sf_hdr, f)) const field_t dir2sf_flds[] = { { "hdr", FLDT_DIR2_SF_HDR, OI(OFF(count)), C1, 0, TYP_NONE }, { "list", FLDT_DIR2_SF_ENTRY, dir2_sf_list_offset, dir2_sf_list_count, FLD_ARRAY|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { NULL } }; const field_t dir2_inou_flds[] = { { "i8", FLDT_DIR2_INO8, 0, dir2_inou_i8_count, FLD_COUNT, TYP_INODE }, { "i4", FLDT_DIR2_INO4, 0, dir2_inou_i4_count, FLD_COUNT, TYP_INODE }, { NULL } }; #define HOFF(f) bitize(offsetof(xfs_dir2_sf_hdr_t, f)) const field_t dir2_sf_hdr_flds[] = { { "count", FLDT_UINT8D, OI(HOFF(count)), C1, 0, TYP_NONE }, { "i8count", FLDT_UINT8D, OI(HOFF(i8count)), C1, 0, TYP_NONE }, { "parent", FLDT_DIR2_INOU, OI(HOFF(parent)), C1, 0, TYP_NONE }, { NULL } }; #define EOFF(f) bitize(offsetof(xfs_dir2_sf_entry_t, f)) const field_t dir2_sf_entry_flds[] = { { "namelen", FLDT_UINT8D, OI(EOFF(namelen)), C1, 0, TYP_NONE }, { "offset", FLDT_DIR2_SF_OFF, OI(EOFF(offset)), C1, 0, TYP_NONE }, { "name", FLDT_CHARNS, OI(EOFF(name)), dir2_sf_entry_name_count, FLD_COUNT, TYP_NONE }, { "inumber", FLDT_DIR2_INOU, dir2_sf_entry_inumber_offset, C1, FLD_OFFSET, TYP_NONE }, { NULL } }; /*ARGSUSED*/ static int dir2_inou_i4_count( void *obj, int startoff) { struct xfs_dinode *dip = obj; struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); sf = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); return sf->i8count == 0; } /*ARGSUSED*/ static int dir2_inou_i8_count( void *obj, int startoff) { struct xfs_dinode *dip = obj; struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); sf = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); return sf->i8count != 0; } /*ARGSUSED*/ int dir2_inou_size( void *obj, int startoff, int idx) { struct xfs_dinode *dip = obj; struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); sf = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); return bitize(sf->i8count ? XFS_INO64_SIZE : XFS_INO32_SIZE); } static int dir2_sf_entry_name_count( void *obj, int startoff) { xfs_dir2_sf_entry_t *e; ASSERT(bitoffs(startoff) == 0); e = (xfs_dir2_sf_entry_t *)((char *)obj + byteize(startoff)); return e->namelen; } static int dir2_sf_entry_inumber_offset( void *obj, int startoff, int idx) { xfs_dir2_sf_entry_t *e; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); e = (xfs_dir2_sf_entry_t *)((char *)obj + byteize(startoff)); return bitize((int)((char *)xfs_dir2_sf_inumberp(e) - (char *)e)); } static int dir3_sf_entry_inumber_offset( void *obj, int startoff, int idx) { xfs_dir2_sf_entry_t *e; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); e = (xfs_dir2_sf_entry_t *)((char *)obj + byteize(startoff)); /* plus 1 to skip the ftype entry */ return bitize((int)((char *)xfs_dir2_sf_inumberp(e) + 1 - (char *)e)); } static int dir3_sf_entry_ftype_offset( void *obj, int startoff, int idx) { xfs_dir2_sf_entry_t *e; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); e = (xfs_dir2_sf_entry_t *)((char *)obj + byteize(startoff)); return bitize((int)((char *)&e->name[e->namelen] - (char *)e)); } int dir2_sf_entry_size( void *obj, int startoff, int idx) { xfs_dir2_sf_entry_t *e; int i; struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff)); e = xfs_dir2_sf_firstentry(sf); for (i = 0; i < idx; i++) e = M_DIROPS(mp)->sf_nextentry(sf, e); return bitize((int)M_DIROPS(mp)->sf_entsize(sf, e->namelen)); } /*ARGSUSED*/ int dir2_sf_hdr_size( void *obj, int startoff, int idx) { struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff)); return bitize(xfs_dir2_sf_hdr_size(sf->i8count)); } static int dir2_sf_list_count( void *obj, int startoff) { struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff)); return sf->count; } static int dir2_sf_list_offset( void *obj, int startoff, int idx) { xfs_dir2_sf_entry_t *e; int i; struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff)); e = xfs_dir2_sf_firstentry(sf); for (i = 0; i < idx; i++) e = M_DIROPS(mp)->sf_nextentry(sf, e); return bitize((int)((char *)e - (char *)sf)); } /*ARGSUSED*/ int dir2sf_size( void *obj, int startoff, int idx) { xfs_dir2_sf_entry_t *e; int i; struct xfs_dir2_sf_hdr *sf; ASSERT(bitoffs(startoff) == 0); ASSERT(idx == 0); sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff)); e = xfs_dir2_sf_firstentry(sf); for (i = 0; i < sf->count; i++) e = M_DIROPS(mp)->sf_nextentry(sf, e); return bitize((int)((char *)e - (char *)sf)); } #define OFF(f) bitize(offsetof(struct xfs_dir2_sf_hdr, f)) const field_t dir3sf_flds[] = { { "hdr", FLDT_DIR2_SF_HDR, OI(OFF(count)), C1, 0, TYP_NONE }, { "list", FLDT_DIR3_SF_ENTRY, dir2_sf_list_offset, dir2_sf_list_count, FLD_ARRAY|FLD_COUNT|FLD_OFFSET, TYP_NONE }, { NULL } }; #define E3OFF(f) bitize(offsetof(xfs_dir2_sf_entry_t, f)) const field_t dir3_sf_entry_flds[] = { { "namelen", FLDT_UINT8D, OI(EOFF(namelen)), C1, 0, TYP_NONE }, { "offset", FLDT_DIR2_SF_OFF, OI(EOFF(offset)), C1, 0, TYP_NONE }, { "name", FLDT_CHARNS, OI(EOFF(name)), dir2_sf_entry_name_count, FLD_COUNT, TYP_NONE }, { "inumber", FLDT_DIR2_INOU, dir3_sf_entry_inumber_offset, C1, FLD_OFFSET, TYP_NONE }, { "filetype", FLDT_UINT8D, dir3_sf_entry_ftype_offset, C1, FLD_OFFSET, TYP_NONE }, { NULL } }; xfsprogs-4.9.0+nmu1ubuntu2/db/dir2sf.h0000644000000000000000000000227713063067167014436 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const field_t dir2sf_flds[]; extern const field_t dir2_inou_flds[]; extern const field_t dir2_sf_hdr_flds[]; extern const field_t dir2_sf_entry_flds[]; extern const field_t dir3sf_flds[]; extern const field_t dir3_sf_entry_flds[]; extern int dir2sf_size(void *obj, int startoff, int idx); extern int dir2_inou_size(void *obj, int startoff, int idx); extern int dir2_sf_entry_size(void *obj, int startoff, int idx); extern int dir2_sf_hdr_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/dquot.c0000644000000000000000000001162613063067170014364 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "bit.h" #include "bmap.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "inode.h" #include "io.h" #include "init.h" #include "output.h" #include "dquot.h" static int dquot_f(int argc, char **argv); static void dquot_help(void); static const cmdinfo_t dquot_cmd = { "dquot", NULL, dquot_f, 1, 2, 1, N_("[-g|-p|-u] id"), N_("set current address to a group, project or user quota block for given ID"), dquot_help, }; const field_t dqblk_hfld[] = { { "", FLDT_DQBLK, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define DDOFF(f) bitize(offsetof(xfs_dqblk_t, dd_ ## f)) #define DDSZC(f) szcount(xfs_dqblk_t, dd_ ## f) const field_t dqblk_flds[] = { { "diskdq", FLDT_DISK_DQUOT, OI(DDOFF(diskdq)), C1, 0, TYP_NONE }, { "fill", FLDT_CHARS, OI(DDOFF(fill)), CI(DDSZC(fill)), FLD_SKIPALL, TYP_NONE }, { "crc", FLDT_CRC, OI(DDOFF(crc)), C1, 0, TYP_NONE }, { "lsn", FLDT_UINT64X, OI(DDOFF(lsn)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(DDOFF(uuid)), C1, 0, TYP_NONE }, { NULL } }; #define DOFF(f) bitize(offsetof(xfs_disk_dquot_t, d_ ## f)) const field_t disk_dquot_flds[] = { { "magic", FLDT_UINT16X, OI(DOFF(magic)), C1, 0, TYP_NONE }, { "version", FLDT_UINT8X, OI(DOFF(version)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT8X, OI(DOFF(flags)), C1, 0, TYP_NONE }, { "id", FLDT_DQID, OI(DOFF(id)), C1, 0, TYP_NONE }, { "blk_hardlimit", FLDT_QCNT, OI(DOFF(blk_hardlimit)), C1, 0, TYP_NONE }, { "blk_softlimit", FLDT_QCNT, OI(DOFF(blk_softlimit)), C1, 0, TYP_NONE }, { "ino_hardlimit", FLDT_QCNT, OI(DOFF(ino_hardlimit)), C1, 0, TYP_NONE }, { "ino_softlimit", FLDT_QCNT, OI(DOFF(ino_softlimit)), C1, 0, TYP_NONE }, { "bcount", FLDT_QCNT, OI(DOFF(bcount)), C1, 0, TYP_NONE }, { "icount", FLDT_QCNT, OI(DOFF(icount)), C1, 0, TYP_NONE }, { "itimer", FLDT_INT32D, OI(DOFF(itimer)), C1, 0, TYP_NONE }, { "btimer", FLDT_INT32D, OI(DOFF(btimer)), C1, 0, TYP_NONE }, { "iwarns", FLDT_QWARNCNT, OI(DOFF(iwarns)), C1, 0, TYP_NONE }, { "bwarns", FLDT_QWARNCNT, OI(DOFF(bwarns)), C1, 0, TYP_NONE }, { "pad0", FLDT_INT32D, OI(DOFF(pad0)), C1, FLD_SKIPALL, TYP_NONE }, { "rtb_hardlimit", FLDT_QCNT, OI(DOFF(rtb_hardlimit)), C1, 0, TYP_NONE }, { "rtb_softlimit", FLDT_QCNT, OI(DOFF(rtb_softlimit)), C1, 0, TYP_NONE }, { "rtbcount", FLDT_QCNT, OI(DOFF(rtbcount)), C1, 0, TYP_NONE }, { "rtbtimer", FLDT_INT32D, OI(DOFF(rtbtimer)), C1, 0, TYP_NONE }, { "rtbwarns", FLDT_QWARNCNT, OI(DOFF(rtbwarns)), C1, 0, TYP_NONE }, { "pad", FLDT_UINT16X, OI(DOFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, { NULL } }; static void dquot_help(void) { } static int dquot_f( int argc, char **argv) { bmap_ext_t bm; int c; int dogrp; int doprj; xfs_dqid_t id; xfs_ino_t ino; int nex; char *p; int perblock; xfs_fileoff_t qbno; int qoff; char *s; dogrp = doprj = optind = 0; while ((c = getopt(argc, argv, "gpu")) != EOF) { switch (c) { case 'g': dogrp = 1; doprj = 0; break; case 'p': doprj = 1; dogrp = 0; break; case 'u': dogrp = doprj = 0; break; default: dbprintf(_("bad option for dquot command\n")); return 0; } } s = doprj ? _("project") : dogrp ? _("group") : _("user"); if (optind != argc - 1) { dbprintf(_("dquot command requires one %s id argument\n"), s); return 0; } ino = mp->m_sb.sb_uquotino; if (doprj) ino = mp->m_sb.sb_pquotino; else if (dogrp) ino = mp->m_sb.sb_gquotino; if (ino == 0 || ino == NULLFSINO) { dbprintf(_("no %s quota inode present\n"), s); return 0; } id = (xfs_dqid_t)strtol(argv[optind], &p, 0); if (*p != '\0') { dbprintf(_("bad %s id for dquot %s\n"), s, argv[optind]); return 0; } perblock = (int)(mp->m_sb.sb_blocksize / sizeof(xfs_dqblk_t)); qbno = (xfs_fileoff_t)id / perblock; qoff = (int)(id % perblock); push_cur(); set_cur_inode(ino); nex = 1; bmap(qbno, 1, XFS_DATA_FORK, &nex, &bm); pop_cur(); if (nex == 0) { dbprintf(_("no %s quota data for id %d\n"), s, id); return 0; } set_cur(&typtab[TYP_DQBLK], XFS_FSB_TO_DADDR(mp, bm.startblock), blkbb, DB_RING_IGN, NULL); iocur_top->dquot_buf = 1; off_cur(qoff * (int)sizeof(xfs_dqblk_t), sizeof(xfs_dqblk_t)); ring_add(); return 0; } void dquot_init(void) { add_command(&dquot_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/dquot.h0000644000000000000000000000156413063067170014371 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field disk_dquot_flds[]; extern const struct field dqblk_flds[]; extern const struct field dqblk_hfld[]; extern void dquot_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/echo.c0000644000000000000000000000223713063067170014144 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "echo.h" #include "output.h" static int echo_f(int argc, char **argv); static const cmdinfo_t echo_cmd = { "echo", NULL, echo_f, 0, -1, 0, N_("[args]..."), N_("echo arguments"), NULL }; /*ARGSUSED*/ static int echo_f( int argc, char **argv) { char *c; for (c = *(++argv); c; c = *(++argv)) dbprintf("%s ", c); dbprintf("\n"); return 0; } void echo_init(void) { add_command(&echo_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/echo.h0000644000000000000000000000136513063067170014152 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void echo_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/faddr.c0000644000000000000000000002051113063067170014301 0ustar /* * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "fprint.h" #include "faddr.h" #include "field.h" #include "inode.h" #include "io.h" #include "bit.h" #include "bmap.h" #include "output.h" #include "init.h" void fa_agblock( void *obj, int bit, typnm_t next) { xfs_agblock_t bno; if (cur_agno == NULLAGNUMBER) { dbprintf(_("no current allocation group, cannot set new addr\n")); return; } bno = (xfs_agblock_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == NULLAGBLOCK) { dbprintf(_("null block number, cannot set new addr\n")); return; } ASSERT(typtab[next].typnm == next); set_cur(&typtab[next], XFS_AGB_TO_DADDR(mp, cur_agno, bno), blkbb, DB_RING_ADD, NULL); } /*ARGSUSED*/ void fa_agino( void *obj, int bit, typnm_t next) { xfs_agino_t agino; if (cur_agno == NULLAGNUMBER) { dbprintf(_("no current allocation group, cannot set new addr\n")); return; } agino = (xfs_agino_t)getbitval(obj, bit, bitsz(agino), BVUNSIGNED); if (agino == NULLAGINO) { dbprintf(_("null inode number, cannot set new addr\n")); return; } set_cur_inode(XFS_AGINO_TO_INO(mp, cur_agno, agino)); } /*ARGSUSED*/ void fa_attrblock( void *obj, int bit, typnm_t next) { bmap_ext_t bm; __uint32_t bno; xfs_fsblock_t dfsbno; int nex; bno = (__uint32_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == 0) { dbprintf(_("null attribute block number, cannot set new addr\n")); return; } nex = 1; bmap(bno, 1, XFS_ATTR_FORK, &nex, &bm); if (nex == 0) { dbprintf(_("attribute block is unmapped\n")); return; } dfsbno = bm.startblock + (bno - bm.startoff); ASSERT(typtab[next].typnm == next); set_cur(&typtab[next], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), blkbb, DB_RING_ADD, NULL); } void fa_cfileoffa( void *obj, int bit, typnm_t next) { bmap_ext_t bm; xfs_fileoff_t bno; xfs_fsblock_t dfsbno; int nex; bno = (xfs_fileoff_t)getbitval(obj, bit, BMBT_STARTOFF_BITLEN, BVUNSIGNED); if (bno == NULLFILEOFF) { dbprintf(_("null block number, cannot set new addr\n")); return; } nex = 1; bmap(bno, 1, XFS_ATTR_FORK, &nex, &bm); if (nex == 0) { dbprintf(_("file block is unmapped\n")); return; } dfsbno = bm.startblock + (bno - bm.startoff); ASSERT(typtab[next].typnm == next); set_cur(&typtab[next], XFS_FSB_TO_DADDR(mp, dfsbno), blkbb, DB_RING_ADD, NULL); } void fa_cfileoffd( void *obj, int bit, typnm_t next) { bbmap_t bbmap; bmap_ext_t *bmp; xfs_fileoff_t bno; xfs_fsblock_t dfsbno; int nb; int nex; bno = (xfs_fileoff_t)getbitval(obj, bit, BMBT_STARTOFF_BITLEN, BVUNSIGNED); if (bno == NULLFILEOFF) { dbprintf(_("null block number, cannot set new addr\n")); return; } nex = nb = next == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1; bmp = malloc(nb * sizeof(*bmp)); bmap(bno, nb, XFS_DATA_FORK, &nex, bmp); if (nex == 0) { dbprintf(_("file block is unmapped\n")); free(bmp); return; } dfsbno = bmp->startblock + (bno - bmp->startoff); ASSERT(typtab[next].typnm == next); if (nex > 1) make_bbmap(&bbmap, nex, bmp); set_cur(&typtab[next], XFS_FSB_TO_DADDR(mp, dfsbno), nb * blkbb, DB_RING_ADD, nex > 1 ? &bbmap: NULL); free(bmp); } void fa_cfsblock( void *obj, int bit, typnm_t next) { xfs_fsblock_t bno; int nb; bno = (xfs_fsblock_t)getbitval(obj, bit, BMBT_STARTBLOCK_BITLEN, BVUNSIGNED); if (bno == NULLFSBLOCK) { dbprintf(_("null block number, cannot set new addr\n")); return; } nb = next == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1; ASSERT(typtab[next].typnm == next); set_cur(&typtab[next], XFS_FSB_TO_DADDR(mp, bno), nb * blkbb, DB_RING_ADD, NULL); } void fa_dfiloffa( void *obj, int bit, typnm_t next) { bmap_ext_t bm; xfs_fileoff_t bno; xfs_fsblock_t dfsbno; int nex; bno = (xfs_fileoff_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == NULLFILEOFF) { dbprintf(_("null block number, cannot set new addr\n")); return; } nex = 1; bmap(bno, 1, XFS_ATTR_FORK, &nex, &bm); if (nex == 0) { dbprintf(_("file block is unmapped\n")); return; } dfsbno = bm.startblock + (bno - bm.startoff); ASSERT(typtab[next].typnm == next); set_cur(&typtab[next], XFS_FSB_TO_DADDR(mp, dfsbno), blkbb, DB_RING_ADD, NULL); } void fa_dfiloffd( void *obj, int bit, typnm_t next) { bbmap_t bbmap; bmap_ext_t *bmp; xfs_fileoff_t bno; xfs_fsblock_t dfsbno; int nb; int nex; bno = (xfs_fileoff_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == NULLFILEOFF) { dbprintf(_("null block number, cannot set new addr\n")); return; } nex = nb = next == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1; bmp = malloc(nb * sizeof(*bmp)); bmap(bno, nb, XFS_DATA_FORK, &nex, bmp); if (nex == 0) { dbprintf(_("file block is unmapped\n")); free(bmp); return; } dfsbno = bmp->startblock + (bno - bmp->startoff); ASSERT(typtab[next].typnm == next); if (nex > 1) make_bbmap(&bbmap, nex, bmp); set_cur(&typtab[next], XFS_FSB_TO_DADDR(mp, dfsbno), nb * blkbb, DB_RING_ADD, nex > 1 ? &bbmap : NULL); free(bmp); } void fa_dfsbno( void *obj, int bit, typnm_t next) { xfs_fsblock_t bno; bno = (xfs_fsblock_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == NULLFSBLOCK) { dbprintf(_("null block number, cannot set new addr\n")); return; } ASSERT(typtab[next].typnm == next); set_cur(&typtab[next], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_ADD, NULL); } /*ARGSUSED*/ void fa_dirblock( void *obj, int bit, typnm_t next) { bbmap_t bbmap; bmap_ext_t *bmp; __uint32_t bno; xfs_fsblock_t dfsbno; int nex; bno = (__uint32_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == 0) { dbprintf(_("null directory block number, cannot set new addr\n")); return; } nex = mp->m_dir_geo->fsbcount; bmp = malloc(nex * sizeof(*bmp)); bmap(bno, mp->m_dir_geo->fsbcount, XFS_DATA_FORK, &nex, bmp); if (nex == 0) { dbprintf(_("directory block is unmapped\n")); free(bmp); return; } dfsbno = bmp->startblock + (bno - bmp->startoff); ASSERT(typtab[next].typnm == next); if (nex > 1) make_bbmap(&bbmap, nex, bmp); set_cur(&typtab[next], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), XFS_FSB_TO_BB(mp, mp->m_dir_geo->fsbcount), DB_RING_ADD, nex > 1 ? &bbmap : NULL); free(bmp); } void fa_drfsbno( void *obj, int bit, typnm_t next) { xfs_rfsblock_t bno; bno = (xfs_rfsblock_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == NULLRFSBLOCK) { dbprintf(_("null block number, cannot set new addr\n")); return; } ASSERT(typtab[next].typnm == next); set_cur(&typtab[next], (__int64_t)XFS_FSB_TO_BB(mp, bno), blkbb, DB_RING_ADD, NULL); } /*ARGSUSED*/ void fa_drtbno( void *obj, int bit, typnm_t next) { xfs_rtblock_t bno; bno = (xfs_rtblock_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == NULLRTBLOCK) { dbprintf(_("null block number, cannot set new addr\n")); return; } /* need set_cur to understand rt subvolume */ } /*ARGSUSED*/ void fa_ino( void *obj, int bit, typnm_t next) { xfs_ino_t ino; ASSERT(next == TYP_INODE); ino = (xfs_ino_t)getbitval(obj, bit, bitsz(ino), BVUNSIGNED); if (ino == NULLFSINO) { dbprintf(_("null inode number, cannot set new addr\n")); return; } set_cur_inode(ino); } void fa_ino4( void *obj, int bit, typnm_t next) { xfs_ino_t ino; ASSERT(next == TYP_INODE); ino = (xfs_ino_t)getbitval(obj, bit, bitsz(XFS_INO32_SIZE), BVUNSIGNED); if (ino == NULLFSINO) { dbprintf(_("null inode number, cannot set new addr\n")); return; } set_cur_inode(ino); } void fa_ino8( void *obj, int bit, typnm_t next) { xfs_ino_t ino; ASSERT(next == TYP_INODE); ino = (xfs_ino_t)getbitval(obj, bit, bitsz(XFS_INO64_SIZE), BVUNSIGNED); if (ino == NULLFSINO) { dbprintf(_("null inode number, cannot set new addr\n")); return; } set_cur_inode(ino); } xfsprogs-4.9.0+nmu1ubuntu2/db/faddr.h0000644000000000000000000000326513063067170014315 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ typedef void (*adfnc_t)(void *obj, int bit, typnm_t next); extern void fa_agblock(void *obj, int bit, typnm_t next); extern void fa_agino(void *obj, int bit, typnm_t next); extern void fa_attrblock(void *obj, int bit, typnm_t next); extern void fa_cfileoffd(void *obj, int bit, typnm_t next); extern void fa_cfsblock(void *obj, int bit, typnm_t next); extern void fa_dfiloffd(void *obj, int bit, typnm_t next); extern void fa_dfsbno(void *obj, int bit, typnm_t next); extern void fa_dinode_union(void *obj, int bit, typnm_t next); extern void fa_dirblock(void *obj, int bit, typnm_t next); extern void fa_drfsbno(void *obj, int bit, typnm_t next); extern void fa_drtbno(void *obj, int bit, typnm_t next); extern void fa_ino(void *obj, int bit, typnm_t next); extern void fa_cfileoffa(void *obj, int bit, typnm_t next); extern void fa_dfiloffa(void *obj, int bit, typnm_t next); extern void fa_ino4(void *obj, int bit, typnm_t next); extern void fa_ino8(void *obj, int bit, typnm_t next); xfsprogs-4.9.0+nmu1ubuntu2/db/field.c0000644000000000000000000004741513063067170014320 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "inode.h" #include "btblock.h" #include "bmroot.h" #include "bit.h" #include "agf.h" #include "agfl.h" #include "agi.h" #include "sb.h" #include "attr.h" #include "attrshort.h" #include "dquot.h" #include "dir2.h" #include "dir2sf.h" #include "symlink.h" const ftattr_t ftattrtab[] = { { FLDT_AEXTNUM, "aextnum", fp_num, "%d", SI(bitsz(xfs_aextnum_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_AGBLOCK, "agblock", fp_num, "%u", SI(bitsz(xfs_agblock_t)), FTARG_DONULL, fa_agblock, NULL }, { FLDT_AGBLOCKNZ, "agblocknz", fp_num, "%u", SI(bitsz(xfs_agblock_t)), FTARG_SKIPZERO|FTARG_DONULL, fa_agblock, NULL }, { FLDT_AGF, "agf", NULL, (char *)agf_flds, agf_size, FTARG_SIZE, NULL, agf_flds }, { FLDT_AGFL, "agfl", NULL, (char *)agfl_flds, agfl_size, FTARG_SIZE, NULL, agfl_flds }, { FLDT_AGFL_CRC, "agfl", NULL, (char *)agfl_crc_flds, agfl_size, FTARG_SIZE, NULL, agfl_crc_flds }, { FLDT_AGI, "agi", NULL, (char *)agi_flds, agi_size, FTARG_SIZE, NULL, agi_flds }, { FLDT_AGINO, "agino", fp_num, "%u", SI(bitsz(xfs_agino_t)), FTARG_DONULL, fa_agino, NULL }, { FLDT_AGINONN, "aginonn", fp_num, "%u", SI(bitsz(xfs_agino_t)), FTARG_SKIPNULL, fa_agino, NULL }, { FLDT_AGNUMBER, "agnumber", fp_num, "%u", SI(bitsz(xfs_agnumber_t)), FTARG_DONULL, NULL, NULL }, /* attr fields */ { FLDT_ATTR, "attr", NULL, (char *)attr_flds, attr_size, FTARG_SIZE, NULL, attr_flds }, { FLDT_ATTR_BLKINFO, "attr_blkinfo", NULL, (char *)attr_blkinfo_flds, SI(bitsz(struct xfs_da_blkinfo)), 0, NULL, attr_blkinfo_flds }, { FLDT_ATTR_LEAF_ENTRY, "attr_leaf_entry", fp_sarray, (char *)attr_leaf_entry_flds, SI(bitsz(struct xfs_attr_leaf_entry)), 0, NULL, attr_leaf_entry_flds }, { FLDT_ATTR_LEAF_HDR, "attr_leaf_hdr", NULL, (char *)attr_leaf_hdr_flds, SI(bitsz(struct xfs_attr_leaf_hdr)), 0, NULL, attr_leaf_hdr_flds }, { FLDT_ATTR_LEAF_MAP, "attr_leaf_map", fp_sarray, (char *)attr_leaf_map_flds, SI(bitsz(struct xfs_attr_leaf_map)), 0, NULL, attr_leaf_map_flds }, { FLDT_ATTR_LEAF_NAME, "attr_leaf_name", NULL, (char *)attr_leaf_name_flds, attr_leaf_name_size, FTARG_SIZE, NULL, attr_leaf_name_flds }, { FLDT_ATTR_NODE_ENTRY, "attr_node_entry", fp_sarray, (char *)attr_node_entry_flds, SI(bitsz(struct xfs_da_node_entry)), 0, NULL, attr_node_entry_flds }, { FLDT_ATTR_NODE_HDR, "attr_node_hdr", NULL, (char *)attr_node_hdr_flds, SI(bitsz(struct xfs_da_node_hdr)), 0, NULL, attr_node_hdr_flds }, { FLDT_ATTR_SF_ENTRY, "attr_sf_entry", NULL, (char *)attr_sf_entry_flds, attr_sf_entry_size, FTARG_SIZE, NULL, attr_sf_entry_flds }, { FLDT_ATTR_SF_HDR, "attr_sf_hdr", NULL, (char *)attr_sf_hdr_flds, SI(bitsz(struct xfs_attr_sf_hdr)), 0, NULL, attr_sf_hdr_flds }, { FLDT_ATTRBLOCK, "attrblock", fp_num, "%u", SI(bitsz(__uint32_t)), 0, fa_attrblock, NULL }, { FLDT_ATTRSHORT, "attrshort", NULL, (char *)attr_shortform_flds, attrshort_size, FTARG_SIZE, NULL, attr_shortform_flds }, /* attr3 specific fields */ { FLDT_ATTR3, "attr3", NULL, (char *)attr3_flds, attr_size, FTARG_SIZE, NULL, attr3_flds }, { FLDT_ATTR3_LEAF_HDR, "attr3_leaf_hdr", NULL, (char *)attr3_leaf_hdr_flds, SI(bitsz(struct xfs_attr3_leaf_hdr)), 0, NULL, attr3_leaf_hdr_flds }, { FLDT_ATTR3_NODE_HDR, "attr3_node_hdr", NULL, (char *)da3_node_hdr_flds, SI(bitsz(struct xfs_da3_node_hdr)), 0, NULL, da3_node_hdr_flds }, { FLDT_BMAPBTA, "bmapbta", NULL, (char *)bmapbta_flds, btblock_size, FTARG_SIZE, NULL, bmapbta_flds }, { FLDT_BMAPBTA_CRC, "bmapbta", NULL, (char *)bmapbta_crc_flds, btblock_size, FTARG_SIZE, NULL, bmapbta_crc_flds }, { FLDT_BMAPBTAKEY, "bmapbtakey", fp_sarray, (char *)bmapbta_key_flds, SI(bitsz(xfs_bmbt_key_t)), 0, NULL, bmapbta_key_flds }, { FLDT_BMAPBTAPTR, "bmapbtaptr", fp_num, "%llu", SI(bitsz(xfs_bmbt_ptr_t)), 0, fa_dfsbno, NULL }, { FLDT_BMAPBTAREC, "bmapbtarec", fp_sarray, (char *)bmapbta_rec_flds, SI(bitsz(xfs_bmbt_rec_t)), 0, NULL, bmapbta_rec_flds }, { FLDT_BMAPBTD, "bmapbtd", NULL, (char *)bmapbtd_flds, btblock_size, FTARG_SIZE, NULL, bmapbtd_flds }, { FLDT_BMAPBTD_CRC, "bmapbtd", NULL, (char *)bmapbtd_crc_flds, btblock_size, FTARG_SIZE, NULL, bmapbtd_crc_flds }, { FLDT_BMAPBTDKEY, "bmapbtdkey", fp_sarray, (char *)bmapbtd_key_flds, SI(bitsz(xfs_bmbt_key_t)), 0, NULL, bmapbtd_key_flds }, { FLDT_BMAPBTDPTR, "bmapbtdptr", fp_num, "%llu", SI(bitsz(xfs_bmbt_ptr_t)), 0, fa_dfsbno, NULL }, { FLDT_BMAPBTDREC, "bmapbtdrec", fp_sarray, (char *)bmapbtd_rec_flds, SI(bitsz(xfs_bmbt_rec_t)), 0, NULL, bmapbtd_rec_flds }, { FLDT_BMROOTA, "bmroota", NULL, (char *)bmroota_flds, bmroota_size, FTARG_SIZE, NULL, bmroota_flds }, { FLDT_BMROOTAKEY, "bmrootakey", fp_sarray, (char *)bmroota_key_flds, SI(bitsz(xfs_bmdr_key_t)), 0, NULL, bmroota_key_flds }, { FLDT_BMROOTAPTR, "bmrootaptr", fp_num, "%llu", SI(bitsz(xfs_bmdr_ptr_t)), 0, fa_dfsbno, NULL }, { FLDT_BMROOTD, "bmrootd", NULL, (char *)bmrootd_flds, bmrootd_size, FTARG_SIZE, NULL, bmrootd_flds }, { FLDT_BMROOTDKEY, "bmrootdkey", fp_sarray, (char *)bmrootd_key_flds, SI(bitsz(xfs_bmdr_key_t)), 0, NULL, bmrootd_key_flds }, { FLDT_BMROOTDPTR, "bmrootdptr", fp_num, "%llu", SI(bitsz(xfs_bmdr_ptr_t)), 0, fa_dfsbno, NULL }, { FLDT_BNOBT, "bnobt", NULL, (char *)bnobt_flds, btblock_size, FTARG_SIZE, NULL, bnobt_flds }, { FLDT_BNOBT_CRC, "bnobt", NULL, (char *)bnobt_crc_flds, btblock_size, FTARG_SIZE, NULL, bnobt_crc_flds }, { FLDT_BNOBTKEY, "bnobtkey", fp_sarray, (char *)bnobt_key_flds, SI(bitsz(xfs_alloc_key_t)), 0, NULL, bnobt_key_flds }, { FLDT_BNOBTPTR, "bnobtptr", fp_num, "%u", SI(bitsz(xfs_alloc_ptr_t)), 0, fa_agblock, NULL }, { FLDT_BNOBTREC, "bnobtrec", fp_sarray, (char *)bnobt_rec_flds, SI(bitsz(xfs_alloc_rec_t)), 0, NULL, bnobt_rec_flds }, { FLDT_CEXTFLG, "cextflag", fp_num, "%u", SI(BMBT_EXNTFLAG_BITLEN), 0, NULL, NULL }, { FLDT_CEXTLEN, "cextlen", fp_num, "%u", SI(BMBT_BLOCKCOUNT_BITLEN), 0, NULL, NULL }, { FLDT_CFILEOFFA, "cfileoffa", fp_num, "%llu", SI(BMBT_STARTOFF_BITLEN), 0, fa_cfileoffa, NULL }, { FLDT_CFILEOFFD, "cfileoffd", fp_num, "%llu", SI(BMBT_STARTOFF_BITLEN), 0, fa_cfileoffd, NULL }, { FLDT_CFSBLOCK, "cfsblock", fp_num, "%llu", SI(BMBT_STARTBLOCK_BITLEN), 0, fa_cfsblock, NULL }, { FLDT_CHARNS, "charns", fp_charns, NULL, SI(bitsz(char)), 0, NULL, NULL }, { FLDT_CHARS, "chars", fp_num, "%c", SI(bitsz(char)), 0, NULL, NULL }, { FLDT_REXTLEN, "rextlen", fp_num, "%u", SI(RMAPBT_BLOCKCOUNT_BITLEN), 0, NULL, NULL }, { FLDT_RFILEOFFD, "rfileoffd", fp_num, "%llu", SI(RMAPBT_OFFSET_BITLEN), 0, NULL, NULL }, { FLDT_REXTFLG, "rextflag", fp_num, "%u", SI(RMAPBT_EXNTFLAG_BITLEN), 0, NULL, NULL }, { FLDT_RATTRFORKFLG, "rattrforkflag", fp_num, "%u", SI(RMAPBT_ATTRFLAG_BITLEN), 0, NULL, NULL }, { FLDT_RBMBTFLG, "rbmbtflag", fp_num, "%u", SI(RMAPBT_BMBTFLAG_BITLEN), 0, NULL, NULL }, { FLDT_CAGBLOCK, "cagblock", fp_num, "%u", SI(REFCNTBT_AGBLOCK_BITLEN), FTARG_DONULL, fa_agblock, NULL }, { FLDT_CCOWFLG, "ccowflag", fp_num, "%u", SI(REFCNTBT_COWFLAG_BITLEN), 0, NULL, NULL }, { FLDT_CNTBT, "cntbt", NULL, (char *)cntbt_flds, btblock_size, FTARG_SIZE, NULL, cntbt_flds }, { FLDT_CNTBT_CRC, "cntbt", NULL, (char *)cntbt_crc_flds, btblock_size, FTARG_SIZE, NULL, cntbt_crc_flds }, { FLDT_CNTBTKEY, "cntbtkey", fp_sarray, (char *)cntbt_key_flds, SI(bitsz(xfs_alloc_key_t)), 0, NULL, cntbt_key_flds }, { FLDT_CNTBTPTR, "cntbtptr", fp_num, "%u", SI(bitsz(xfs_alloc_ptr_t)), 0, fa_agblock, NULL }, { FLDT_CNTBTREC, "cntbtrec", fp_sarray, (char *)cntbt_rec_flds, SI(bitsz(xfs_alloc_rec_t)), 0, NULL, cntbt_rec_flds }, { FLDT_RMAPBT_CRC, "rmapbt", NULL, (char *)rmapbt_crc_flds, btblock_size, FTARG_SIZE, NULL, rmapbt_crc_flds }, { FLDT_RMAPBTKEY, "rmapbtkey", fp_sarray, (char *)rmapbt_key_flds, SI(bitize(2 * sizeof(struct xfs_rmap_key))), 0, NULL, rmapbt_key_flds }, { FLDT_RMAPBTPTR, "rmapbtptr", fp_num, "%u", SI(bitsz(xfs_rmap_ptr_t)), 0, fa_agblock, NULL }, { FLDT_RMAPBTREC, "rmapbtrec", fp_sarray, (char *)rmapbt_rec_flds, SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rmapbt_rec_flds }, { FLDT_REFCBT_CRC, "refcntbt", NULL, (char *)refcbt_crc_flds, btblock_size, FTARG_SIZE, NULL, refcbt_crc_flds }, { FLDT_REFCBTKEY, "refcntbtkey", fp_sarray, (char *)refcbt_key_flds, SI(bitsz(struct xfs_refcount_key)), 0, NULL, refcbt_key_flds }, { FLDT_REFCBTPTR, "refcntbtptr", fp_num, "%u", SI(bitsz(xfs_refcount_ptr_t)), 0, fa_agblock, NULL }, { FLDT_REFCBTREC, "refcntbtrec", fp_sarray, (char *)refcbt_rec_flds, SI(bitsz(struct xfs_refcount_rec)), 0, NULL, refcbt_rec_flds }, /* CRC field */ { FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(__uint32_t)), 0, NULL, NULL }, { FLDT_DEV, "dev", fp_num, "%#x", SI(bitsz(xfs_dev_t)), 0, NULL, NULL }, { FLDT_DFILOFFA, "dfiloffa", fp_num, "%llu", SI(bitsz(xfs_fileoff_t)), 0, fa_dfiloffa, NULL }, { FLDT_DFILOFFD, "dfiloffd", fp_num, "%llu", SI(bitsz(xfs_fileoff_t)), 0, fa_dfiloffd, NULL }, { FLDT_DFSBNO, "dfsbno", fp_num, "%llu", SI(bitsz(xfs_fsblock_t)), FTARG_DONULL, fa_dfsbno, NULL }, { FLDT_DINODE_A, "dinode_a", NULL, (char *)inode_a_flds, inode_a_size, FTARG_SIZE|FTARG_OKEMPTY, NULL, inode_a_flds }, { FLDT_DINODE_CORE, "dinode_core", NULL, (char *)inode_core_flds, SI(bitsz(xfs_dinode_t)), 0, NULL, inode_core_flds }, { FLDT_DINODE_FMT, "dinode_fmt", fp_dinode_fmt, NULL, SI(bitsz(__int8_t)), 0, NULL, NULL }, { FLDT_DINODE_U, "dinode_u", NULL, (char *)inode_u_flds, inode_u_size, FTARG_SIZE|FTARG_OKEMPTY, NULL, inode_u_flds }, { FLDT_DINODE_V3, "dinode_v3", NULL, (char *)inode_v3_flds, SI(bitsz(xfs_dinode_t)), 0, NULL, inode_v3_flds }, /* dir v2 fields */ { FLDT_DIR2, "dir2", NULL, (char *)dir2_flds, dir2_size, FTARG_SIZE, NULL, dir2_flds }, { FLDT_DIR2_BLOCK_TAIL, "dir2_block_tail", NULL, (char *)dir2_block_tail_flds, SI(bitsz(xfs_dir2_block_tail_t)), 0, NULL, dir2_block_tail_flds }, { FLDT_DIR2_DATA_FREE, "dir2_data_free", NULL, (char *)dir2_data_free_flds, SI(bitsz(xfs_dir2_data_free_t)), 0, NULL, dir2_data_free_flds }, { FLDT_DIR2_DATA_HDR, "dir2_data_hdr", NULL, (char *)dir2_data_hdr_flds, SI(bitsz(xfs_dir2_data_hdr_t)), 0, NULL, dir2_data_hdr_flds }, { FLDT_DIR2_DATA_OFF, "dir2_data_off", fp_num, "%#x", SI(bitsz(xfs_dir2_data_off_t)), 0, NULL, NULL }, { FLDT_DIR2_DATA_OFFNZ, "dir2_data_offnz", fp_num, "%#x", SI(bitsz(xfs_dir2_data_off_t)), FTARG_SKIPZERO, NULL, NULL }, { FLDT_DIR2_DATA_UNION, "dir2_data_union", NULL, (char *)dir2_data_union_flds, dir2_data_union_size, FTARG_SIZE, NULL, dir2_data_union_flds }, { FLDT_DIR2_FREE_HDR, "dir2_free_hdr", NULL, (char *)dir2_free_hdr_flds, SI(bitsz(xfs_dir2_free_hdr_t)), 0, NULL, dir2_free_hdr_flds }, { FLDT_DIR2_INO4, "dir2_ino4", fp_num, "%u", SI(bitize(XFS_INO32_SIZE)), 0, fa_ino4, NULL }, { FLDT_DIR2_INO8, "dir2_ino8", fp_num, "%llu", SI(bitize(XFS_INO64_SIZE)), 0, fa_ino8, NULL }, { FLDT_DIR2_INOU, "dir2_inou", NULL, (char *)dir2_inou_flds, dir2_inou_size, FTARG_SIZE, NULL, dir2_inou_flds }, { FLDT_DIR2_LEAF_ENTRY, "dir2_leaf_entry", NULL, (char *)dir2_leaf_entry_flds, SI(bitsz(xfs_dir2_leaf_entry_t)), 0, NULL, dir2_leaf_entry_flds }, { FLDT_DIR2_LEAF_HDR, "dir2_leaf_hdr", NULL, (char *)dir2_leaf_hdr_flds, SI(bitsz(xfs_dir2_leaf_hdr_t)), 0, NULL, dir2_leaf_hdr_flds }, { FLDT_DIR2_LEAF_TAIL, "dir2_leaf_tail", NULL, (char *)dir2_leaf_tail_flds, SI(bitsz(xfs_dir2_leaf_tail_t)), 0, NULL, dir2_leaf_tail_flds }, { FLDT_DIR2_SF_ENTRY, "dir2_sf_entry", NULL, (char *)dir2_sf_entry_flds, dir2_sf_entry_size, FTARG_SIZE, NULL, dir2_sf_entry_flds }, { FLDT_DIR2_SF_HDR, "dir2_sf_hdr", NULL, (char *)dir2_sf_hdr_flds, dir2_sf_hdr_size, FTARG_SIZE, NULL, dir2_sf_hdr_flds }, { FLDT_DIR2_SF_OFF, "dir2_sf_off", fp_num, "%#x", SI(bitize(2*sizeof(__u8))), 0, NULL, NULL }, { FLDT_DIR2SF, "dir2sf", NULL, (char *)dir2sf_flds, dir2sf_size, FTARG_SIZE, NULL, dir2sf_flds }, /* dir v3 fields */ { FLDT_DIR3, "dir3", NULL, (char *)dir3_flds, dir2_size, FTARG_SIZE, NULL, dir3_flds }, { FLDT_DIR3_BLKHDR, "dir3_blk_hdr", NULL, (char *)dir3_blkhdr_flds, SI(bitsz(struct xfs_dir3_blk_hdr)), 0, NULL, dir3_blkhdr_flds }, { FLDT_DIR3_DATA_HDR, "dir3_data_hdr", NULL, (char *)dir3_data_hdr_flds, SI(bitsz(struct xfs_dir3_data_hdr)), 0, NULL, dir3_data_hdr_flds }, { FLDT_DIR3_FREE_HDR, "dir3_free_hdr", NULL, (char *)dir3_free_hdr_flds, SI(bitsz(struct xfs_dir3_free_hdr)), 0, NULL, dir3_free_hdr_flds }, { FLDT_DIR3_LEAF_HDR, "dir3_leaf_hdr", NULL, (char *)dir3_leaf_hdr_flds, SI(bitsz(struct xfs_dir3_leaf_hdr)), 0, NULL, dir3_leaf_hdr_flds }, { FLDT_DIR3_DATA_UNION, "dir3_data_union", NULL, (char *)dir3_data_union_flds, dir2_data_union_size, FTARG_SIZE, NULL, dir3_data_union_flds }, { FLDT_DIR3_SF_ENTRY, "dir3_sf_entry", NULL, (char *)dir3_sf_entry_flds, dir2_sf_entry_size, FTARG_SIZE, NULL, dir3_sf_entry_flds }, { FLDT_DIR3SF, "dir3sf", NULL, (char *)dir3sf_flds, dir2sf_size, FTARG_SIZE, NULL, dir3sf_flds }, /* dir v2/3 node fields */ { FLDT_DA_BLKINFO, "dir_blkinfo", NULL, (char *)da_blkinfo_flds, SI(bitsz(struct xfs_da_blkinfo)), 0, NULL, da_blkinfo_flds }, { FLDT_DA_NODE_ENTRY, "dir_node_entry", fp_sarray, (char *)da_node_entry_flds, SI(bitsz(struct xfs_da_node_entry)), 0, NULL, da_node_entry_flds }, { FLDT_DA_NODE_HDR, "dir_node_hdr", NULL, (char *)da_node_hdr_flds, SI(bitsz(struct xfs_da_node_hdr)), 0, NULL, da_node_hdr_flds }, { FLDT_DA3_BLKINFO, "dir_blkinfo", NULL, (char *)da3_blkinfo_flds, SI(bitsz(struct xfs_da3_blkinfo)), 0, NULL, da3_blkinfo_flds }, { FLDT_DA3_NODE_HDR, "dir_node_hdr", NULL, (char *)da3_node_hdr_flds, SI(bitsz(struct xfs_da3_node_hdr)), 0, NULL, da3_node_hdr_flds }, { FLDT_DIRBLOCK, "dirblock", fp_num, "%u", SI(bitsz(__uint32_t)), 0, fa_dirblock, NULL }, { FLDT_DISK_DQUOT, "disk_dquot", NULL, (char *)disk_dquot_flds, SI(bitsz(xfs_disk_dquot_t)), 0, NULL, disk_dquot_flds }, { FLDT_DQBLK, "dqblk", NULL, (char *)dqblk_flds, SI(bitsz(xfs_dqblk_t)), 0, NULL, dqblk_flds }, { FLDT_DQID, "dqid", fp_num, "%d", SI(bitsz(xfs_dqid_t)), 0, NULL, NULL }, { FLDT_DRFSBNO, "drfsbno", fp_num, "%llu", SI(bitsz(xfs_rfsblock_t)), FTARG_DONULL, fa_drfsbno, NULL }, { FLDT_DRTBNO, "drtbno", fp_num, "%llu", SI(bitsz(xfs_rtblock_t)), FTARG_DONULL, fa_drtbno, NULL }, { FLDT_EXTLEN, "extlen", fp_num, "%u", SI(bitsz(xfs_extlen_t)), 0, NULL, NULL }, { FLDT_EXTNUM, "extnum", fp_num, "%d", SI(bitsz(xfs_extnum_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_FSIZE, "fsize", fp_num, "%lld", SI(bitsz(xfs_fsize_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_INO, "ino", fp_num, "%llu", SI(bitsz(xfs_ino_t)), FTARG_DONULL, fa_ino, NULL }, { FLDT_INOBT, "inobt", NULL, (char *)inobt_flds, btblock_size, FTARG_SIZE, NULL, inobt_flds }, { FLDT_INOBT_CRC, "inobt", NULL, (char *)inobt_crc_flds, btblock_size, FTARG_SIZE, NULL, inobt_crc_flds }, { FLDT_INOBT_SPCRC, "inobt", NULL, (char *)inobt_spcrc_flds, btblock_size, FTARG_SIZE, NULL, inobt_spcrc_flds }, { FLDT_INOBTKEY, "inobtkey", fp_sarray, (char *)inobt_key_flds, SI(bitsz(xfs_inobt_key_t)), 0, NULL, inobt_key_flds }, { FLDT_INOBTPTR, "inobtptr", fp_num, "%u", SI(bitsz(xfs_inobt_ptr_t)), 0, fa_agblock, NULL }, { FLDT_INOBTREC, "inobtrec", fp_sarray, (char *)inobt_rec_flds, SI(bitsz(xfs_inobt_rec_t)), 0, NULL, inobt_rec_flds }, { FLDT_INOBTSPREC, "inobtsprec", fp_sarray, (char *) inobt_sprec_flds, SI(bitsz(xfs_inobt_rec_t)), 0, NULL, inobt_sprec_flds }, { FLDT_INODE, "inode", NULL, (char *)inode_flds, inode_size, FTARG_SIZE, NULL, inode_flds }, { FLDT_INODE_CRC, "inode", NULL, (char *)inode_crc_flds, inode_size, FTARG_SIZE, NULL, inode_crc_flds }, { FLDT_INOFREE, "inofree", fp_num, "%#llx", SI(bitsz(xfs_inofree_t)), 0, NULL, NULL }, { FLDT_INT16D, "int16d", fp_num, "%d", SI(bitsz(__int16_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_INT32D, "int32d", fp_num, "%d", SI(bitsz(__int32_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_INT64D, "int64d", fp_num, "%lld", SI(bitsz(__int64_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_INT8D, "int8d", fp_num, "%d", SI(bitsz(__int8_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_NSEC, "nsec", fp_num, "%09d", SI(bitsz(__int32_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_QCNT, "qcnt", fp_num, "%llu", SI(bitsz(xfs_qcnt_t)), 0, NULL, NULL }, { FLDT_QWARNCNT, "qwarncnt", fp_num, "%u", SI(bitsz(xfs_qwarncnt_t)), 0, NULL, NULL }, { FLDT_SB, "sb", NULL, (char *)sb_flds, sb_size, FTARG_SIZE, NULL, sb_flds }, /* CRC enabled symlink */ { FLDT_SYMLINK_CRC, "symlink", NULL, (char *)symlink_crc_flds, symlink_size, FTARG_SIZE, NULL, symlink_crc_flds }, { FLDT_TIME, "time", fp_time, NULL, SI(bitsz(__int32_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds, SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds }, { FLDT_UINT1, "uint1", fp_num, "%u", SI(1), 0, NULL, NULL }, { FLDT_UINT16D, "uint16d", fp_num, "%u", SI(bitsz(__uint16_t)), 0, NULL, NULL }, { FLDT_UINT16O, "uint16o", fp_num, "%#o", SI(bitsz(__uint16_t)), 0, NULL, NULL }, { FLDT_UINT16X, "uint16x", fp_num, "%#x", SI(bitsz(__uint16_t)), 0, NULL, NULL }, { FLDT_UINT32D, "uint32d", fp_num, "%u", SI(bitsz(__uint32_t)), 0, NULL, NULL }, { FLDT_UINT32O, "uint32o", fp_num, "%#o", SI(bitsz(__uint32_t)), 0, NULL, NULL }, { FLDT_UINT32X, "uint32x", fp_num, "%#x", SI(bitsz(__uint32_t)), 0, NULL, NULL }, { FLDT_UINT64D, "uint64d", fp_num, "%llu", SI(bitsz(__uint64_t)), 0, NULL, NULL }, { FLDT_UINT64O, "uint64o", fp_num, "%#llo", SI(bitsz(__uint64_t)), 0, NULL, NULL }, { FLDT_UINT64X, "uint64x", fp_num, "%#llx", SI(bitsz(__uint64_t)), 0, NULL, NULL }, { FLDT_UINT8D, "uint8d", fp_num, "%u", SI(bitsz(__uint8_t)), 0, NULL, NULL }, { FLDT_UINT8O, "uint8o", fp_num, "%#o", SI(bitsz(__uint8_t)), 0, NULL, NULL }, { FLDT_UINT8X, "uint8x", fp_num, "%#x", SI(bitsz(__uint8_t)), 0, NULL, NULL }, { FLDT_UUID, "uuid", fp_uuid, NULL, SI(bitsz(uuid_t)), 0, NULL, NULL }, { FLDT_ZZZ, NULL } }; int bitoffset( const field_t *f, void *obj, int startoff, int idx) { if (!(f->flags & FLD_OFFSET)) { if (f->flags & FLD_ARRAY) { int abase; #ifdef DEBUG const ftattr_t *fa = &ftattrtab[f->ftyp]; #endif abase = (f->flags & FLD_ABASE1) != 0; ASSERT(fa->ftyp == f->ftyp); ASSERT((fa->arg & FTARG_SIZE) == 0); return (int)(intptr_t)f->offset + (idx - abase) * fsize(f, obj, startoff, idx); } else return (int)(intptr_t)f->offset; } else return (*f->offset)(obj, startoff, idx); } int fcount( const field_t *f, void *obj, int startoff) { if (!(f->flags & FLD_COUNT)) return (int)(intptr_t)f->count; else return (*f->count)(obj, startoff); } const field_t * findfield( char *name, const field_t *fields, void *obj, int startoff) { const field_t *f; /* we only match if this field name matches and has a non-zero count */ for (f = fields; f->name; f++) if (strcmp(f->name, name) == 0 && fcount(f, obj, startoff)) return f; return NULL; } int fsize( const field_t *f, void *obj, int startoff, int idx) { const ftattr_t *fa; fa = &ftattrtab[f->ftyp]; ASSERT(fa->ftyp == f->ftyp); if (!(fa->arg & FTARG_SIZE)) return (int)(intptr_t)fa->size; else return (*fa->size)(obj, startoff, idx); } xfsprogs-4.9.0+nmu1ubuntu2/db/field.h0000644000000000000000000001227713063067170014323 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ typedef enum fldt { FLDT_AEXTNUM, FLDT_AGBLOCK, FLDT_AGBLOCKNZ, FLDT_AGF, FLDT_AGFL, FLDT_AGFL_CRC, FLDT_AGI, FLDT_AGINO, FLDT_AGINONN, FLDT_AGNUMBER, /* attr fields */ FLDT_ATTR, FLDT_ATTR_BLKINFO, FLDT_ATTR_LEAF_ENTRY, FLDT_ATTR_LEAF_HDR, FLDT_ATTR_LEAF_MAP, FLDT_ATTR_LEAF_NAME, FLDT_ATTR_NODE_ENTRY, FLDT_ATTR_NODE_HDR, FLDT_ATTR_SF_ENTRY, FLDT_ATTR_SF_HDR, FLDT_ATTRBLOCK, FLDT_ATTRSHORT, /* attr 3 specific fields */ FLDT_ATTR3, FLDT_ATTR3_LEAF_HDR, FLDT_ATTR3_NODE_HDR, FLDT_BMAPBTA, FLDT_BMAPBTA_CRC, FLDT_BMAPBTAKEY, FLDT_BMAPBTAPTR, FLDT_BMAPBTAREC, FLDT_BMAPBTD, FLDT_BMAPBTD_CRC, FLDT_BMAPBTDKEY, FLDT_BMAPBTDPTR, FLDT_BMAPBTDREC, FLDT_BMROOTA, FLDT_BMROOTAKEY, FLDT_BMROOTAPTR, FLDT_BMROOTD, FLDT_BMROOTDKEY, FLDT_BMROOTDPTR, FLDT_BNOBT, FLDT_BNOBT_CRC, FLDT_BNOBTKEY, FLDT_BNOBTPTR, FLDT_BNOBTREC, FLDT_CEXTFLG, FLDT_CEXTLEN, FLDT_CFILEOFFA, FLDT_CFILEOFFD, FLDT_CFSBLOCK, FLDT_CHARNS, FLDT_CHARS, FLDT_REXTLEN, FLDT_RFILEOFFD, FLDT_REXTFLG, FLDT_RATTRFORKFLG, FLDT_RBMBTFLG, FLDT_CAGBLOCK, FLDT_CCOWFLG, FLDT_CNTBT, FLDT_CNTBT_CRC, FLDT_CNTBTKEY, FLDT_CNTBTPTR, FLDT_CNTBTREC, FLDT_RMAPBT_CRC, FLDT_RMAPBTKEY, FLDT_RMAPBTPTR, FLDT_RMAPBTREC, FLDT_REFCBT_CRC, FLDT_REFCBTKEY, FLDT_REFCBTPTR, FLDT_REFCBTREC, /* CRC field type */ FLDT_CRC, FLDT_DEV, FLDT_DFILOFFA, FLDT_DFILOFFD, FLDT_DFSBNO, FLDT_DINODE_A, FLDT_DINODE_CORE, FLDT_DINODE_FMT, FLDT_DINODE_U, FLDT_DINODE_V3, /* dir v2 fields */ FLDT_DIR2, FLDT_DIR2_BLOCK_TAIL, FLDT_DIR2_DATA_FREE, FLDT_DIR2_DATA_HDR, FLDT_DIR2_DATA_OFF, FLDT_DIR2_DATA_OFFNZ, FLDT_DIR2_DATA_UNION, FLDT_DIR2_FREE_HDR, FLDT_DIR2_INO4, FLDT_DIR2_INO8, FLDT_DIR2_INOU, FLDT_DIR2_LEAF_ENTRY, FLDT_DIR2_LEAF_HDR, FLDT_DIR2_LEAF_TAIL, FLDT_DIR2_SF_ENTRY, FLDT_DIR2_SF_HDR, FLDT_DIR2_SF_OFF, FLDT_DIR2SF, /* dir v3 fields */ FLDT_DIR3, FLDT_DIR3_BLKHDR, FLDT_DIR3_DATA_HDR, FLDT_DIR3_FREE_HDR, FLDT_DIR3_LEAF_HDR, FLDT_DIR3_DATA_UNION, FLDT_DIR3_SF_ENTRY, FLDT_DIR3SF, /* dir v2/3 node fields */ FLDT_DA_BLKINFO, FLDT_DA_NODE_ENTRY, FLDT_DA_NODE_HDR, FLDT_DA3_BLKINFO, FLDT_DA3_NODE_HDR, FLDT_DIRBLOCK, FLDT_DISK_DQUOT, FLDT_DQBLK, FLDT_DQID, FLDT_DRFSBNO, FLDT_DRTBNO, FLDT_EXTLEN, FLDT_EXTNUM, FLDT_FSIZE, FLDT_INO, FLDT_INOBT, FLDT_INOBT_CRC, FLDT_INOBT_SPCRC, FLDT_INOBTKEY, FLDT_INOBTPTR, FLDT_INOBTREC, FLDT_INOBTSPREC, FLDT_INODE, FLDT_INODE_CRC, FLDT_INOFREE, FLDT_INT16D, FLDT_INT32D, FLDT_INT64D, FLDT_INT8D, FLDT_NSEC, FLDT_QCNT, FLDT_QWARNCNT, FLDT_SB, /* CRC enabled symlink */ FLDT_SYMLINK_CRC, FLDT_TIME, FLDT_TIMESTAMP, FLDT_UINT1, FLDT_UINT16D, FLDT_UINT16O, FLDT_UINT16X, FLDT_UINT32D, FLDT_UINT32O, FLDT_UINT32X, FLDT_UINT64D, FLDT_UINT64O, FLDT_UINT64X, FLDT_UINT8D, FLDT_UINT8O, FLDT_UINT8X, FLDT_UUID, FLDT_ZZZ /* mark last entry */ } fldt_t; typedef int (*offset_fnc_t)(void *obj, int startoff, int idx); #define OI(o) ((offset_fnc_t)(intptr_t)(o)) typedef int (*count_fnc_t)(void *obj, int startoff); #define CI(c) ((count_fnc_t)(intptr_t)(c)) #define C1 CI(1) typedef struct field { char *name; fldt_t ftyp; offset_fnc_t offset; count_fnc_t count; int flags; typnm_t next; } field_t; /* * flag values */ #define FLD_ABASE1 1 /* field array base is 1 not 0 */ #define FLD_SKIPALL 2 /* skip this field in an all-fields print */ #define FLD_ARRAY 4 /* this field is an array */ #define FLD_OFFSET 8 /* offset value is a function pointer */ #define FLD_COUNT 16 /* count value is a function pointer */ typedef int (*size_fnc_t)(void *obj, int startoff, int idx); #define SI(s) ((size_fnc_t)(intptr_t)(s)) typedef struct ftattr { fldt_t ftyp; char *name; prfnc_t prfunc; char *fmtstr; size_fnc_t size; int arg; adfnc_t adfunc; const field_t *subfld; } ftattr_t; extern const ftattr_t ftattrtab[]; /* * arg values */ #define FTARG_SKIPZERO 1 /* skip 0 words */ #define FTARG_DONULL 2 /* make -1 words be "null" */ #define FTARG_SKIPNULL 4 /* skip -1 words */ #define FTARG_SIGNED 8 /* field value is signed */ #define FTARG_SIZE 16 /* size field is a function */ #define FTARG_SKIPNMS 32 /* skip printing names this time */ #define FTARG_OKEMPTY 64 /* ok if this (union type) is empty */ extern int bitoffset(const field_t *f, void *obj, int startoff, int idx); extern int fcount(const field_t *f, void *obj, int startoff); extern const field_t *findfield(char *name, const field_t *fields, void *obj, int startoff); extern int fsize(const field_t *f, void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/flist.c0000644000000000000000000002261713063067170014353 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "flist.h" #include "debug.h" #include "output.h" #include "malloc.h" static void flist_expand_arrays(flist_t *fl); static void flist_expand_structs(flist_t *fl, void *obj); static flist_t *flist_replicate(flist_t *fl); static ftok_t *flist_split(char *s); static void ftok_free(ftok_t *ft); static void flist_expand_arrays( flist_t *fl) { const field_t *f; #ifdef DEBUG const ftattr_t *fa; #endif int high; int idx; int low; flist_t *new; flist_t *prev; flist_t *sib; f = fl->fld; #ifdef DEBUG fa = &ftattrtab[f->ftyp]; #endif ASSERT(fa->ftyp == f->ftyp); ASSERT(f->flags & FLD_ARRAY); low = fl->low; high = fl->high; fl->high = fl->low; sib = fl->sibling; for (idx = low + 1, prev = fl; idx <= high; idx++) { new = flist_make(f->name); new->fld = f; new->low = new->high = idx; new->flags |= FL_OKLOW | FL_OKHIGH; new->child = flist_replicate(fl->child); prev->sibling = new; prev = new; } prev->sibling = sib; } static void flist_expand_structs( flist_t *fl, void *obj) { const field_t *cf; const field_t *f; const ftattr_t *fa; flist_t *new; flist_t *prev; f = fl->fld; fa = &ftattrtab[f->ftyp]; ASSERT(fa->ftyp == f->ftyp); ASSERT(fa->subfld != NULL); ASSERT(fl->child == NULL); for (cf = fa->subfld, prev = NULL; cf->name != NULL; cf++) { if (fcount(cf, obj, fl->offset) == 0) continue; if (cf->flags & FLD_SKIPALL) continue; new = flist_make(cf->name); new->fld = cf; if (prev) prev->sibling = new; else fl->child = new; prev = new; } } void flist_free( flist_t *fl) { if (fl->child) flist_free(fl->child); if (fl->sibling) flist_free(fl->sibling); if (fl->name) xfree(fl->name); xfree(fl); } flist_t * flist_make( char *name) { flist_t *fl; fl = xmalloc(sizeof(*fl)); fl->name = xstrdup(name); fl->fld = NULL; fl->child = NULL; fl->sibling = NULL; fl->low = 0; fl->high = 0; fl->flags = 0; fl->offset = 0; return fl; } int flist_parse( const field_t *fields, flist_t *fl, void *obj, int startoff) { const field_t *f; const ftattr_t *fa; int high; int low; while (fl) { f = findfield(fl->name, fields, obj, startoff); if (f == NULL) { dbprintf(_("field %s not found\n"), fl->name); return 0; } fl->fld = f; fa = &ftattrtab[f->ftyp]; ASSERT(fa->ftyp == f->ftyp); if (f->flags & FLD_ARRAY) { low = (f->flags & FLD_ABASE1) != 0; high = fcount(f, obj, startoff) + low - 1; if (low > high) { dbprintf(_("no elements in %s\n"), fl->name); return 0; } if (fl->flags & FL_OKHIGH) { if (fl->low < low || fl->low > high || fl->high < low || fl->high > high) { dbprintf(_("indices %d-%d for field %s " "out of range %d-%d\n"), fl->low, fl->high, fl->name, low, high); return 0; } } else if (fl->flags & FL_OKLOW) { if (fl->low < low || fl->low > high) { dbprintf(_("index %d for field %s out of " "range %d-%d\n"), fl->low, fl->name, low, high); return 0; } fl->high = fl->low; fl->flags |= FL_OKHIGH; } else { fl->low = low; fl->high = high; fl->flags |= FL_OKLOW | FL_OKHIGH; } } else { if (fl->flags & FL_OKLOW) { dbprintf(_("field %s is not an array\n"), fl->name); return 0; } } fl->offset = startoff + bitoffset(f, obj, startoff, fl->low); if ((fl->child != NULL || fa->prfunc == NULL) && (f->flags & FLD_ARRAY) && fl->low != fl->high) flist_expand_arrays(fl); if (fa->prfunc == NULL && fl->child == NULL) flist_expand_structs(fl, obj); if (fl->child) { if (fa->subfld == NULL) { dbprintf(_("field %s has no subfields\n"), fl->name); return 0; } if (!flist_parse(fa->subfld, fl->child, obj, fl->offset)) return 0; } fl = fl->sibling; } return 1; } void flist_print( flist_t *fl) { if (!(debug_state & DEBUG_FLIST)) return; while (fl) { dbprintf(_("fl@%p:\n"), fl); dbprintf(_("\tname=%s, fld=%p, child=%p, sibling=%p\n"), fl->name, fl->fld, fl->child, fl->sibling); dbprintf(_("\tlow=%d, high=%d, flags=%d (%s%s), offset=%d\n"), fl->low, fl->high, fl->flags, fl->flags & FL_OKLOW ? _("oklow ") : "", fl->flags & FL_OKHIGH ? _("okhigh") : "", fl->offset); dbprintf(_("\tfld->name=%s, fld->ftyp=%d (%s)\n"), fl->fld->name, fl->fld->ftyp, ftattrtab[fl->fld->ftyp].name); dbprintf(_("\tfld->flags=%d (%s%s%s%s%s)\n"), fl->fld->flags, fl->fld->flags & FLD_ABASE1 ? "abase1 " : "", fl->fld->flags & FLD_SKIPALL ? "skipall " : "", fl->fld->flags & FLD_ARRAY ? "array " : "", fl->fld->flags & FLD_OFFSET ? "offset " : "", fl->fld->flags & FLD_COUNT ? "count " : ""); if (fl->child) flist_print(fl->child); fl = fl->sibling; } } static flist_t * flist_replicate( flist_t *f) { flist_t *new; if (f == NULL) return NULL; new = flist_make(f->name); new->fld = f->fld; new->child = flist_replicate(f->child); new->sibling = flist_replicate(f->sibling); new->low = f->low; new->high = f->high; new->flags = f->flags; new->offset = f->offset; return new; } flist_t * flist_scan( char *name) { flist_t *fl; flist_t *lfl; flist_t *nfl; int num; ftok_t *p; ftok_t *v; char *x; v = flist_split(name); if (!v) return NULL; p = v; fl = lfl = NULL; while (p->tokty != TT_END) { if (p->tokty != TT_NAME) goto bad; nfl = flist_make(p->tok); if (lfl) lfl->child = nfl; else fl = nfl; lfl = nfl; p++; if (p->tokty == TT_LB) { p++; if (p->tokty != TT_NUM) goto bad; num = (int)strtoul(p->tok, &x, 0); if (*x != '\0') goto bad; nfl->flags |= FL_OKLOW; nfl->low = num; p++; if (p->tokty == TT_DASH) { p++; if (p->tokty != TT_NUM) goto bad; num = (int)strtoul(p->tok, &x, 0); if (*x != '\0') goto bad; nfl->flags |= FL_OKHIGH; nfl->high = num; p++; } if (p->tokty != TT_RB) goto bad; p++; } if (p->tokty == TT_DOT) { p++; if (p->tokty == TT_END) goto bad; } } ftok_free(v); return fl; bad: dbprintf(_("bad syntax in field name %s\n"), name); ftok_free(v); if (fl) flist_free(fl); return NULL; } static ftok_t * flist_split( char *s) { char *a; int i; static char *idchars; static char *initidchar; int l; int tailskip = 0; static char *numchars; static char *xnumchars; /* extended for hex conversion */ int nv; static char punctchars[] = "[-]."; static tokty_t puncttypes[] = { TT_LB, TT_DASH, TT_RB, TT_DOT }; tokty_t t; ftok_t *v; if (idchars == NULL) { idchars = xmalloc(26 + 10 + 1 + 1); initidchar = xmalloc(26 + 1); numchars = xmalloc(10 + 1); xnumchars = xmalloc(12 + 1); for (i = 'a'; i <= 'z'; i++) { idchars[i - 'a'] = i; initidchar[i - 'a'] = i; } for (i = '0'; i <= '9'; i++) { idchars[26 + (i - '0')] = i; numchars[i - '0'] = i; xnumchars[i - '0'] = i; } idchars[26 + 10] = '_'; idchars[26 + 10 + 1] = '\0'; initidchar[26] = '\0'; numchars[10] = '\0'; xnumchars[10] = 'x'; xnumchars[11] = 'X'; xnumchars[12] = '\0'; } nv = 0; v = xmalloc(sizeof(*v)); v->tok = NULL; while (*s) { /* need to add string handling */ if (*s == '\"') { s++; /* skip first quote */ if ((a = strrchr(s, '\"')) == NULL) { dbprintf(_("missing closing quote %s\n"), s); ftok_free(v); return NULL; } tailskip = 1; /* skip remaing quote */ l = (int)(a - s); t = TT_STRING; } else if (strchr(initidchar, *s)) { l = (int)strspn(s, idchars); t = TT_NAME; } else if (strchr(numchars, *s)) { l = (int)strspn(s, xnumchars); t = TT_NUM; } else if ((a = strchr(punctchars, *s))) { l = 1; t = puncttypes[a - punctchars]; } else { dbprintf(_("bad character in field %s\n"), s); ftok_free(v); return NULL; } a = xmalloc(l + 1); strncpy(a, s, l); a[l] = '\0'; v = xrealloc(v, (nv + 2) * sizeof(*v)); v[nv].tok = a; v[nv].tokty = t; nv++; s += l + tailskip; tailskip = 0; } v[nv].tok = NULL; v[nv].tokty = TT_END; return v; } /* * Given a set of fields, scan for a field of the given type. * Return an flist leading to the first found field * of that type. * Return NULL if no field of the given type is found. */ flist_t * flist_find_ftyp( const field_t *fields, fldt_t type) { flist_t *fl; const field_t *f; const ftattr_t *fa; for (f = fields; f->name; f++) { fl = flist_make(f->name); fl->fld = f; if (f->ftyp == type) return fl; fa = &ftattrtab[f->ftyp]; if (fa->subfld) { flist_t *nfl; nfl = flist_find_ftyp(fa->subfld, type); if (nfl) { fl->child = nfl; return fl; } } flist_free(fl); } return NULL; } static void ftok_free( ftok_t *ft) { ftok_t *p; for (p = ft; p->tok; p++) xfree(p->tok); xfree(ft); } xfsprogs-4.9.0+nmu1ubuntu2/db/flist.h0000644000000000000000000000147513063067170014357 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. */ struct field; typedef struct flist { char *name; const struct field *fld; struct flist *child; struct flist *sibling; int low; int high; int flags; int offset; } flist_t; /* * Flags for flist */ #define FL_OKLOW 1 #define FL_OKHIGH 2 typedef enum tokty { TT_NAME, TT_NUM, TT_STRING, TT_LB, TT_RB, TT_DASH, TT_DOT, TT_END } tokty_t; typedef struct ftok { char *tok; tokty_t tokty; } ftok_t; extern void flist_free(flist_t *fl); extern flist_t *flist_make(char *name); extern int flist_parse(const struct field *fields, flist_t *fl, void *obj, int startoff); extern void flist_print(flist_t *fl); extern flist_t *flist_scan(char *name); extern flist_t *flist_find_ftyp(const field_t *fields, fldt_t type); xfsprogs-4.9.0+nmu1ubuntu2/db/fprint.c0000644000000000000000000001064713063067170014534 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "inode.h" #include "btblock.h" #include "bit.h" #include "print.h" #include "output.h" #include "sig.h" #include "malloc.h" #include "io.h" int fp_charns( void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array) { int i; char *p; ASSERT(bitoffs(bit) == 0); ASSERT(size == bitsz(char)); dbprintf("\""); for (i = 0, p = (char *)obj + byteize(bit); i < count && !seenint(); i++, p++) { if (*p == '\\' || *p == '\'' || *p == '"' || *p == '\?') dbprintf("\\%c", *p); else if (isgraph((int)*p) || *p == ' ') dbprintf("%c", *p); else if (*p == '\a' || *p == '\b' || *p == '\f' || *p == '\n' || *p == '\r' || *p == '\t' || *p == '\v') dbprintf("\\%c", *p + ('a' - '\a')); else dbprintf("\\%03o", *p & 0xff); } dbprintf("\""); return 1; } int fp_num( void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array) { int bitpos; int i; int isnull; __int64_t val; for (i = 0, bitpos = bit; i < count && !seenint(); i++, bitpos += size) { val = getbitval(obj, bitpos, size, (arg & FTARG_SIGNED) ? BVSIGNED : BVUNSIGNED); if ((arg & FTARG_SKIPZERO) && val == 0) continue; isnull = (arg & FTARG_SIGNED) || size == 64 ? val == -1LL : val == ((1LL << size) - 1LL); if ((arg & FTARG_SKIPNULL) && isnull) continue; if (array && count > 1) dbprintf("%d:", i + base); if ((arg & FTARG_DONULL) && isnull) dbprintf(_("null")); else if (size > 32) dbprintf(fmtstr, val); else dbprintf(fmtstr, (__int32_t)val); if (i < count - 1) dbprintf(" "); } return 1; } /*ARGSUSED*/ int fp_sarray( void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array) { print_sarray(obj, bit, count, size, base, array, (const field_t *)fmtstr, (arg & FTARG_SKIPNMS) != 0); return 1; } /*ARGSUSED*/ int fp_time( void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array) { int bitpos; char *c; int i; time_t t; ASSERT(bitoffs(bit) == 0); for (i = 0, bitpos = bit; i < count && !seenint(); i++, bitpos += size) { if (array) dbprintf("%d:", i + base); t=(time_t)getbitval((char *)obj + byteize(bitpos), 0, sizeof(int32_t)*8, 0); c = ctime(&t); dbprintf("%24.24s", c); if (i < count - 1) dbprintf(" "); } return 1; } /*ARGSUSED*/ int fp_uuid( void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array) { char bp[40]; /* UUID string is 36 chars + trailing '\0' */ int i; uuid_t *p; ASSERT(bitoffs(bit) == 0); for (p = (uuid_t *)((char *)obj + byteize(bit)), i = 0; i < count && !seenint(); i++, p++) { if (array) dbprintf("%d:", i + base); platform_uuid_unparse(p, bp); dbprintf("%s", bp); if (i < count - 1) dbprintf(" "); } return 1; } /* * CRC is correct is the current buffer it is being pulled out * of is not marked with a EFSCORRUPTED error. */ int fp_crc( void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array) { int bitpos; int i; __int64_t val; char *ok; switch (iocur_crc_valid()) { case -1: ok = "unchecked"; break; case 0: ok = "bad"; break; case 1: ok = "correct"; break; default: ok = "unknown state"; break; } for (i = 0, bitpos = bit; i < count && !seenint(); i++, bitpos += size) { if (array) dbprintf("%d:", i + base); val = getbitval(obj, bitpos, size, BVUNSIGNED); if (size > 32) dbprintf(fmtstr, val, ok); else dbprintf(fmtstr, (__int32_t)val, ok); if (i < count - 1) dbprintf(" "); } return 1; } xfsprogs-4.9.0+nmu1ubuntu2/db/fprint.h0000644000000000000000000000275113063067167014544 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ typedef int (*prfnc_t)(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); extern int fp_charns(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); extern int fp_num(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); extern int fp_sarray(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); extern int fp_time(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); extern int fp_uuid(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); extern int fp_crc(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); xfsprogs-4.9.0+nmu1ubuntu2/db/frag.c0000644000000000000000000002724513063067170014153 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include "bmap.h" #include "command.h" #include "frag.h" #include "io.h" #include "output.h" #include "type.h" #include "init.h" #include "malloc.h" typedef struct extent { xfs_fileoff_t startoff; xfs_filblks_t blockcount; } extent_t; typedef struct extmap { int naents; int nents; extent_t ents[1]; } extmap_t; #define EXTMAP_SIZE(n) \ (offsetof(extmap_t, ents) + (sizeof(extent_t) * (n))) static int aflag; static int dflag; static __uint64_t extcount_actual; static __uint64_t extcount_ideal; static int fflag; static int lflag; static int qflag; static int Rflag; static int rflag; static int vflag; typedef void (*scan_lbtree_f_t)(struct xfs_btree_block *block, int level, extmap_t **extmapp, typnm_t btype); typedef void (*scan_sbtree_f_t)(struct xfs_btree_block *block, int level, xfs_agf_t *agf); static extmap_t *extmap_alloc(xfs_extnum_t nex); static xfs_extnum_t extmap_ideal(extmap_t *extmap); static void extmap_set_ext(extmap_t **extmapp, xfs_fileoff_t o, xfs_extlen_t c); static int frag_f(int argc, char **argv); static int init(int argc, char **argv); static void process_bmbt_reclist(xfs_bmbt_rec_t *rp, int numrecs, extmap_t **extmapp); static void process_btinode(xfs_dinode_t *dip, extmap_t **extmapp, int whichfork); static void process_exinode(xfs_dinode_t *dip, extmap_t **extmapp, int whichfork); static void process_fork(xfs_dinode_t *dip, int whichfork); static void process_inode(xfs_agf_t *agf, xfs_agino_t agino, xfs_dinode_t *dip); static void scan_ag(xfs_agnumber_t agno); static void scan_lbtree(xfs_fsblock_t root, int nlevels, scan_lbtree_f_t func, extmap_t **extmapp, typnm_t btype); static void scan_sbtree(xfs_agf_t *agf, xfs_agblock_t root, int nlevels, scan_sbtree_f_t func, typnm_t btype); static void scanfunc_bmap(struct xfs_btree_block *block, int level, extmap_t **extmapp, typnm_t btype); static void scanfunc_ino(struct xfs_btree_block *block, int level, xfs_agf_t *agf); static const cmdinfo_t frag_cmd = { "frag", NULL, frag_f, 0, -1, 0, "[-a] [-d] [-f] [-l] [-q] [-R] [-r] [-v]", "get file fragmentation data", NULL }; static extmap_t * extmap_alloc( xfs_extnum_t nex) { extmap_t *extmap; if (nex < 1) nex = 1; extmap = xmalloc(EXTMAP_SIZE(nex)); extmap->naents = nex; extmap->nents = 0; return extmap; } static xfs_extnum_t extmap_ideal( extmap_t *extmap) { extent_t *ep; xfs_extnum_t rval; for (ep = &extmap->ents[0], rval = 0; ep < &extmap->ents[extmap->nents]; ep++) { if (ep == &extmap->ents[0] || ep->startoff != ep[-1].startoff + ep[-1].blockcount) rval++; } return rval; } static void extmap_set_ext( extmap_t **extmapp, xfs_fileoff_t o, xfs_extlen_t c) { extmap_t *extmap; extent_t *ent; extmap = *extmapp; if (extmap->nents == extmap->naents) { extmap->naents++; extmap = xrealloc(extmap, EXTMAP_SIZE(extmap->naents)); *extmapp = extmap; } ent = &extmap->ents[extmap->nents]; ent->startoff = o; ent->blockcount = c; extmap->nents++; } void frag_init(void) { add_command(&frag_cmd); } /* * Get file fragmentation information. */ static int frag_f( int argc, char **argv) { xfs_agnumber_t agno; double answer; if (!init(argc, argv)) return 0; for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) scan_ag(agno); if (extcount_actual) answer = (double)(extcount_actual - extcount_ideal) * 100.0 / (double)extcount_actual; else answer = 0.0; dbprintf(_("actual %llu, ideal %llu, fragmentation factor %.2f%%\n"), extcount_actual, extcount_ideal, answer); dbprintf(_("Note, this number is largely meaningless.\n")); answer = (double)extcount_actual / (double)extcount_ideal; dbprintf(_("Files on this filesystem average %.2f extents per file\n"), answer); return 0; } static int init( int argc, char **argv) { int c; aflag = dflag = fflag = lflag = qflag = Rflag = rflag = vflag = 0; optind = 0; while ((c = getopt(argc, argv, "adflqRrv")) != EOF) { switch (c) { case 'a': aflag = 1; break; case 'd': dflag = 1; break; case 'f': fflag = 1; break; case 'l': lflag = 1; break; case 'q': qflag = 1; break; case 'R': Rflag = 1; break; case 'r': rflag = 1; break; case 'v': vflag = 1; break; default: dbprintf(_("bad option for frag command\n")); return 0; } } if (!aflag && !dflag && !fflag && !lflag && !qflag && !Rflag && !rflag) aflag = dflag = fflag = lflag = qflag = Rflag = rflag = 1; extcount_actual = extcount_ideal = 0; return 1; } static void process_bmbt_reclist( xfs_bmbt_rec_t *rp, int numrecs, extmap_t **extmapp) { xfs_filblks_t c; int f; int i; xfs_fileoff_t o; xfs_fsblock_t s; for (i = 0; i < numrecs; i++, rp++) { convert_extent(rp, &o, &s, &c, &f); extmap_set_ext(extmapp, (xfs_fileoff_t)o, (xfs_extlen_t)c); } } static void process_btinode( xfs_dinode_t *dip, extmap_t **extmapp, int whichfork) { xfs_bmdr_block_t *dib; int i; xfs_bmbt_ptr_t *pp; dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); if (be16_to_cpu(dib->bb_level) == 0) { xfs_bmbt_rec_t *rp = XFS_BMDR_REC_ADDR(dib, 1); process_bmbt_reclist(rp, be16_to_cpu(dib->bb_numrecs), extmapp); return; } pp = XFS_BMDR_PTR_ADDR(dib, 1, libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0)); for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++) scan_lbtree(get_unaligned_be64(&pp[i]), be16_to_cpu(dib->bb_level), scanfunc_bmap, extmapp, whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA); } static void process_exinode( xfs_dinode_t *dip, extmap_t **extmapp, int whichfork) { xfs_bmbt_rec_t *rp; rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork); process_bmbt_reclist(rp, XFS_DFORK_NEXTENTS(dip, whichfork), extmapp); } static void process_fork( xfs_dinode_t *dip, int whichfork) { extmap_t *extmap; int nex; nex = XFS_DFORK_NEXTENTS(dip, whichfork); if (!nex) return; extmap = extmap_alloc(nex); switch (XFS_DFORK_FORMAT(dip, whichfork)) { case XFS_DINODE_FMT_EXTENTS: process_exinode(dip, &extmap, whichfork); break; case XFS_DINODE_FMT_BTREE: process_btinode(dip, &extmap, whichfork); break; } extcount_actual += extmap->nents; extcount_ideal += extmap_ideal(extmap); xfree(extmap); } static void process_inode( xfs_agf_t *agf, xfs_agino_t agino, xfs_dinode_t *dip) { __uint64_t actual; __uint64_t ideal; xfs_ino_t ino; int skipa; int skipd; ino = XFS_AGINO_TO_INO(mp, be32_to_cpu(agf->agf_seqno), agino); switch (be16_to_cpu(dip->di_mode) & S_IFMT) { case S_IFDIR: skipd = !dflag; break; case S_IFREG: if (!rflag && (be16_to_cpu(dip->di_flags) & XFS_DIFLAG_REALTIME)) skipd = 1; else if (!Rflag && (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino)) skipd = 1; else if (!qflag && (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino || ino == mp->m_sb.sb_pquotino)) skipd = 1; else skipd = !fflag; break; case S_IFLNK: skipd = !lflag; break; default: skipd = 1; break; } actual = extcount_actual; ideal = extcount_ideal; if (!skipd) process_fork(dip, XFS_DATA_FORK); skipa = !aflag || !XFS_DFORK_Q(dip); if (!skipa) process_fork(dip, XFS_ATTR_FORK); if (vflag && (!skipd || !skipa)) dbprintf(_("inode %lld actual %lld ideal %lld\n"), ino, extcount_actual - actual, extcount_ideal - ideal); } static void scan_ag( xfs_agnumber_t agno) { xfs_agf_t *agf; xfs_agi_t *agi; push_cur(); set_cur(&typtab[TYP_AGF], XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if ((agf = iocur_top->data) == NULL) { dbprintf(_("can't read agf block for ag %u\n"), agno); pop_cur(); return; } push_cur(); set_cur(&typtab[TYP_AGI], XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if ((agi = iocur_top->data) == NULL) { dbprintf(_("can't read agi block for ag %u\n"), agno); pop_cur(); pop_cur(); return; } scan_sbtree(agf, be32_to_cpu(agi->agi_root), be32_to_cpu(agi->agi_level), scanfunc_ino, TYP_INOBT); pop_cur(); pop_cur(); } static void scan_lbtree( xfs_fsblock_t root, int nlevels, scan_lbtree_f_t func, extmap_t **extmapp, typnm_t btype) { push_cur(); set_cur(&typtab[btype], XFS_FSB_TO_DADDR(mp, root), blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { dbprintf(_("can't read btree block %u/%u\n"), XFS_FSB_TO_AGNO(mp, root), XFS_FSB_TO_AGBNO(mp, root)); return; } (*func)(iocur_top->data, nlevels - 1, extmapp, btype); pop_cur(); } static void scan_sbtree( xfs_agf_t *agf, xfs_agblock_t root, int nlevels, scan_sbtree_f_t func, typnm_t btype) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); push_cur(); set_cur(&typtab[btype], XFS_AGB_TO_DADDR(mp, seqno, root), blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { dbprintf(_("can't read btree block %u/%u\n"), seqno, root); return; } (*func)(iocur_top->data, nlevels - 1, agf); pop_cur(); } static void scanfunc_bmap( struct xfs_btree_block *block, int level, extmap_t **extmapp, typnm_t btype) { int i; xfs_bmbt_ptr_t *pp; xfs_bmbt_rec_t *rp; int nrecs; nrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (nrecs > mp->m_bmap_dmxr[0]) { dbprintf(_("invalid numrecs (%u) in %s block\n"), nrecs, typtab[btype].name); return; } rp = XFS_BMBT_REC_ADDR(mp, block, 1); process_bmbt_reclist(rp, nrecs, extmapp); return; } if (nrecs > mp->m_bmap_dmxr[1]) { dbprintf(_("invalid numrecs (%u) in %s block\n"), nrecs, typtab[btype].name); return; } pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[0]); for (i = 0; i < nrecs; i++) scan_lbtree(be64_to_cpu(pp[i]), level, scanfunc_bmap, extmapp, btype); } static void scanfunc_ino( struct xfs_btree_block *block, int level, xfs_agf_t *agf) { xfs_agino_t agino; xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int i; int j; int off; xfs_inobt_ptr_t *pp; xfs_inobt_rec_t *rp; if (level == 0) { rp = XFS_INOBT_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { agino = be32_to_cpu(rp[i].ir_startino); off = XFS_INO_TO_OFFSET(mp, agino); push_cur(); set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, seqno, XFS_AGINO_TO_AGBNO(mp, agino)), XFS_FSB_TO_BB(mp, mp->m_ialloc_blks), DB_RING_IGN, NULL); if (iocur_top->data == NULL) { dbprintf(_("can't read inode block %u/%u\n"), seqno, XFS_AGINO_TO_AGBNO(mp, agino)); continue; } for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { if (XFS_INOBT_IS_FREE_DISK(&rp[i], j)) continue; process_inode(agf, agino + j, (xfs_dinode_t *) ((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog))); } pop_cur(); } return; } pp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), level, scanfunc_ino, TYP_INOBT); } xfsprogs-4.9.0+nmu1ubuntu2/db/frag.h0000644000000000000000000000136513063067170014153 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void frag_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/freesp.c0000644000000000000000000002232513063067170014512 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "freesp.h" #include "io.h" #include "type.h" #include "output.h" #include "init.h" #include "malloc.h" typedef struct histent { int low; int high; long long count; long long blocks; } histent_t; static void addhistent(int h); static void addtohist(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len); static int freesp_f(int argc, char **argv); static void histinit(int maxlen); static int init(int argc, char **argv); static void printhist(void); static void scan_ag(xfs_agnumber_t agno); static void scanfunc_bno(struct xfs_btree_block *block, typnm_t typ, int level, xfs_agf_t *agf); static void scanfunc_cnt(struct xfs_btree_block *block, typnm_t typ, int level, xfs_agf_t *agf); static void scan_freelist(xfs_agf_t *agf); static void scan_sbtree(xfs_agf_t *agf, xfs_agblock_t root, typnm_t typ, int nlevels, void (*func)(struct xfs_btree_block *block, typnm_t typ, int level, xfs_agf_t *agf)); static int usage(void); static int agcount; static xfs_agnumber_t *aglist; static int countflag; static int dumpflag; static int equalsize; static histent_t *hist; static int histcount; static int multsize; static int seen1; static int summaryflag; static long long totblocks; static long long totexts; static const cmdinfo_t freesp_cmd = { "freesp", NULL, freesp_f, 0, -1, 0, "[-bcdfs] [-a agno]... [-e binsize] [-h h1]... [-m binmult]", "summarize free space for filesystem", NULL }; static int inaglist( xfs_agnumber_t agno) { int i; if (agcount == 0) return 1; for (i = 0; i < agcount; i++) if (aglist[i] == agno) return 1; return 0; } /* * Report on freespace usage in xfs filesystem. */ static int freesp_f( int argc, char **argv) { xfs_agnumber_t agno; if (!init(argc, argv)) return 0; if (dumpflag) dbprintf("%8s %8s %8s\n", "agno", "agbno", "len"); for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { if (inaglist(agno)) scan_ag(agno); } if (histcount) printhist(); if (summaryflag) { dbprintf(_("total free extents %lld\n"), totexts); dbprintf(_("total free blocks %lld\n"), totblocks); dbprintf(_("average free extent size %g\n"), (double)totblocks / (double)totexts); } if (aglist) xfree(aglist); if (hist) xfree(hist); return 0; } void freesp_init(void) { add_command(&freesp_cmd); } static void aglistadd( char *a) { aglist = xrealloc(aglist, (agcount + 1) * sizeof(*aglist)); aglist[agcount] = (xfs_agnumber_t)atoi(a); agcount++; } static int init( int argc, char **argv) { int c; int speced = 0; agcount = countflag = dumpflag = equalsize = multsize = optind = 0; histcount = seen1 = summaryflag = 0; totblocks = totexts = 0; aglist = NULL; hist = NULL; while ((c = getopt(argc, argv, "a:bcde:h:m:s")) != EOF) { switch (c) { case 'a': aglistadd(optarg); break; case 'b': if (speced) return usage(); multsize = 2; speced = 1; break; case 'c': countflag = 1; break; case 'd': dumpflag = 1; break; case 'e': if (speced) return usage(); equalsize = atoi(optarg); speced = 1; break; case 'h': if (speced && !histcount) return usage(); addhistent(atoi(optarg)); speced = 1; break; case 'm': if (speced) return usage(); multsize = atoi(optarg); speced = 1; break; case 's': summaryflag = 1; break; case '?': return usage(); } } if (optind != argc) return usage(); if (!speced) multsize = 2; histinit((int)mp->m_sb.sb_agblocks); return 1; } static int usage(void) { dbprintf(_("freesp arguments: [-bcds] [-a agno] [-e binsize] [-h h1]... " "[-m binmult]\n")); return 0; } static void scan_ag( xfs_agnumber_t agno) { xfs_agf_t *agf; push_cur(); set_cur(&typtab[TYP_AGF], XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); agf = iocur_top->data; scan_freelist(agf); if (countflag) scan_sbtree(agf, be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]), TYP_CNTBT, be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]), scanfunc_cnt); else scan_sbtree(agf, be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]), TYP_BNOBT, be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]), scanfunc_bno); pop_cur(); } static void scan_freelist( xfs_agf_t *agf) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); xfs_agfl_t *agfl; xfs_agblock_t bno; int i; __be32 *agfl_bno; if (be32_to_cpu(agf->agf_flcount) == 0) return; push_cur(); set_cur(&typtab[TYP_AGFL], XFS_AG_DADDR(mp, seqno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); agfl = iocur_top->data; i = be32_to_cpu(agf->agf_flfirst); /* open coded XFS_BUF_TO_AGFL_BNO */ agfl_bno = xfs_sb_version_hascrc(&mp->m_sb) ? &agfl->agfl_bno[0] : (__be32 *)agfl; /* verify agf values before proceeding */ if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp) || be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) { dbprintf(_("agf %d freelist blocks bad, skipping " "freelist scan\n"), i); pop_cur(); return; } for (;;) { bno = be32_to_cpu(agfl_bno[i]); addtohist(seqno, bno, 1); if (i == be32_to_cpu(agf->agf_fllast)) break; if (++i == XFS_AGFL_SIZE(mp)) i = 0; } pop_cur(); } static void scan_sbtree( xfs_agf_t *agf, xfs_agblock_t root, typnm_t typ, int nlevels, void (*func)(struct xfs_btree_block *block, typnm_t typ, int level, xfs_agf_t *agf)) { xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); push_cur(); set_cur(&typtab[typ], XFS_AGB_TO_DADDR(mp, seqno, root), blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { dbprintf(_("can't read btree block %u/%u\n"), seqno, root); return; } (*func)(iocur_top->data, typ, nlevels - 1, agf); pop_cur(); } /*ARGSUSED*/ static void scanfunc_bno( struct xfs_btree_block *block, typnm_t typ, int level, xfs_agf_t *agf) { int i; xfs_alloc_ptr_t *pp; xfs_alloc_rec_t *rp; if (!(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC || be32_to_cpu(block->bb_magic) == XFS_ABTB_CRC_MAGIC)) return; if (level == 0) { rp = XFS_ALLOC_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) addtohist(be32_to_cpu(agf->agf_seqno), be32_to_cpu(rp[i].ar_startblock), be32_to_cpu(rp[i].ar_blockcount)); return; } pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), typ, level, scanfunc_bno); } static void scanfunc_cnt( struct xfs_btree_block *block, typnm_t typ, int level, xfs_agf_t *agf) { int i; xfs_alloc_ptr_t *pp; xfs_alloc_rec_t *rp; if (!(be32_to_cpu(block->bb_magic) == XFS_ABTC_MAGIC || be32_to_cpu(block->bb_magic) == XFS_ABTC_CRC_MAGIC)) return; if (level == 0) { rp = XFS_ALLOC_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) addtohist(be32_to_cpu(agf->agf_seqno), be32_to_cpu(rp[i].ar_startblock), be32_to_cpu(rp[i].ar_blockcount)); return; } pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_sbtree(agf, be32_to_cpu(pp[i]), typ, level, scanfunc_cnt); } static void addhistent( int h) { hist = xrealloc(hist, (histcount + 1) * sizeof(*hist)); if (h == 0) h = 1; hist[histcount].low = h; hist[histcount].count = hist[histcount].blocks = 0; histcount++; if (h == 1) seen1 = 1; } static void addtohist( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len) { int i; if (dumpflag) dbprintf("%8d %8d %8d\n", agno, agbno, len); totexts++; totblocks += len; for (i = 0; i < histcount; i++) { if (hist[i].high >= len) { hist[i].count++; hist[i].blocks += len; break; } } } static int hcmp( const void *a, const void *b) { return ((histent_t *)a)->low - ((histent_t *)b)->low; } static void histinit( int maxlen) { int i; if (equalsize) { for (i = 1; i < maxlen; i += equalsize) addhistent(i); } else if (multsize) { for (i = 1; i < maxlen; i *= multsize) addhistent(i); } else { if (!seen1) addhistent(1); qsort(hist, histcount, sizeof(*hist), hcmp); } for (i = 0; i < histcount; i++) { if (i < histcount - 1) hist[i].high = hist[i + 1].low - 1; else hist[i].high = maxlen; } } static void printhist(void) { int i; dbprintf("%7s %7s %7s %7s %6s\n", _("from"), _("to"), _("extents"), _("blocks"), _("pct")); for (i = 0; i < histcount; i++) { if (hist[i].count) dbprintf("%7d %7d %7lld %7lld %6.2f\n", hist[i].low, hist[i].high, hist[i].count, hist[i].blocks, hist[i].blocks * 100.0 / totblocks); } } xfsprogs-4.9.0+nmu1ubuntu2/db/freesp.h0000644000000000000000000000136713063067170014522 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void freesp_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/fsmap.c0000644000000000000000000001005113033541503014317 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "libxfs.h" #include "command.h" #include "fsmap.h" #include "output.h" #include "init.h" struct fsmap_info { unsigned long long nr; xfs_agnumber_t agno; }; static int fsmap_fn( struct xfs_btree_cur *cur, struct xfs_rmap_irec *rec, void *priv) { struct fsmap_info *info = priv; dbprintf(_("%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n"), info->nr, info->agno, rec->rm_startblock, rec->rm_blockcount, rec->rm_owner, rec->rm_offset, !!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK), !!(rec->rm_flags & XFS_RMAP_ATTR_FORK), !!(rec->rm_flags & XFS_RMAP_UNWRITTEN)); info->nr++; return 0; } static void fsmap( xfs_fsblock_t start_fsb, xfs_fsblock_t end_fsb) { struct fsmap_info info; xfs_agnumber_t start_ag; xfs_agnumber_t end_ag; xfs_agnumber_t agno; xfs_daddr_t eofs; struct xfs_rmap_irec low = {0}; struct xfs_rmap_irec high = {0}; struct xfs_btree_cur *bt_cur; struct xfs_buf *agbp; int error; eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); if (XFS_FSB_TO_DADDR(mp, end_fsb) >= eofs) end_fsb = XFS_DADDR_TO_FSB(mp, eofs - 1); low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb); high.rm_startblock = -1U; high.rm_owner = ULLONG_MAX; high.rm_offset = ULLONG_MAX; high.rm_flags = XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK | XFS_RMAP_UNWRITTEN; start_ag = XFS_FSB_TO_AGNO(mp, start_fsb); end_ag = XFS_FSB_TO_AGNO(mp, end_fsb); info.nr = 0; for (agno = start_ag; agno <= end_ag; agno++) { if (agno == end_ag) high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsb); error = -libxfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) { dbprintf(_("Error %d while reading AGF.\n"), error); return; } bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, agno); if (!bt_cur) { libxfs_putbuf(agbp); dbprintf(_("Not enough memory.\n")); return; } info.agno = agno; error = -libxfs_rmap_query_range(bt_cur, &low, &high, fsmap_fn, &info); if (error) { libxfs_btree_del_cursor(bt_cur, XFS_BTREE_ERROR); libxfs_putbuf(agbp); dbprintf(_("Error %d while querying fsmap btree.\n"), error); return; } libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); libxfs_putbuf(agbp); if (agno == start_ag) low.rm_startblock = 0; } } int fsmap_f( int argc, char **argv) { char *p; int c; xfs_fsblock_t start_fsb = 0; xfs_fsblock_t end_fsb = NULLFSBLOCK; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) { dbprintf(_("Filesystem does not support reverse mapping btree.\n")); return 0; } while ((c = getopt(argc, argv, "")) != EOF) { switch (c) { default: dbprintf(_("Bad option for fsmap command.\n")); return 0; } } if (argc > optind) { start_fsb = strtoull(argv[optind], &p, 0); if (*p != '\0' || start_fsb >= mp->m_sb.sb_dblocks) { dbprintf(_("Bad fsmap start_fsb %s.\n"), argv[optind]); return 0; } } if (argc > optind + 1) { end_fsb = strtoull(argv[optind + 1], &p, 0); if (*p != '\0') { dbprintf(_("Bad fsmap end_fsb %s.\n"), argv[optind + 1]); return 0; } } fsmap(start_fsb, end_fsb); return 0; } static const cmdinfo_t fsmap_cmd = { "fsmap", NULL, fsmap_f, 0, 2, 0, N_("[start_fsb] [end_fsb]"), N_("display reverse mapping(s)"), NULL }; void fsmap_init(void) { add_command(&fsmap_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/fsmap.h0000644000000000000000000000153613033541503014334 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ extern void fsmap_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/hash.c0000644000000000000000000000275213063067170014153 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "addr.h" #include "command.h" #include "type.h" #include "io.h" #include "output.h" static int hash_f(int argc, char **argv); static void hash_help(void); static const cmdinfo_t hash_cmd = { "hash", NULL, hash_f, 1, 1, 0, N_("string"), N_("calculate hash value"), hash_help }; static void hash_help(void) { dbprintf(_( "\n" " 'hash' prints out the calculated hash value for a string using the\n" "directory/attribute code hash function.\n" "\n" " Usage: \"hash \"\n" "\n" )); } /* ARGSUSED */ static int hash_f( int argc, char **argv) { xfs_dahash_t hashval; hashval = libxfs_da_hashname((unsigned char *)argv[1], (int)strlen(argv[1])); dbprintf("0x%x\n", hashval); return 0; } void hash_init(void) { add_command(&hash_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/hash.h0000644000000000000000000000136113063067170014153 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void hash_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/help.c0000644000000000000000000000401513063067170014152 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "help.h" #include "output.h" static void help_all(void); static void help_onecmd(const char *cmd, const cmdinfo_t *ct); static int help_f(int argc, char **argv); static void help_oneline(const char *cmd, const cmdinfo_t *ct); static const cmdinfo_t help_cmd = { "help", "?", help_f, 0, 1, 0, N_("[command]"), N_("help for one or all commands"), NULL }; static void help_all(void) { const cmdinfo_t *ct; for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) help_oneline(ct->name, ct); dbprintf(_("\nUse 'help commandname' for extended help.\n")); } static int help_f( int argc, char **argv) { const cmdinfo_t *ct; if (argc == 1) { help_all(); return 0; } ct = find_command(argv[1]); if (ct == NULL) { dbprintf(_("command %s not found\n"), argv[1]); return 0; } help_onecmd(argv[1], ct); return 0; } void help_init(void) { add_command(&help_cmd); } static void help_onecmd( const char *cmd, const cmdinfo_t *ct) { help_oneline(cmd, ct); if (ct->help) ct->help(); } static void help_oneline( const char *cmd, const cmdinfo_t *ct) { if (cmd) dbprintf("%s ", cmd); else { dbprintf("%s ", ct->name); if (ct->altname) dbprintf(_("(or %s) "), ct->altname); } if (ct->args) dbprintf("%s ", ct->args); dbprintf("-- %s\n", ct->oneline); } xfsprogs-4.9.0+nmu1ubuntu2/db/help.h0000644000000000000000000000136513063067170014164 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void help_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/init.c0000644000000000000000000001214713063067170014172 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include #include "command.h" #include "init.h" #include "input.h" #include "io.h" #include "init.h" #include "sig.h" #include "output.h" #include "malloc.h" #include "type.h" static char **cmdline; static int ncmdline; char *fsdevice; int blkbb; int exitcode; int expert_mode; int force; struct xfs_mount xmount; struct xfs_mount *mp; struct xlog xlog; libxfs_init_t x; xfs_agnumber_t cur_agno = NULLAGNUMBER; static void usage(void) { fprintf(stderr, _( "Usage: %s [-ifFrxV] [-p prog] [-l logdev] [-c cmd]... device\n" ), progname); exit(1); } void init( int argc, char **argv) { struct xfs_sb *sbp; struct xfs_buf *bp; int c; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); progname = basename(argv[0]); while ((c = getopt(argc, argv, "c:fFip:rxVl:")) != EOF) { switch (c) { case 'c': cmdline = xrealloc(cmdline, (ncmdline+1)*sizeof(char*)); cmdline[ncmdline++] = optarg; break; case 'f': x.disfile = 1; break; case 'F': force = 1; break; case 'i': x.isreadonly = (LIBXFS_ISREADONLY|LIBXFS_ISINACTIVE); break; case 'p': progname = optarg; break; case 'r': x.isreadonly = LIBXFS_ISREADONLY; break; case 'l': x.logname = optarg; break; case 'x': expert_mode = 1; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); case '?': usage(); /*NOTREACHED*/ } } if (optind + 1 != argc) { usage(); /*NOTREACHED*/ } fsdevice = argv[optind]; if (!x.disfile) x.volname = fsdevice; else x.dname = fsdevice; x.bcache_flags = CACHE_MISCOMPARE_PURGE; if (!libxfs_init(&x)) { fputs(_("\nfatal error -- couldn't initialize XFS library\n"), stderr); exit(1); } /* * Read the superblock, but don't validate it - we are a diagnostic * tool and so need to be able to mount busted filesystems. */ memset(&xmount, 0, sizeof(struct xfs_mount)); libxfs_buftarg_init(&xmount, x.ddev, x.logdev, x.rtdev); bp = libxfs_readbuf(xmount.m_ddev_targp, XFS_SB_DADDR, 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, NULL); if (!bp || bp->b_error) { fprintf(stderr, _("%s: %s is invalid (cannot read first 512 " "bytes)\n"), progname, fsdevice); exit(1); } /* copy SB from buffer to in-core, converting architecture as we go */ libxfs_sb_from_disk(&xmount.m_sb, XFS_BUF_TO_SBP(bp)); libxfs_putbuf(bp); libxfs_purgebuf(bp); sbp = &xmount.m_sb; if (sbp->sb_magicnum != XFS_SB_MAGIC) { fprintf(stderr, _("%s: %s is not a valid XFS filesystem (unexpected SB magic number 0x%08x)\n"), progname, fsdevice, sbp->sb_magicnum); if (!force) { fprintf(stderr, _("Use -F to force a read attempt.\n")); exit(EXIT_FAILURE); } } mp = libxfs_mount(&xmount, sbp, x.ddev, x.logdev, x.rtdev, LIBXFS_MOUNT_DEBUGGER); if (!mp) { fprintf(stderr, _("%s: device %s unusable (not an XFS filesystem?)\n"), progname, fsdevice); exit(1); } mp->m_log = &xlog; blkbb = 1 << mp->m_blkbb_log; /* * xfs_check needs corrected incore superblock values */ if (sbp->sb_rootino != NULLFSINO && xfs_sb_version_haslazysbcount(&mp->m_sb)) { int error = -libxfs_initialize_perag_data(mp, sbp->sb_agcount); if (error) { fprintf(stderr, _("%s: cannot init perag data (%d). Continuing anyway.\n"), progname, error); } } if (xfs_sb_version_hassparseinodes(&mp->m_sb)) type_set_tab_spcrc(); else if (xfs_sb_version_hascrc(&mp->m_sb)) type_set_tab_crc(); push_cur(); init_commands(); init_sig(); } int main( int argc, char **argv) { int c, i, done = 0; char *input; char **v; int start_iocur_sp; pushfile(stdin); init(argc, argv); start_iocur_sp = iocur_sp; for (i = 0; !done && i < ncmdline; i++) { v = breakline(cmdline[i], &c); if (c) done = command(c, v); xfree(v); } if (cmdline) { xfree(cmdline); goto close_devices; } while (!done) { if ((input = fetchline()) == NULL) break; v = breakline(input, &c); if (c) done = command(c, v); doneline(input, v); } close_devices: /* * Make sure that we pop the all the buffer contexts we hold so that * they are released before we purge the caches during unmount. */ while (iocur_sp > start_iocur_sp) pop_cur(); libxfs_umount(mp); if (x.ddev) libxfs_device_close(x.ddev); if (x.logdev && x.logdev != x.ddev) libxfs_device_close(x.logdev); if (x.rtdev) libxfs_device_close(x.rtdev); return exitcode; } xfsprogs-4.9.0+nmu1ubuntu2/db/init.h0000644000000000000000000000160213063067170014171 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern char *fsdevice; extern int blkbb; extern int exitcode; extern int expert_mode; extern xfs_mount_t *mp; extern libxfs_init_t x; extern xfs_agnumber_t cur_agno; xfsprogs-4.9.0+nmu1ubuntu2/db/inode.c0000644000000000000000000004566313063067170014336 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "inode.h" #include "io.h" #include "print.h" #include "block.h" #include "bit.h" #include "output.h" #include "init.h" static int inode_a_bmbt_count(void *obj, int startoff); static int inode_a_bmx_count(void *obj, int startoff); static int inode_a_count(void *obj, int startoff); static int inode_a_offset(void *obj, int startoff, int idx); static int inode_a_sfattr_count(void *obj, int startoff); static int inode_core_nlinkv2_count(void *obj, int startoff); static int inode_core_onlink_count(void *obj, int startoff); static int inode_core_projid_count(void *obj, int startoff); static int inode_core_nlinkv1_count(void *obj, int startoff); static int inode_f(int argc, char **argv); static int inode_u_offset(void *obj, int startoff, int idx); static int inode_u_bmbt_count(void *obj, int startoff); static int inode_u_bmx_count(void *obj, int startoff); static int inode_u_c_count(void *obj, int startoff); static int inode_u_dev_count(void *obj, int startoff); static int inode_u_muuid_count(void *obj, int startoff); static int inode_u_sfdir2_count(void *obj, int startoff); static int inode_u_sfdir3_count(void *obj, int startoff); static int inode_u_symlink_count(void *obj, int startoff); static const cmdinfo_t inode_cmd = { "inode", NULL, inode_f, 0, 1, 1, "[inode#]", "set current inode", NULL }; const field_t inode_hfld[] = { { "", FLDT_INODE, OI(0), C1, 0, TYP_NONE }, { NULL } }; const field_t inode_crc_hfld[] = { { "", FLDT_INODE_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; /* XXX: fix this up! */ #define OFF(f) bitize(offsetof(xfs_dinode_t, di_ ## f)) const field_t inode_flds[] = { { "core", FLDT_DINODE_CORE, OI(OFF(magic)), C1, 0, TYP_NONE }, { "next_unlinked", FLDT_AGINO, OI(OFF(next_unlinked)), C1, 0, TYP_INODE }, { "u", FLDT_DINODE_U, inode_u_offset, C1, FLD_OFFSET, TYP_NONE }, { "a", FLDT_DINODE_A, inode_a_offset, inode_a_count, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { NULL } }; const field_t inode_crc_flds[] = { { "core", FLDT_DINODE_CORE, OI(OFF(magic)), C1, 0, TYP_NONE }, { "next_unlinked", FLDT_AGINO, OI(OFF(next_unlinked)), C1, 0, TYP_INODE }, { "v3", FLDT_DINODE_V3, OI(OFF(magic)), C1, 0, TYP_NONE }, { "u3", FLDT_DINODE_U, inode_u_offset, C1, FLD_OFFSET, TYP_NONE }, { "a", FLDT_DINODE_A, inode_a_offset, inode_a_count, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { NULL } }; #define COFF(f) bitize(offsetof(xfs_dinode_t, di_ ## f)) const field_t inode_core_flds[] = { { "magic", FLDT_UINT16X, OI(COFF(magic)), C1, 0, TYP_NONE }, { "mode", FLDT_UINT16O, OI(COFF(mode)), C1, 0, TYP_NONE }, { "version", FLDT_INT8D, OI(COFF(version)), C1, 0, TYP_NONE }, { "format", FLDT_DINODE_FMT, OI(COFF(format)), C1, 0, TYP_NONE }, { "nlinkv1", FLDT_UINT16D, OI(COFF(onlink)), inode_core_nlinkv1_count, FLD_COUNT, TYP_NONE }, { "nlinkv2", FLDT_UINT32D, OI(COFF(nlink)), inode_core_nlinkv2_count, FLD_COUNT, TYP_NONE }, { "onlink", FLDT_UINT16D, OI(COFF(onlink)), inode_core_onlink_count, FLD_COUNT, TYP_NONE }, { "projid_lo", FLDT_UINT16D, OI(COFF(projid_lo)), inode_core_projid_count, FLD_COUNT, TYP_NONE }, { "projid_hi", FLDT_UINT16D, OI(COFF(projid_hi)), inode_core_projid_count, FLD_COUNT, TYP_NONE }, { "uid", FLDT_UINT32D, OI(COFF(uid)), C1, 0, TYP_NONE }, { "gid", FLDT_UINT32D, OI(COFF(gid)), C1, 0, TYP_NONE }, { "flushiter", FLDT_UINT16D, OI(COFF(flushiter)), C1, 0, TYP_NONE }, { "atime", FLDT_TIMESTAMP, OI(COFF(atime)), C1, 0, TYP_NONE }, { "mtime", FLDT_TIMESTAMP, OI(COFF(mtime)), C1, 0, TYP_NONE }, { "ctime", FLDT_TIMESTAMP, OI(COFF(ctime)), C1, 0, TYP_NONE }, { "size", FLDT_FSIZE, OI(COFF(size)), C1, 0, TYP_NONE }, { "nblocks", FLDT_DRFSBNO, OI(COFF(nblocks)), C1, 0, TYP_NONE }, { "extsize", FLDT_EXTLEN, OI(COFF(extsize)), C1, 0, TYP_NONE }, { "nextents", FLDT_EXTNUM, OI(COFF(nextents)), C1, 0, TYP_NONE }, { "naextents", FLDT_AEXTNUM, OI(COFF(anextents)), C1, 0, TYP_NONE }, { "forkoff", FLDT_UINT8D, OI(COFF(forkoff)), C1, 0, TYP_NONE }, { "aformat", FLDT_DINODE_FMT, OI(COFF(aformat)), C1, 0, TYP_NONE }, { "dmevmask", FLDT_UINT32X, OI(COFF(dmevmask)), C1, 0, TYP_NONE }, { "dmstate", FLDT_UINT16D, OI(COFF(dmstate)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT16X, OI(COFF(flags)), C1, FLD_SKIPALL, TYP_NONE }, { "newrtbm", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NEWRTBM_BIT - 1), C1, 0, TYP_NONE }, { "prealloc", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_PREALLOC_BIT - 1), C1, 0, TYP_NONE }, { "realtime", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_REALTIME_BIT - 1), C1, 0, TYP_NONE }, { "immutable", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_IMMUTABLE_BIT-1), C1, 0, TYP_NONE }, { "append", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_APPEND_BIT - 1), C1, 0, TYP_NONE }, { "sync", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_SYNC_BIT - 1), C1, 0, TYP_NONE }, { "noatime", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NOATIME_BIT - 1), C1, 0, TYP_NONE }, { "nodump", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NODUMP_BIT - 1), C1, 0, TYP_NONE }, { "rtinherit", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_RTINHERIT_BIT-1), C1, 0, TYP_NONE }, { "projinherit", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_PROJINHERIT_BIT-1),C1, 0, TYP_NONE }, { "nosymlinks", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NOSYMLINKS_BIT-1), C1, 0, TYP_NONE }, { "extsz", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_EXTSIZE_BIT-1),C1, 0, TYP_NONE }, { "extszinherit", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_EXTSZINHERIT_BIT-1),C1, 0, TYP_NONE }, { "nodefrag", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NODEFRAG_BIT-1),C1, 0, TYP_NONE }, { "filestream", FLDT_UINT1, OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_FILESTREAM_BIT-1),C1, 0, TYP_NONE }, { "gen", FLDT_UINT32D, OI(COFF(gen)), C1, 0, TYP_NONE }, { NULL } }; const field_t inode_v3_flds[] = { { "crc", FLDT_CRC, OI(COFF(crc)), C1, 0, TYP_NONE }, { "change_count", FLDT_UINT64D, OI(COFF(changecount)), C1, 0, TYP_NONE }, { "lsn", FLDT_UINT64X, OI(COFF(lsn)), C1, 0, TYP_NONE }, { "flags2", FLDT_UINT64X, OI(COFF(flags2)), C1, 0, TYP_NONE }, { "cowextsize", FLDT_EXTLEN, OI(COFF(cowextsize)), C1, 0, TYP_NONE }, { "crtime", FLDT_TIMESTAMP, OI(COFF(crtime)), C1, 0, TYP_NONE }, { "inumber", FLDT_INO, OI(COFF(ino)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(COFF(uuid)), C1, 0, TYP_NONE }, { "reflink", FLDT_UINT1, OI(COFF(flags2) + bitsz(__uint64_t) - XFS_DIFLAG2_REFLINK_BIT-1), C1, 0, TYP_NONE }, { "cowextsz", FLDT_UINT1, OI(COFF(flags2) + bitsz(__uint64_t) - XFS_DIFLAG2_COWEXTSIZE_BIT-1), C1, 0, TYP_NONE }, { NULL } }; #define TOFF(f) bitize(offsetof(xfs_timestamp_t, t_ ## f)) const field_t timestamp_flds[] = { { "sec", FLDT_TIME, OI(TOFF(sec)), C1, 0, TYP_NONE }, { "nsec", FLDT_NSEC, OI(TOFF(nsec)), C1, 0, TYP_NONE }, { NULL } }; const field_t inode_u_flds[] = { { "bmbt", FLDT_BMROOTD, NULL, inode_u_bmbt_count, FLD_COUNT, TYP_NONE }, { "bmx", FLDT_BMAPBTDREC, NULL, inode_u_bmx_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "c", FLDT_CHARNS, NULL, inode_u_c_count, FLD_COUNT, TYP_NONE }, { "dev", FLDT_DEV, NULL, inode_u_dev_count, FLD_COUNT, TYP_NONE }, { "muuid", FLDT_UUID, NULL, inode_u_muuid_count, FLD_COUNT, TYP_NONE }, { "sfdir2", FLDT_DIR2SF, NULL, inode_u_sfdir2_count, FLD_COUNT, TYP_NONE }, { "sfdir3", FLDT_DIR3SF, NULL, inode_u_sfdir3_count, FLD_COUNT, TYP_NONE }, { "symlink", FLDT_CHARNS, NULL, inode_u_symlink_count, FLD_COUNT, TYP_NONE }, { NULL } }; const field_t inode_a_flds[] = { { "bmbt", FLDT_BMROOTA, NULL, inode_a_bmbt_count, FLD_COUNT, TYP_NONE }, { "bmx", FLDT_BMAPBTAREC, NULL, inode_a_bmx_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, { "sfattr", FLDT_ATTRSHORT, NULL, inode_a_sfattr_count, FLD_COUNT, TYP_NONE }, { NULL } }; static const char *dinode_fmt_name[] = { "dev", "local", "extents", "btree", "uuid" }; static const int dinode_fmt_name_size = sizeof(dinode_fmt_name) / sizeof(dinode_fmt_name[0]); /*ARGSUSED*/ int fp_dinode_fmt( void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array) { int bitpos; xfs_dinode_fmt_t f; int i; for (i = 0, bitpos = bit; i < count; i++, bitpos += size) { f = (xfs_dinode_fmt_t)getbitval(obj, bitpos, size, BVSIGNED); if (array) dbprintf("%d:", i + base); if (f < 0 || f >= dinode_fmt_name_size) dbprintf("%d", (int)f); else dbprintf("%d (%s)", (int)f, dinode_fmt_name[(int)f]); if (i < count - 1) dbprintf(" "); } return 1; } static int inode_a_bmbt_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; if (!XFS_DFORK_Q(dip)) return 0; ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff)); return dip->di_aformat == XFS_DINODE_FMT_BTREE; } static int inode_a_bmx_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; if (!XFS_DFORK_Q(dip)) return 0; ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff)); return dip->di_aformat == XFS_DINODE_FMT_EXTENTS ? be16_to_cpu(dip->di_anextents) : 0; } static int inode_a_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(startoff == 0); dip = obj; return XFS_DFORK_Q(dip); } static int inode_a_offset( void *obj, int startoff, int idx) { xfs_dinode_t *dip; ASSERT(startoff == 0); ASSERT(idx == 0); dip = obj; ASSERT(XFS_DFORK_Q(dip)); return bitize((int)((char *)XFS_DFORK_APTR(dip) - (char *)dip)); } static int inode_a_sfattr_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; if (!XFS_DFORK_Q(dip)) return 0; ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff)); return dip->di_aformat == XFS_DINODE_FMT_LOCAL; } int inode_a_size( void *obj, int startoff, int idx) { xfs_attr_shortform_t *asf; xfs_dinode_t *dip; ASSERT(startoff == 0); ASSERT(idx == 0); dip = obj; switch (dip->di_aformat) { case XFS_DINODE_FMT_LOCAL: asf = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); return bitize(be16_to_cpu(asf->hdr.totsize)); case XFS_DINODE_FMT_EXTENTS: return (int)be16_to_cpu(dip->di_anextents) * bitsz(xfs_bmbt_rec_t); case XFS_DINODE_FMT_BTREE: return bitize((int)XFS_DFORK_ASIZE(dip, mp)); default: return 0; } } static int inode_core_nlinkv1_count( void *obj, int startoff) { xfs_dinode_t *dic; ASSERT(startoff == 0); ASSERT(obj == iocur_top->data); dic = obj; return dic->di_version == 1; } static int inode_core_nlinkv2_count( void *obj, int startoff) { xfs_dinode_t *dic; ASSERT(startoff == 0); ASSERT(obj == iocur_top->data); dic = obj; return dic->di_version >= 2; } static int inode_core_onlink_count( void *obj, int startoff) { xfs_dinode_t *dic; ASSERT(startoff == 0); ASSERT(obj == iocur_top->data); dic = obj; return dic->di_version >= 2; } static int inode_core_projid_count( void *obj, int startoff) { xfs_dinode_t *dic; ASSERT(startoff == 0); ASSERT(obj == iocur_top->data); dic = obj; return dic->di_version >= 2; } static int inode_f( int argc, char **argv) { xfs_ino_t ino; char *p; if (argc > 1) { ino = strtoull(argv[1], &p, 0); if (*p != '\0') { dbprintf(_("bad value for inode number %s\n"), argv[1]); return 0; } set_cur_inode(ino); } else if (iocur_top->ino == NULLFSINO) dbprintf(_("no current inode\n")); else dbprintf(_("current inode number is %lld\n"), iocur_top->ino); return 0; } void inode_init(void) { add_command(&inode_cmd); } typnm_t inode_next_type(void) { switch (iocur_top->mode & S_IFMT) { case S_IFDIR: return TYP_DIR2; case S_IFLNK: return TYP_SYMLINK; case S_IFREG: if (iocur_top->ino == mp->m_sb.sb_rbmino) return TYP_RTBITMAP; else if (iocur_top->ino == mp->m_sb.sb_rsumino) return TYP_RTSUMMARY; else if (iocur_top->ino == mp->m_sb.sb_uquotino || iocur_top->ino == mp->m_sb.sb_gquotino || iocur_top->ino == mp->m_sb.sb_pquotino) return TYP_DQBLK; else return TYP_DATA; default: return TYP_NONE; } } int inode_size( void *obj, int startoff, int idx) { return bitize(mp->m_sb.sb_inodesize); } static int inode_u_offset( void *obj, int startoff, int idx) { xfs_dinode_t *dip; ASSERT(startoff == 0); ASSERT(idx == 0); dip = obj; return bitize((int)((char *)XFS_DFORK_DPTR(dip) - (char *)dip)); } static int inode_u_bmbt_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_BTREE; } static int inode_u_bmx_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_EXTENTS ? be32_to_cpu(dip->di_nextents) : 0; } static int inode_u_c_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_LOCAL && (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG ? (int)be64_to_cpu(dip->di_size) : 0; } static int inode_u_dev_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_DEV; } static int inode_u_muuid_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_UUID; } static int inode_u_sfdir2_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_LOCAL && (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFDIR && !xfs_sb_version_hasftype(&mp->m_sb); } static int inode_u_sfdir3_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_LOCAL && (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFDIR && xfs_sb_version_hasftype(&mp->m_sb); } int inode_u_size( void *obj, int startoff, int idx) { xfs_dinode_t *dip; ASSERT(startoff == 0); ASSERT(idx == 0); dip = obj; switch (dip->di_format) { case XFS_DINODE_FMT_DEV: return bitsz(xfs_dev_t); case XFS_DINODE_FMT_LOCAL: return bitize((int)be64_to_cpu(dip->di_size)); case XFS_DINODE_FMT_EXTENTS: return (int)be32_to_cpu(dip->di_nextents) * bitsz(xfs_bmbt_rec_t); case XFS_DINODE_FMT_BTREE: return bitize((int)XFS_DFORK_DSIZE(dip, mp)); case XFS_DINODE_FMT_UUID: return bitsz(uuid_t); default: return 0; } } static int inode_u_symlink_count( void *obj, int startoff) { xfs_dinode_t *dip; ASSERT(bitoffs(startoff) == 0); ASSERT(obj == iocur_top->data); dip = obj; ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); return dip->di_format == XFS_DINODE_FMT_LOCAL && (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFLNK ? (int)be64_to_cpu(dip->di_size) : 0; } /* * We are now using libxfs for our IO backend, so we should always try to use * inode cluster buffers rather than filesystem block sized buffers for reading * inodes. This means that we always use the same buffers as libxfs operations * does, and that avoids buffer cache issues caused by overlapping buffers. This * can be seen clearly when trying to read the root inode. Much of this logic is * similar to libxfs_imap(). */ void set_cur_inode( xfs_ino_t ino) { xfs_agblock_t agbno; xfs_agino_t agino; xfs_agnumber_t agno; xfs_dinode_t *dip; int offset; int numblks = blkbb; xfs_agblock_t cluster_agbno; agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); offset = XFS_AGINO_TO_OFFSET(mp, agino); if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || offset >= mp->m_sb.sb_inopblock || XFS_AGINO_TO_INO(mp, agno, agino) != ino) { dbprintf(_("bad inode number %lld\n"), ino); return; } cur_agno = agno; if (mp->m_inode_cluster_size > mp->m_sb.sb_blocksize && mp->m_inoalign_mask) { xfs_agblock_t chunk_agbno; xfs_agblock_t offset_agbno; int blks_per_cluster; blks_per_cluster = mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog; offset_agbno = agbno & mp->m_inoalign_mask; chunk_agbno = agbno - offset_agbno; cluster_agbno = chunk_agbno + ((offset_agbno / blks_per_cluster) * blks_per_cluster); offset += ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock); numblks = XFS_FSB_TO_BB(mp, blks_per_cluster); } else cluster_agbno = agbno; /* * First set_cur to the block with the inode * then use off_cur to get the right part of the buffer. */ ASSERT(typtab[TYP_INODE].typnm == TYP_INODE); /* ingore ring update here, do it explicitly below */ set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, cluster_agbno), numblks, DB_RING_IGN, NULL); off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize); if (!iocur_top->data) return; dip = iocur_top->data; iocur_top->ino_buf = 1; iocur_top->ino = ino; iocur_top->mode = be16_to_cpu(dip->di_mode); if ((iocur_top->mode & S_IFMT) == S_IFDIR) iocur_top->dirino = ino; if (xfs_sb_version_hascrc(&mp->m_sb)) { iocur_top->ino_crc_ok = libxfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize, XFS_DINODE_CRC_OFF); if (!iocur_top->ino_crc_ok) dbprintf( _("Metadata CRC error detected for ino %lld\n"), ino); } /* track updated info in ring */ ring_add(); } xfsprogs-4.9.0+nmu1ubuntu2/db/inode.h0000644000000000000000000000275113063067170014332 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field inode_a_flds[]; extern const struct field inode_core_flds[]; extern const struct field inode_v3_flds[]; extern const struct field inode_flds[]; extern const struct field inode_crc_flds[]; extern const struct field inode_hfld[]; extern const struct field inode_crc_hfld[]; extern const struct field inode_u_flds[]; extern const struct field timestamp_flds[]; extern int fp_dinode_fmt(void *obj, int bit, int count, char *fmtstr, int size, int arg, int base, int array); extern int inode_a_size(void *obj, int startoff, int idx); extern void inode_init(void); extern typnm_t inode_next_type(void); extern int inode_size(void *obj, int startoff, int idx); extern int inode_u_size(void *obj, int startoff, int idx); extern void set_cur_inode(xfs_ino_t ino); xfsprogs-4.9.0+nmu1ubuntu2/db/input.c0000644000000000000000000001346713063067170014374 0ustar /* * Copyright (c) 2000-2003 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include "command.h" #include "input.h" #include "output.h" #include "sig.h" #include "malloc.h" #include "init.h" #if defined(ENABLE_READLINE) # include # include #elif defined(ENABLE_EDITLINE) # include #endif int inputstacksize; FILE **inputstack; FILE *curinput; static void popfile(void); static int source_f(int argc, char **argv); static const cmdinfo_t source_cmd = { "source", NULL, source_f, 1, 1, 0, N_("source-file"), N_("get commands from source-file"), NULL }; /* our homegrown strtok that understands strings */ static char * tokenize( char *inp) { static char *last_place = NULL; char *start; char *walk; int in_string = 0; int in_escape = 0; if (inp) { start = inp; } else { if (last_place == NULL) return NULL; /* we're done */ if (*last_place != '\0') return NULL; start = last_place + 1; } last_place = NULL; /* eat whitespace */ while (*start == ' ' || *start == '\t') start++; walk = start; for (;*walk != '\0'; walk++) { if (in_escape) { in_escape = 0; continue; } if (*walk == '\\') in_escape = 1; else if (*walk == '\"') in_string ^= 1; if (!in_string && !in_escape && (*walk == ' ' || *walk == '\t')) { last_place = walk; *last_place = '\0'; break; } } if (walk == start) return NULL; return start; } char ** breakline( char *input, int *count) { int c; char *inp; char *p; char **rval; c = 0; inp = input; rval = xcalloc(sizeof(char *), 1); for (;;) { p = tokenize(inp); if (p == NULL) break; inp = NULL; c++; rval = xrealloc(rval, sizeof(*rval) * (c + 1)); rval[c - 1] = p; rval[c] = NULL; } *count = c; return rval; } void doneline( char *input, char **vec) { xfree(input); xfree(vec); } static char * get_prompt(void) { static char prompt[FILENAME_MAX + 1]; if (!prompt[0]) snprintf(prompt, sizeof(prompt), "%s> ", progname); return prompt; } static char * fetchline_internal(void) { char buf[1024]; int iscont; size_t len; size_t rlen; char *rval; rval = NULL; for (rlen = iscont = 0; ; ) { if (inputstacksize == 1) { if (iscont) dbprintf("... "); else dbprintf(get_prompt(), progname); fflush(stdin); } if (seenint() || (!fgets(buf, sizeof(buf), curinput) && ferror(curinput) && seenint())) { clearint(); dbprintf("^C\n"); clearerr(curinput); if (iscont) { iscont = 0; rlen = 0; if (rval) { xfree(rval); rval = NULL; } } continue; } if (ferror(curinput) || feof(curinput) || (len = strlen(buf)) == 0) { popfile(); if (curinput == NULL) { dbprintf("\n"); return NULL; } iscont = 0; rlen = 0; if (rval) { xfree(rval); rval = NULL; } continue; } if (inputstacksize == 1) logprintf("%s", buf); rval = xrealloc(rval, rlen + len + 1); if (rlen == 0) rval[0] = '\0'; rlen += len; strcat(rval, buf); if (buf[len - 1] == '\n') { if (len > 1 && buf[len - 2] == '\\') { rval[rlen - 2] = ' '; rval[rlen - 1] = '\0'; rlen--; iscont = 1; } else { rval[rlen - 1] = '\0'; rlen--; break; } } } return rval; } #ifdef ENABLE_READLINE char * fetchline(void) { char *line; if (inputstacksize == 1) { line = readline(get_prompt()); if (line && *line) { add_history(line); logprintf("%s", line); } } else { line = fetchline_internal(); } return line; } #elif defined(ENABLE_EDITLINE) static char *el_get_prompt(EditLine *e) { return get_prompt(); } char * fetchline(void) { static EditLine *el; static History *hist; HistEvent hevent; char *line; int count; if (!el) { hist = history_init(); history(hist, &hevent, H_SETSIZE, 100); el = el_init(progname, stdin, stdout, stderr); el_source(el, NULL); el_set(el, EL_SIGNAL, 1); el_set(el, EL_PROMPT, el_get_prompt); el_set(el, EL_HIST, history, (const char *)hist); } if (inputstacksize == 1) { line = xstrdup(el_gets(el, &count)); if (line) { if (count > 0) line[count-1] = '\0'; if (*line) { history(hist, &hevent, H_ENTER, line); logprintf("%s", line); } } } else { line = fetchline_internal(); } return line; } #else char * fetchline(void) { return fetchline_internal(); } #endif static void popfile(void) { if (inputstacksize == 0) { curinput = NULL; return; } if (curinput != stdin) fclose(curinput); inputstacksize--; if (inputstacksize) { inputstack = xrealloc(inputstack, inputstacksize * sizeof(*inputstack)); curinput = inputstack[inputstacksize - 1]; } else { free(inputstack); curinput = NULL; inputstack = NULL; } } void pushfile( FILE *file) { inputstack = xrealloc(inputstack, (inputstacksize + 1) * sizeof(*inputstack)); inputstacksize++; curinput = inputstack[inputstacksize - 1] = file; } /* ARGSUSED */ static int source_f( int argc, char **argv) { FILE *f; f = fopen(argv[1], "r"); if (f == NULL) dbprintf(_("can't open %s\n"), argv[0]); else pushfile(f); return 0; } void input_init(void) { add_command(&source_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/input.h0000644000000000000000000000162713063067170014374 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern char **breakline(char *input, int *count); extern void doneline(char *input, char **vec); extern char *fetchline(void); extern void input_init(void); extern void pushfile(FILE *file); xfsprogs-4.9.0+nmu1ubuntu2/db/io.c0000644000000000000000000003402213063067170013632 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "inode.h" #include "io.h" #include "output.h" #include "init.h" #include "malloc.h" #include "crc.h" static int pop_f(int argc, char **argv); static void pop_help(void); static int push_f(int argc, char **argv); static void push_help(void); static int stack_f(int argc, char **argv); static void stack_help(void); static int forward_f(int argc, char **argv); static void forward_help(void); static int back_f(int argc, char **argv); static void back_help(void); static int ring_f(int argc, char **argv); static void ring_help(void); static const cmdinfo_t pop_cmd = { "pop", NULL, pop_f, 0, 0, 0, NULL, N_("pop location from the stack"), pop_help }; static const cmdinfo_t push_cmd = { "push", NULL, push_f, 0, 2, 0, N_("[command]"), N_("push location to the stack"), push_help }; static const cmdinfo_t stack_cmd = { "stack", NULL, stack_f, 0, 0, 0, NULL, N_("view the location stack"), stack_help }; static const cmdinfo_t forward_cmd = { "forward", "f", forward_f, 0, 0, 0, NULL, N_("move forward to next entry in the position ring"), forward_help }; static const cmdinfo_t back_cmd = { "back", "b", back_f, 0, 0, 0, NULL, N_("move to the previous location in the position ring"), back_help }; static const cmdinfo_t ring_cmd = { "ring", NULL, ring_f, 0, 1, 0, NULL, N_("show position ring or move to a specific entry"), ring_help }; iocur_t *iocur_base; iocur_t *iocur_top; int iocur_sp = -1; int iocur_len; #define RING_ENTRIES 20 static iocur_t iocur_ring[RING_ENTRIES]; static int ring_head = -1; static int ring_tail = -1; static int ring_current = -1; void io_init(void) { add_command(&pop_cmd); add_command(&push_cmd); add_command(&stack_cmd); add_command(&forward_cmd); add_command(&back_cmd); add_command(&ring_cmd); } void off_cur( int off, int len) { if (iocur_top == NULL || off + len > BBTOB(iocur_top->blen)) dbprintf(_("can't set block offset to %d\n"), off); else { iocur_top->boff = off; iocur_top->off = ((xfs_off_t)iocur_top->bb << BBSHIFT) + off; iocur_top->len = len; iocur_top->data = (void *)((char *)iocur_top->buf + off); } } void pop_cur(void) { if (iocur_sp < 0) { dbprintf(_("can't pop anything from I/O stack\n")); return; } if (iocur_top->bp) { libxfs_putbuf(iocur_top->bp); iocur_top->bp = NULL; } if (iocur_top->bbmap) { free(iocur_top->bbmap); iocur_top->bbmap = NULL; } if (--iocur_sp >= 0) { iocur_top = iocur_base + iocur_sp; cur_typ = iocur_top->typ; } else { iocur_top = iocur_base; iocur_sp = 0; } } /*ARGSUSED*/ static int pop_f( int argc, char **argv) { pop_cur(); return 0; } static void pop_help(void) { dbprintf(_( "\n" " Changes the address and data type to the first entry on the stack.\n" "\n" )); } void print_iocur( char *tag, iocur_t *ioc) { int i; dbprintf("%s\n", tag); dbprintf(_("\tbyte offset %lld, length %d\n"), ioc->off, ioc->len); dbprintf(_("\tbuffer block %lld (fsbno %lld), %d bb%s\n"), ioc->bb, (xfs_fsblock_t)XFS_DADDR_TO_FSB(mp, ioc->bb), ioc->blen, ioc->blen == 1 ? "" : "s"); if (ioc->bbmap) { dbprintf(_("\tblock map")); for (i = 0; i < ioc->bbmap->nmaps; i++) dbprintf(" %lld:%d", ioc->bbmap->b[i].bm_bn, ioc->bbmap->b[i].bm_len); dbprintf("\n"); } dbprintf(_("\tinode %lld, dir inode %lld, type %s\n"), ioc->ino, ioc->dirino, ioc->typ == NULL ? _("none") : ioc->typ->name); } void print_ring(void) { int i; iocur_t *ioc; if (ring_current == -1) { dbprintf(_("no entries in location ring.\n")); return; } dbprintf(_(" type bblock bblen fsbno inode\n")); i = ring_head; for (;;) { ioc = &iocur_ring[i]; if (i == ring_current) printf("*%2d: ", i); else printf(" %2d: ", i); dbprintf("%-7.7s %8lld %5d %8lld %9lld\n", ioc->typ == NULL ? "none" : ioc->typ->name, ioc->bb, ioc->blen, (xfs_fsblock_t)XFS_DADDR_TO_FSB(mp, ioc->bb), ioc->ino ); if (i == ring_tail) break; i = (i+(RING_ENTRIES-1))%RING_ENTRIES; } } void push_cur(void) { if (iocur_sp + 1 >= iocur_len) { iocur_base = xrealloc(iocur_base, sizeof(*iocur_base) * (iocur_len + 1)); iocur_len++; } iocur_sp++; iocur_top = iocur_base + iocur_sp; memset(iocur_top, 0, sizeof(*iocur_base)); iocur_top->ino = iocur_sp > 0 ? iocur_top[-1].ino : NULLFSINO; iocur_top->dirino = iocur_sp > 0 ? iocur_top[-1].dirino : NULLFSINO; iocur_top->mode = iocur_sp > 0 ? iocur_top[-1].mode : 0; cur_typ = NULL; } static int push_f( int argc, char **argv) { const cmdinfo_t *ct; if (argc > 1) { /* check we can execute command */ ct = find_command(argv[1]); if (ct == NULL) { dbprintf(_("no such command %s\n"), argv[1]); return 0; } if (!ct->canpush) { dbprintf(_("no push form allowed for %s\n"), argv[1]); return 0; } } /* save current state */ push_cur(); if (iocur_top[-1].typ && iocur_top[-1].typ->typnm == TYP_INODE) set_cur_inode(iocur_top[-1].ino); else set_cur(iocur_top[-1].typ, iocur_top[-1].bb, iocur_top[-1].blen, DB_RING_IGN, iocur_top[-1].bbmap); /* run requested command */ if (argc>1) (void)command(argc-1, argv+1); return 0; } static void push_help(void) { dbprintf(_( "\n" " Allows you to push the current address and data type on the stack for\n" " later return. 'push' also accepts an additional command to execute after\n" " storing the current address (ex: 'push a rootino' from the superblock).\n" "\n" )); } /* move forward through the ring */ /* ARGSUSED */ static int forward_f( int argc, char **argv) { if (ring_current == -1) { dbprintf(_("ring is empty\n")); return 0; } if (ring_current == ring_head) { dbprintf(_("no further entries\n")); return 0; } ring_current = (ring_current+1)%RING_ENTRIES; set_cur(iocur_ring[ring_current].typ, iocur_ring[ring_current].bb, iocur_ring[ring_current].blen, DB_RING_IGN, iocur_ring[ring_current].bbmap); return 0; } static void forward_help(void) { dbprintf(_( "\n" " The 'forward' ('f') command moves to the next location in the position\n" " ring, updating the current position and data type. If the current location\n" " is the top entry in the ring, then the 'forward' command will have\n" " no effect.\n" "\n" )); } /* move backwards through the ring */ /* ARGSUSED */ static int back_f( int argc, char **argv) { if (ring_current == -1) { dbprintf(_("ring is empty\n")); return 0; } if (ring_current == ring_tail) { dbprintf(_("no previous entries\n")); return 0; } ring_current = (ring_current+(RING_ENTRIES-1))%RING_ENTRIES; set_cur(iocur_ring[ring_current].typ, iocur_ring[ring_current].bb, iocur_ring[ring_current].blen, DB_RING_IGN, iocur_ring[ring_current].bbmap); return 0; } static void back_help(void) { dbprintf(_( "\n" " The 'back' ('b') command moves to the previous location in the position\n" " ring, updating the current position and data type. If the current location\n" " is the last entry in the ring, then the 'back' command will have no effect.\n" "\n" )); } /* show or go to specific point in ring */ static int ring_f( int argc, char **argv) { int index; if (argc == 1) { print_ring(); return 0; } index = (int)strtoul(argv[1], NULL, 0); if (index < 0 || index >= RING_ENTRIES) { dbprintf(_("invalid entry: %d\n"), index); return 0; } ring_current = index; set_cur(iocur_ring[index].typ, iocur_ring[index].bb, iocur_ring[index].blen, DB_RING_IGN, iocur_ring[index].bbmap); return 0; } static void ring_help(void) { dbprintf(_( "\n" " The position ring automatically keeps track of each disk location and\n" " structure type for each change of position you make during your xfs_db\n" " session. The last %d most recent entries are kept in the ring.\n" "\n" " To display the current list of ring entries type 'ring' by itself on\n" " the command line. The entry highlighted by an asterisk ('*') is the\n" " current entry.\n" "\n" " To move to another entry in the ring type 'ring ' where is\n" " your desired entry from the ring position list.\n" "\n" " You may also use the 'forward' ('f') or 'back' ('b') commands to move\n" " to the previous or next entry in the ring, respectively.\n" "\n" " Note: Unlike the 'stack', 'push' and 'pop' commands, the ring tracks your\n" " location implicitly. Use the 'push' and 'pop' commands if you wish to\n" " store a specific location explicitly for later return.\n" "\n"), RING_ENTRIES); } void ring_add(void) { if (ring_head == -1) { /* only get here right after startup */ ring_head = 0; ring_tail = 0; ring_current = 0; iocur_ring[0] = *iocur_top; } else { if (ring_current == ring_head) { ring_head = (ring_head+1)%RING_ENTRIES; iocur_ring[ring_head] = *iocur_top; if (ring_head == ring_tail) ring_tail = (ring_tail+1)%RING_ENTRIES; ring_current = ring_head; } else { ring_current = (ring_current+1)%RING_ENTRIES; iocur_ring[ring_current] = *iocur_top; } } } static void write_cur_buf(void) { int ret; ret = -libxfs_writebufr(iocur_top->bp); if (ret != 0) dbprintf(_("write error: %s\n"), strerror(ret)); /* re-read buffer from disk */ ret = -libxfs_readbufr(mp->m_ddev_targp, iocur_top->bb, iocur_top->bp, iocur_top->blen, 0); if (ret != 0) dbprintf(_("read error: %s\n"), strerror(ret)); } static void write_cur_bbs(void) { int ret; ret = -libxfs_writebufr(iocur_top->bp); if (ret != 0) dbprintf(_("write error: %s\n"), strerror(ret)); /* re-read buffer from disk */ ret = -libxfs_readbufr_map(mp->m_ddev_targp, iocur_top->bp, 0); if (ret != 0) dbprintf(_("read error: %s\n"), strerror(ret)); } void xfs_dummy_verify( struct xfs_buf *bp) { return; } void xfs_verify_recalc_crc( struct xfs_buf *bp) { xfs_buf_update_cksum(bp, iocur_top->typ->crc_off); } void write_cur(void) { bool skip_crc = false; if (iocur_sp < 0) { dbprintf(_("nothing to write\n")); return; } if (!xfs_sb_version_hascrc(&mp->m_sb) || !iocur_top->bp->b_ops || iocur_top->bp->b_ops->verify_write == xfs_dummy_verify) skip_crc = true; if (!skip_crc) { if (iocur_top->ino_buf) { libxfs_dinode_calc_crc(mp, iocur_top->data); iocur_top->ino_crc_ok = 1; } else if (iocur_top->dquot_buf) { xfs_update_cksum(iocur_top->data, sizeof(struct xfs_dqblk), XFS_DQUOT_CRC_OFF); } } if (iocur_top->bbmap) write_cur_bbs(); else write_cur_buf(); /* If we didn't write the crc automatically, re-check inode validity */ if (xfs_sb_version_hascrc(&mp->m_sb) && skip_crc && iocur_top->ino_buf) { iocur_top->ino_crc_ok = xfs_verify_cksum(iocur_top->data, mp->m_sb.sb_inodesize, XFS_DINODE_CRC_OFF); } } void set_cur( const typ_t *t, __int64_t d, int c, int ring_flag, bbmap_t *bbmap) { struct xfs_buf *bp; xfs_ino_t dirino; xfs_ino_t ino; __uint16_t mode; const struct xfs_buf_ops *ops = t ? t->bops : NULL; if (iocur_sp < 0) { dbprintf(_("set_cur no stack element to set\n")); return; } ino = iocur_top->ino; dirino = iocur_top->dirino; mode = iocur_top->mode; pop_cur(); push_cur(); if (bbmap) { #ifdef DEBUG_BBMAP int i; printf(_("xfs_db got a bbmap for %lld\n"), (long long)d); printf(_("\tblock map")); for (i = 0; i < bbmap->nmaps; i++) printf(" %lld:%d", (long long)bbmap->b[i].bm_bn, bbmap->b[i].bm_len); printf("\n"); #endif iocur_top->bbmap = malloc(sizeof(struct bbmap)); if (!iocur_top->bbmap) return; memcpy(iocur_top->bbmap, bbmap, sizeof(struct bbmap)); bp = libxfs_readbuf_map(mp->m_ddev_targp, bbmap->b, bbmap->nmaps, 0, ops); } else { bp = libxfs_readbuf(mp->m_ddev_targp, d, c, 0, ops); iocur_top->bbmap = NULL; } /* * Keep the buffer even if the verifier says it is corrupted. * We're a diagnostic tool, after all. */ if (!bp || (bp->b_error && bp->b_error != -EFSCORRUPTED && bp->b_error != -EFSBADCRC)) return; iocur_top->buf = bp->b_addr; iocur_top->bp = bp; if (!ops) bp->b_flags |= LIBXFS_B_UNCHECKED; iocur_top->bb = d; iocur_top->blen = c; iocur_top->boff = 0; iocur_top->data = iocur_top->buf; iocur_top->len = BBTOB(c); iocur_top->off = d << BBSHIFT; iocur_top->typ = cur_typ = t; iocur_top->ino = ino; iocur_top->dirino = dirino; iocur_top->mode = mode; iocur_top->ino_buf = 0; iocur_top->dquot_buf = 0; /* store location in ring */ if (ring_flag) ring_add(); } void set_iocur_type( const typ_t *t) { struct xfs_buf *bp = iocur_top->bp; iocur_top->typ = t; /* verify the buffer if the type has one. */ if (!bp) return; if (!t->bops) { bp->b_ops = NULL; bp->b_flags |= LIBXFS_B_UNCHECKED; return; } if (!(bp->b_flags & LIBXFS_B_UPTODATE)) return; bp->b_error = 0; bp->b_ops = t->bops; bp->b_ops->verify_read(bp); bp->b_flags &= ~LIBXFS_B_UNCHECKED; } static void stack_help(void) { dbprintf(_( "\n" " The stack is used to explicitly store your location and data type\n" " for later return. The 'push' operation stores the current address\n" " and type on the stack, the 'pop' operation returns you to the\n" " position and datatype of the top entry on the stack.\n" "\n" " The 'stack' allows explicit location saves, see 'ring' for implicit\n" " position tracking.\n" "\n" )); } /*ARGSUSED*/ static int stack_f( int argc, char **argv) { int i; char tagbuf[8]; for (i = iocur_sp; i > 0; i--) { snprintf(tagbuf, sizeof(tagbuf), "%d: ", i); print_iocur(tagbuf, &iocur_base[i]); } return 0; } xfsprogs-4.9.0+nmu1ubuntu2/db/io.h0000644000000000000000000000533113063067167013646 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ struct typ; #define BBMAP_SIZE (XFS_MAX_BLOCKSIZE / BBSIZE) typedef struct bbmap { int nmaps; struct xfs_buf_map b[BBMAP_SIZE]; } bbmap_t; typedef struct iocur { __int64_t bb; /* BB number in filesystem of buf */ int blen; /* length of "buf", bb's */ int boff; /* data - buf */ void *buf; /* base address of buffer */ void *data; /* current interesting data */ xfs_ino_t dirino; /* current directory inode number */ xfs_ino_t ino; /* current inode number */ int len; /* length of "data", bytes */ __uint16_t mode; /* current inode's mode */ xfs_off_t off; /* fs offset of "data" in bytes */ const struct typ *typ; /* type of "data" */ bbmap_t *bbmap; /* map daddr if fragmented */ struct xfs_buf *bp; /* underlying buffer */ int ino_crc_ok:1; int ino_buf:1; int dquot_buf:1; int need_crc:1; } iocur_t; #define DB_RING_ADD 1 /* add to ring on set_cur */ #define DB_RING_IGN 0 /* do not add to ring on set_cur */ extern iocur_t *iocur_base; /* base of stack */ extern iocur_t *iocur_top; /* top element of stack */ extern int iocur_sp; /* current top of stack */ extern int iocur_len; /* length of stack array */ extern void io_init(void); extern void off_cur(int off, int len); extern void pop_cur(void); extern void print_iocur(char *tag, iocur_t *ioc); extern void push_cur(void); extern int read_buf(__int64_t daddr, int count, void *bufp); extern void write_cur(void); extern void set_cur(const struct typ *t, __int64_t d, int c, int ring_add, bbmap_t *bbmap); extern void ring_add(void); extern void set_iocur_type(const struct typ *t); extern void xfs_dummy_verify(struct xfs_buf *bp); extern void xfs_verify_recalc_crc(struct xfs_buf *bp); /* * returns -1 for unchecked, 0 for bad and 1 for good */ static inline int iocur_crc_valid() { if (!iocur_top->bp) return -1; if (iocur_top->bp->b_flags & LIBXFS_B_UNCHECKED) return -1; return (iocur_top->bp->b_error != -EFSBADCRC && (!iocur_top->ino_buf || iocur_top->ino_crc_ok)); } xfsprogs-4.9.0+nmu1ubuntu2/db/logformat.c0000644000000000000000000000734013033541503015212 0ustar /* * Copyright (c) 2015 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "init.h" #include "output.h" #include "libxlog.h" #define MAX_LSUNIT 256 * 1024 /* max log buf. size */ static int logformat_f(int argc, char **argv) { xfs_daddr_t head_blk; xfs_daddr_t tail_blk; int logversion; int lsunit = -1; int cycle = -1; int error; int c; logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1; while ((c = getopt(argc, argv, "c:s:")) != EOF) { switch (c) { case 'c': cycle = strtol(optarg, NULL, 0); if (cycle == 0) { dbprintf("invalid cycle\n"); return -1; } break; case 's': lsunit = strtol(optarg, NULL, 0); /* * The log stripe unit must be block aligned and no * larger than 256k. */ if (lsunit > 1 && (lsunit % mp->m_sb.sb_blocksize || (logversion == 2 && lsunit > MAX_LSUNIT))) { dbprintf("invalid log stripe unit\n"); return -1; } break; default: dbprintf("invalid option\n"); return -1; } } /* * Check whether the log is dirty. This also determines the current log * cycle if we have to use it by default below. */ memset(mp->m_log, 0, sizeof(struct xlog)); mp->m_log->l_mp = mp; mp->m_log->l_dev = mp->m_logdev_targp; mp->m_log->l_logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); mp->m_log->l_logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); mp->m_log->l_sectBBsize = BBSIZE; if (xfs_sb_version_hassector(&mp->m_sb)) mp->m_log->l_sectBBsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT); mp->m_log->l_sectBBsize = BTOBB(mp->m_log->l_sectBBsize); error = xlog_find_tail(mp->m_log, &head_blk, &tail_blk); if (error) { dbprintf("could not find log head/tail\n"); return -1; } if (head_blk != tail_blk) { dbprintf(_( "The log is dirty. Please mount to replay the log.\n")); return -1; } /* * Use the current cycle and/or log stripe unit if either is not * provided by the user. */ if (cycle < 0) cycle = mp->m_log->l_curr_cycle; if (lsunit < 0) lsunit = mp->m_sb.sb_logsunit; dbprintf("Formatting the log to cycle %d, stripe unit %d bytes.\n", cycle, lsunit); error = -libxfs_log_clear(mp->m_logdev_targp, NULL, mp->m_log->l_logBBstart, mp->m_log->l_logBBsize, &mp->m_sb.sb_uuid, logversion, lsunit, XLOG_FMT, cycle, false); if (error) { dbprintf("error formatting log - %d\n", error); return error; } return 0; } static void logformat_help(void) { dbprintf(_( "\n" " The 'logformat' command reformats (clears) the log to the specified log\n" " cycle and log stripe unit. If the log cycle is not specified, the log is\n" " reformatted to the current cycle. If the log stripe unit is not specified,\n" " the stripe unit from the filesystem superblock is used.\n" "\n" )); } static const struct cmdinfo logformat_cmd = { .name = "logformat", .altname = NULL, .cfunc = logformat_f, .argmin = 0, .argmax = 4, .canpush = 0, .args = N_("[-c cycle] [-s sunit]"), .oneline = N_("reformat the log"), .help = logformat_help, }; void logformat_init(void) { if (!expert_mode) return; add_command(&logformat_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/logformat.h0000644000000000000000000000134013033541503015211 0ustar /* * Copyright (c) 2015 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ void logformat_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/malloc.c0000644000000000000000000000277013063067170014477 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "init.h" #include "malloc.h" #include "output.h" static void badmalloc(void) { dbprintf(_("%s: out of memory\n"), progname); exit(4); } void * xcalloc( size_t nelem, size_t elsize) { void *ptr; ptr = calloc(nelem, elsize); if (ptr) return ptr; badmalloc(); /* NOTREACHED */ return NULL; } void xfree( void *ptr) { free(ptr); } void * xmalloc( size_t size) { void *ptr; ptr = valloc(size); if (ptr) return ptr; badmalloc(); /* NOTREACHED */ return NULL; } void * xrealloc( void *ptr, size_t size) { ptr = realloc(ptr, size); if (ptr || !size) return ptr; badmalloc(); /* NOTREACHED */ return NULL; } char * xstrdup( const char *s1) { char *s; s = strdup(s1); if (s) return s; badmalloc(); /* NOTREACHED */ return NULL; } xfsprogs-4.9.0+nmu1ubuntu2/db/malloc.h0000644000000000000000000000164113063067167014506 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void *xcalloc(size_t nelem, size_t elsize); extern void xfree(void *ptr); extern void *xmalloc(size_t size); extern void *xrealloc(void *ptr, size_t size); extern char *xstrdup(const char *s1); xfsprogs-4.9.0+nmu1ubuntu2/db/metadump.c0000644000000000000000000021721413063067170015045 0ustar /* * Copyright (c) 2007, 2011 SGI * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "bmap.h" #include "command.h" #include "metadump.h" #include "io.h" #include "output.h" #include "type.h" #include "init.h" #include "sig.h" #include "xfs_metadump.h" #include "fprint.h" #include "faddr.h" #include "field.h" #include "dir2.h" #define DEFAULT_MAX_EXT_SIZE 1000 /* * It's possible that multiple files in a directory (or attributes * in a file) produce the same obfuscated name. If that happens, we * try to create another one. After several rounds of this though, * we just give up and leave the original name as-is. */ #define DUP_MAX 5 /* Max duplicates before we give up */ /* copy all metadata structures to/from a file */ static int metadump_f(int argc, char **argv); static void metadump_help(void); /* * metadump commands issue info/wornings/errors to standard error as * metadump supports stdout as a destination. * * All static functions return zero on failure, while the public functions * return zero on success. */ static const cmdinfo_t metadump_cmd = { "metadump", NULL, metadump_f, 0, -1, 0, N_("[-a] [-e] [-g] [-m max_extent] [-w] [-o] filename"), N_("dump metadata to a file"), metadump_help }; static FILE *outf; /* metadump file */ static xfs_metablock_t *metablock; /* header + index + buffers */ static __be64 *block_index; static char *block_buffer; static int num_indices; static int cur_index; static xfs_ino_t cur_ino; static int show_progress = 0; static int stop_on_read_error = 0; static int max_extent_size = DEFAULT_MAX_EXT_SIZE; static int obfuscate = 1; static int zero_stale_data = 1; static int show_warnings = 0; static int progress_since_warning = 0; void metadump_init(void) { add_command(&metadump_cmd); } static void metadump_help(void) { dbprintf(_( "\n" " The 'metadump' command dumps the known metadata to a compact file suitable\n" " for compressing and sending to an XFS maintainer for corruption analysis \n" " or xfs_repair failures.\n\n" " Options:\n" " -a -- Copy full metadata blocks without zeroing unused space\n" " -e -- Ignore read errors and keep going\n" " -g -- Display dump progress\n" " -m -- Specify max extent size in blocks to copy (default = %d blocks)\n" " -o -- Don't obfuscate names and extended attributes\n" " -w -- Show warnings of bad metadata information\n" "\n"), DEFAULT_MAX_EXT_SIZE); } static void print_warning(const char *fmt, ...) { char buf[200]; va_list ap; if (seenint()) return; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); buf[sizeof(buf)-1] = '\0'; fprintf(stderr, "%s%s: %s\n", progress_since_warning ? "\n" : "", progname, buf); progress_since_warning = 0; } static void print_progress(const char *fmt, ...) { char buf[60]; va_list ap; FILE *f; if (seenint()) return; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); buf[sizeof(buf)-1] = '\0'; f = (outf == stdout) ? stderr : stdout; fprintf(f, "\r%-59s", buf); fflush(f); progress_since_warning = 1; } /* * A complete dump file will have a "zero" entry in the last index block, * even if the dump is exactly aligned, the last index will be full of * zeros. If the last index entry is non-zero, the dump is incomplete. * Correspondingly, the last chunk will have a count < num_indices. * * Return 0 for success, -1 for failure. */ static int write_index(void) { /* * write index block and following data blocks (streaming) */ metablock->mb_count = cpu_to_be16(cur_index); if (fwrite(metablock, (cur_index + 1) << BBSHIFT, 1, outf) != 1) { print_warning("error writing to file: %s", strerror(errno)); return -errno; } memset(block_index, 0, num_indices * sizeof(__be64)); cur_index = 0; return 0; } /* * Return 0 for success, -errno for failure. */ static int write_buf_segment( char *data, __int64_t off, int len) { int i; int ret; for (i = 0; i < len; i++, off++, data += BBSIZE) { block_index[cur_index] = cpu_to_be64(off); memcpy(&block_buffer[cur_index << BBSHIFT], data, BBSIZE); if (++cur_index == num_indices) { ret = write_index(); if (ret) return -EIO; } } return 0; } /* * we want to preserve the state of the metadata in the dump - whether it is * intact or corrupt, so even if the buffer has a verifier attached to it we * don't want to run it prior to writing the buffer to the metadump image. * * The only reason for running the verifier is to recalculate the CRCs on a * buffer that has been obfuscated. i.e. a buffer than metadump modified itself. * In this case, we only run the verifier if the buffer was not corrupt to begin * with so that we don't accidentally correct buffers with CRC or errors in them * when we are obfuscating them. */ static int write_buf( iocur_t *buf) { struct xfs_buf *bp = buf->bp; int i; int ret; /* * Run the write verifier to recalculate the buffer CRCs and check * metadump didn't introduce a new corruption. Warn if the verifier * failed, but still continue to dump it into the output file. */ if (buf->need_crc && bp && bp->b_ops && !bp->b_error) { bp->b_ops->verify_write(bp); if (bp->b_error) { print_warning( "obfuscation corrupted block at %s bno 0x%llx/0x%x", bp->b_ops->name, (long long)bp->b_bn, bp->b_bcount); } } /* handle discontiguous buffers */ if (!buf->bbmap) { ret = write_buf_segment(buf->data, buf->bb, buf->blen); if (ret) return ret; } else { int len = 0; for (i = 0; i < buf->bbmap->nmaps; i++) { ret = write_buf_segment(buf->data + BBTOB(len), buf->bbmap->b[i].bm_bn, buf->bbmap->b[i].bm_len); if (ret) return ret; len += buf->bbmap->b[i].bm_len; } } return seenint() ? -EINTR : 0; } /* * We could be processing a corrupt block, so we can't trust any of * the offsets or lengths to be within the buffer range. Hence check * carefully! */ static void zero_btree_node( struct xfs_btree_block *block, typnm_t btype) { int nrecs; xfs_bmbt_ptr_t *bpp; xfs_bmbt_key_t *bkp; xfs_inobt_ptr_t *ipp; xfs_inobt_key_t *ikp; xfs_alloc_ptr_t *app; xfs_alloc_key_t *akp; char *zp1, *zp2; char *key_end; nrecs = be16_to_cpu(block->bb_numrecs); if (nrecs < 0) return; switch (btype) { case TYP_BMAPBTA: case TYP_BMAPBTD: if (nrecs > mp->m_bmap_dmxr[1]) return; bkp = XFS_BMBT_KEY_ADDR(mp, block, 1); bpp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); zp1 = (char *)&bkp[nrecs]; zp2 = (char *)&bpp[nrecs]; key_end = (char *)bpp; break; case TYP_INOBT: case TYP_FINOBT: if (nrecs > mp->m_inobt_mxr[1]) return; ikp = XFS_INOBT_KEY_ADDR(mp, block, 1); ipp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]); zp1 = (char *)&ikp[nrecs]; zp2 = (char *)&ipp[nrecs]; key_end = (char *)ipp; break; case TYP_BNOBT: case TYP_CNTBT: if (nrecs > mp->m_alloc_mxr[1]) return; akp = XFS_ALLOC_KEY_ADDR(mp, block, 1); app = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); zp1 = (char *)&akp[nrecs]; zp2 = (char *)&app[nrecs]; key_end = (char *)app; break; default: return; } /* Zero from end of keys to beginning of pointers */ memset(zp1, 0, key_end - zp1); /* Zero from end of pointers to end of block */ memset(zp2, 0, (char *)block + mp->m_sb.sb_blocksize - zp2); } /* * We could be processing a corrupt block, so we can't trust any of * the offsets or lengths to be within the buffer range. Hence check * carefully! */ static void zero_btree_leaf( struct xfs_btree_block *block, typnm_t btype) { int nrecs; struct xfs_bmbt_rec *brp; struct xfs_inobt_rec *irp; struct xfs_alloc_rec *arp; char *zp; nrecs = be16_to_cpu(block->bb_numrecs); if (nrecs < 0) return; switch (btype) { case TYP_BMAPBTA: case TYP_BMAPBTD: if (nrecs > mp->m_bmap_dmxr[0]) return; brp = XFS_BMBT_REC_ADDR(mp, block, 1); zp = (char *)&brp[nrecs]; break; case TYP_INOBT: case TYP_FINOBT: if (nrecs > mp->m_inobt_mxr[0]) return; irp = XFS_INOBT_REC_ADDR(mp, block, 1); zp = (char *)&irp[nrecs]; break; case TYP_BNOBT: case TYP_CNTBT: if (nrecs > mp->m_alloc_mxr[0]) return; arp = XFS_ALLOC_REC_ADDR(mp, block, 1); zp = (char *)&arp[nrecs]; break; default: return; } /* Zero from end of records to end of block */ memset(zp, 0, (char *)block + mp->m_sb.sb_blocksize - zp); } static void zero_btree_block( struct xfs_btree_block *block, typnm_t btype) { int level; level = be16_to_cpu(block->bb_level); if (level > 0) zero_btree_node(block, btype); else zero_btree_leaf(block, btype); } static int scan_btree( xfs_agnumber_t agno, xfs_agblock_t agbno, int level, typnm_t btype, void *arg, int (*func)(struct xfs_btree_block *block, xfs_agnumber_t agno, xfs_agblock_t agbno, int level, typnm_t btype, void *arg)) { int rval = 0; push_cur(); set_cur(&typtab[btype], XFS_AGB_TO_DADDR(mp, agno, agbno), blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { print_warning("cannot read %s block %u/%u", typtab[btype].name, agno, agbno); rval = !stop_on_read_error; goto pop_out; } if (zero_stale_data) { zero_btree_block(iocur_top->data, btype); iocur_top->need_crc = 1; } if (write_buf(iocur_top)) goto pop_out; if (!(*func)(iocur_top->data, agno, agbno, level - 1, btype, arg)) goto pop_out; rval = 1; pop_out: pop_cur(); return rval; } /* free space tree copy routines */ static int valid_bno( xfs_agnumber_t agno, xfs_agblock_t agbno) { if (agno < (mp->m_sb.sb_agcount - 1) && agbno > 0 && agbno <= mp->m_sb.sb_agblocks) return 1; if (agno == (mp->m_sb.sb_agcount - 1) && agbno > 0 && agbno <= (mp->m_sb.sb_dblocks - (xfs_rfsblock_t)(mp->m_sb.sb_agcount - 1) * mp->m_sb.sb_agblocks)) return 1; return 0; } static int scanfunc_freesp( struct xfs_btree_block *block, xfs_agnumber_t agno, xfs_agblock_t agbno, int level, typnm_t btype, void *arg) { xfs_alloc_ptr_t *pp; int i; int numrecs; if (level == 0) return 1; numrecs = be16_to_cpu(block->bb_numrecs); if (numrecs > mp->m_alloc_mxr[1]) { if (show_warnings) print_warning("invalid numrecs (%u) in %s block %u/%u", numrecs, typtab[btype].name, agno, agbno); return 1; } pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); for (i = 0; i < numrecs; i++) { if (!valid_bno(agno, be32_to_cpu(pp[i]))) { if (show_warnings) print_warning("invalid block number (%u/%u) " "in %s block %u/%u", agno, be32_to_cpu(pp[i]), typtab[btype].name, agno, agbno); continue; } if (!scan_btree(agno, be32_to_cpu(pp[i]), level, btype, arg, scanfunc_freesp)) return 0; } return 1; } static int copy_free_bno_btree( xfs_agnumber_t agno, xfs_agf_t *agf) { xfs_agblock_t root; int levels; root = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]); levels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); /* validate root and levels before processing the tree */ if (root == 0 || root > mp->m_sb.sb_agblocks) { if (show_warnings) print_warning("invalid block number (%u) in bnobt " "root in agf %u", root, agno); return 1; } if (levels >= XFS_BTREE_MAXLEVELS) { if (show_warnings) print_warning("invalid level (%u) in bnobt root " "in agf %u", levels, agno); return 1; } return scan_btree(agno, root, levels, TYP_BNOBT, agf, scanfunc_freesp); } static int copy_free_cnt_btree( xfs_agnumber_t agno, xfs_agf_t *agf) { xfs_agblock_t root; int levels; root = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]); levels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); /* validate root and levels before processing the tree */ if (root == 0 || root > mp->m_sb.sb_agblocks) { if (show_warnings) print_warning("invalid block number (%u) in cntbt " "root in agf %u", root, agno); return 1; } if (levels >= XFS_BTREE_MAXLEVELS) { if (show_warnings) print_warning("invalid level (%u) in cntbt root " "in agf %u", levels, agno); return 1; } return scan_btree(agno, root, levels, TYP_CNTBT, agf, scanfunc_freesp); } static int scanfunc_rmapbt( struct xfs_btree_block *block, xfs_agnumber_t agno, xfs_agblock_t agbno, int level, typnm_t btype, void *arg) { xfs_rmap_ptr_t *pp; int i; int numrecs; if (level == 0) return 1; numrecs = be16_to_cpu(block->bb_numrecs); if (numrecs > mp->m_rmap_mxr[1]) { if (show_warnings) print_warning("invalid numrecs (%u) in %s block %u/%u", numrecs, typtab[btype].name, agno, agbno); return 1; } pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]); for (i = 0; i < numrecs; i++) { if (!valid_bno(agno, be32_to_cpu(pp[i]))) { if (show_warnings) print_warning("invalid block number (%u/%u) " "in %s block %u/%u", agno, be32_to_cpu(pp[i]), typtab[btype].name, agno, agbno); continue; } if (!scan_btree(agno, be32_to_cpu(pp[i]), level, btype, arg, scanfunc_rmapbt)) return 0; } return 1; } static int copy_rmap_btree( xfs_agnumber_t agno, struct xfs_agf *agf) { xfs_agblock_t root; int levels; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 1; root = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); levels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); /* validate root and levels before processing the tree */ if (root == 0 || root > mp->m_sb.sb_agblocks) { if (show_warnings) print_warning("invalid block number (%u) in rmapbt " "root in agf %u", root, agno); return 1; } if (levels >= XFS_BTREE_MAXLEVELS) { if (show_warnings) print_warning("invalid level (%u) in rmapbt root " "in agf %u", levels, agno); return 1; } return scan_btree(agno, root, levels, TYP_RMAPBT, agf, scanfunc_rmapbt); } static int scanfunc_refcntbt( struct xfs_btree_block *block, xfs_agnumber_t agno, xfs_agblock_t agbno, int level, typnm_t btype, void *arg) { xfs_refcount_ptr_t *pp; int i; int numrecs; if (level == 0) return 1; numrecs = be16_to_cpu(block->bb_numrecs); if (numrecs > mp->m_refc_mxr[1]) { if (show_warnings) print_warning("invalid numrecs (%u) in %s block %u/%u", numrecs, typtab[btype].name, agno, agbno); return 1; } pp = XFS_REFCOUNT_PTR_ADDR(block, 1, mp->m_refc_mxr[1]); for (i = 0; i < numrecs; i++) { if (!valid_bno(agno, be32_to_cpu(pp[i]))) { if (show_warnings) print_warning("invalid block number (%u/%u) " "in %s block %u/%u", agno, be32_to_cpu(pp[i]), typtab[btype].name, agno, agbno); continue; } if (!scan_btree(agno, be32_to_cpu(pp[i]), level, btype, arg, scanfunc_refcntbt)) return 0; } return 1; } static int copy_refcount_btree( xfs_agnumber_t agno, struct xfs_agf *agf) { xfs_agblock_t root; int levels; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 1; root = be32_to_cpu(agf->agf_refcount_root); levels = be32_to_cpu(agf->agf_refcount_level); /* validate root and levels before processing the tree */ if (root == 0 || root > mp->m_sb.sb_agblocks) { if (show_warnings) print_warning("invalid block number (%u) in refcntbt " "root in agf %u", root, agno); return 1; } if (levels >= XFS_BTREE_MAXLEVELS) { if (show_warnings) print_warning("invalid level (%u) in refcntbt root " "in agf %u", levels, agno); return 1; } return scan_btree(agno, root, levels, TYP_REFCBT, agf, scanfunc_refcntbt); } /* filename and extended attribute obfuscation routines */ struct name_ent { struct name_ent *next; xfs_dahash_t hash; int namelen; unsigned char name[1]; }; #define NAME_TABLE_SIZE 4096 static struct name_ent *nametable[NAME_TABLE_SIZE]; static void nametable_clear(void) { int i; struct name_ent *ent; for (i = 0; i < NAME_TABLE_SIZE; i++) { while ((ent = nametable[i])) { nametable[i] = ent->next; free(ent); } } } /* * See if the given name is already in the name table. If so, * return a pointer to its entry, otherwise return a null pointer. */ static struct name_ent * nametable_find(xfs_dahash_t hash, int namelen, unsigned char *name) { struct name_ent *ent; for (ent = nametable[hash % NAME_TABLE_SIZE]; ent; ent = ent->next) { if (ent->hash == hash && ent->namelen == namelen && !memcmp(ent->name, name, namelen)) return ent; } return NULL; } /* * Add the given name to the name table. Returns a pointer to the * name's new entry, or a null pointer if an error occurs. */ static struct name_ent * nametable_add(xfs_dahash_t hash, int namelen, unsigned char *name) { struct name_ent *ent; ent = malloc(sizeof *ent + namelen); if (!ent) return NULL; ent->namelen = namelen; memcpy(ent->name, name, namelen); ent->hash = hash; ent->next = nametable[hash % NAME_TABLE_SIZE]; nametable[hash % NAME_TABLE_SIZE] = ent; return ent; } #define is_invalid_char(c) ((c) == '/' || (c) == '\0') #define rol32(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) static inline unsigned char random_filename_char(void) { static unsigned char filename_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789-_"; return filename_alphabet[random() % (sizeof filename_alphabet - 1)]; } #define ORPHANAGE "lost+found" #define ORPHANAGE_LEN (sizeof (ORPHANAGE) - 1) static inline int is_orphanage_dir( struct xfs_mount *mp, xfs_ino_t dir_ino, size_t name_len, unsigned char *name) { return dir_ino == mp->m_sb.sb_rootino && name_len == ORPHANAGE_LEN && !memcmp(name, ORPHANAGE, ORPHANAGE_LEN); } /* * Determine whether a name is one we shouldn't obfuscate because * it's an orphan (or the "lost+found" directory itself). Note * "cur_ino" is the inode for the directory currently being * processed. * * Returns 1 if the name should NOT be obfuscated or 0 otherwise. */ static int in_lost_found( xfs_ino_t ino, int namelen, unsigned char *name) { static xfs_ino_t orphanage_ino = 0; char s[24]; /* 21 is enough (64 bits in decimal) */ int slen; /* Record the "lost+found" inode if we haven't done so already */ ASSERT(ino != 0); if (!orphanage_ino && is_orphanage_dir(mp, cur_ino, namelen, name)) orphanage_ino = ino; /* We don't obfuscate the "lost+found" directory itself */ if (ino == orphanage_ino) return 1; /* Most files aren't in "lost+found" at all */ if (cur_ino != orphanage_ino) return 0; /* * Within "lost+found", we don't obfuscate any file whose * name is the same as its inode number. Any others are * stray files and can be obfuscated. */ slen = snprintf(s, sizeof (s), "%llu", (unsigned long long) ino); return slen == namelen && !memcmp(name, s, namelen); } /* * Given a name and its hash value, massage the name in such a way * that the result is another name of equal length which shares the * same hash value. */ static void obfuscate_name( xfs_dahash_t hash, size_t name_len, unsigned char *name) { unsigned char *newp = name; int i; xfs_dahash_t new_hash = 0; unsigned char *first; unsigned char high_bit; int shift; /* * Our obfuscation algorithm requires at least 5-character * names, so don't bother if the name is too short. We * work backward from a hash value to determine the last * five bytes in a name required to produce a new name * with the same hash. */ if (name_len < 5) return; /* * The beginning of the obfuscated name can be pretty much * anything, so fill it in with random characters. * Accumulate its new hash value as we go. */ for (i = 0; i < name_len - 5; i++) { *newp = random_filename_char(); new_hash = *newp ^ rol32(new_hash, 7); newp++; } /* * Compute which five bytes need to be used at the end of * the name so the hash of the obfuscated name is the same * as the hash of the original. If any result in an invalid * character, flip a bit and arrange for a corresponding bit * in a neighboring byte to be flipped as well. For the * last byte, the "neighbor" to change is the first byte * we're computing here. */ new_hash = rol32(new_hash, 3) ^ hash; first = newp; high_bit = 0; for (shift = 28; shift >= 0; shift -= 7) { *newp = (new_hash >> shift & 0x7f) ^ high_bit; if (is_invalid_char(*newp)) { *newp ^= 1; high_bit = 0x80; } else high_bit = 0; ASSERT(!is_invalid_char(*newp)); newp++; } /* * If we flipped a bit on the last byte, we need to fix up * the matching bit in the first byte. The result will * be a valid character, because we know that first byte * has 0's in its upper four bits (it was produced by a * 28-bit right-shift of a 32-bit unsigned value). */ if (high_bit) { *first ^= 0x10; ASSERT(!is_invalid_char(*first)); } ASSERT(libxfs_da_hashname(name, name_len) == hash); } /* * Flip a bit in each of two bytes at the end of the given name. * This is used in generating a series of alternate names to be used * in the event a duplicate is found. * * The bits flipped are selected such that they both affect the same * bit in the name's computed hash value, so flipping them both will * preserve the hash. * * The following diagram aims to show the portion of a computed * hash that a given byte of a name affects. * * 31 28 24 21 14 8 7 3 0 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ * hash: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ * last-4 ->| |<-- last-2 --->| |<--- last ---->| * |<-- last-3 --->| |<-- last-1 --->| |<- last-4 * |<-- last-7 --->| |<-- last-5 --->| * |<-- last-8 --->| |<-- last-6 --->| * . . . and so on * * The last byte of the name directly affects the low-order byte of * the hash. The next-to-last affects bits 7-14, the next one back * affects bits 14-21, and so on. The effect wraps around when it * goes beyond the top of the hash (as happens for byte last-4). * * Bits that are flipped together "overlap" on the hash value. As * an example of overlap, the last two bytes both affect bit 7 in * the hash. That pair of bytes (and their overlapping bits) can be * used for this "flip bit" operation (it's the first pair tried, * actually). * * A table defines overlapping pairs--the bytes involved and bits * within them--that can be used this way. The byte offset is * relative to a starting point within the name, which will be set * to affect the bytes at the end of the name. The function is * called with a "bitseq" value which indicates which bit flip is * desired, and this translates directly into selecting which entry * in the bit_to_flip[] table to apply. * * The function returns 1 if the operation was successful. It * returns 0 if the result produced a character that's not valid in * a name (either '/' or a '\0'). Finally, it returns -1 if the bit * sequence number is beyond what is supported for a name of this * length. * * Discussion * ---------- * (Also see the discussion above find_alternate(), below.) * * In order to make this function work for any length name, the * table is ordered by increasing byte offset, so that the earliest * entries can apply to the shortest strings. This way all names * are done consistently. * * When bit flips occur, they can convert printable characters * into non-printable ones. In an effort to reduce the impact of * this, the first bit flips are chosen to affect bytes the end of * the name (and furthermore, toward the low bits of a byte). Those * bytes are often non-printable anyway because of the way they are * initially selected by obfuscate_name()). This is accomplished, * using later table entries first. * * Each row in the table doubles the number of alternates that * can be generated. A two-byte name is limited to using only * the first row, so it's possible to generate two alternates * (the original name, plus the alternate produced by flipping * the one pair of bits). In a 5-byte name, the effect of the * first byte overlaps the last by 4 its, and there are 8 bits * to flip, allowing for 256 possible alternates. * * Short names (less than 5 bytes) are never even obfuscated, so for * such names the relatively small number of alternates should never * really be a problem. * * Long names (more than 6 bytes, say) are not likely to exhaust * the number of available alternates. In fact, the table could * probably have stopped at 8 entries, on the assumption that 256 * alternates should be enough for most any situation. The entries * beyond those are present mostly for demonstration of how it could * be populated with more entries, should it ever be necessary to do * so. */ static int flip_bit( size_t name_len, unsigned char *name, uint32_t bitseq) { int index; size_t offset; unsigned char *p0, *p1; unsigned char m0, m1; struct { int byte; /* Offset from start within name */ unsigned char bit; /* Bit within that byte */ } bit_to_flip[][2] = { /* Sorted by second entry's byte */ { { 0, 0 }, { 1, 7 } }, /* Each row defines a pair */ { { 1, 0 }, { 2, 7 } }, /* of bytes and a bit within */ { { 2, 0 }, { 3, 7 } }, /* each byte. Each bit in */ { { 0, 4 }, { 4, 0 } }, /* a pair affects the same */ { { 0, 5 }, { 4, 1 } }, /* bit in the hash, so flipping */ { { 0, 6 }, { 4, 2 } }, /* both will change the name */ { { 0, 7 }, { 4, 3 } }, /* while preserving the hash. */ { { 3, 0 }, { 4, 7 } }, { { 0, 0 }, { 5, 3 } }, /* The first entry's byte offset */ { { 0, 1 }, { 5, 4 } }, /* must be less than the second. */ { { 0, 2 }, { 5, 5 } }, { { 0, 3 }, { 5, 6 } }, /* The table can be extended to */ { { 0, 4 }, { 5, 7 } }, /* an arbitrary number of entries */ { { 4, 0 }, { 5, 7 } }, /* but there's not much point. */ /* . . . */ }; /* Find the first entry *not* usable for name of this length */ for (index = 0; index < ARRAY_SIZE(bit_to_flip); index++) if (bit_to_flip[index][1].byte >= name_len) break; /* * Back up to the last usable entry. If that number is * smaller than the bit sequence number, inform the caller * that nothing this large (or larger) will work. */ if (bitseq > --index) return -1; /* * We will be switching bits at the end of name, with a * preference for affecting the last bytes first. Compute * where in the name we'll start applying the changes. */ offset = name_len - (bit_to_flip[index][1].byte + 1); index -= bitseq; /* Use later table entries first */ p0 = name + offset + bit_to_flip[index][0].byte; p1 = name + offset + bit_to_flip[index][1].byte; m0 = 1 << bit_to_flip[index][0].bit; m1 = 1 << bit_to_flip[index][1].bit; /* Only change the bytes if it produces valid characters */ if (is_invalid_char(*p0 ^ m0) || is_invalid_char(*p1 ^ m1)) return 0; *p0 ^= m0; *p1 ^= m1; return 1; } /* * This function generates a well-defined sequence of "alternate" * names for a given name. An alternate is a name having the same * length and same hash value as the original name. This is needed * because the algorithm produces only one obfuscated name to use * for a given original name, and it's possible that result matches * a name already seen. This function checks for this, and if it * occurs, finds another suitable obfuscated name to use. * * Each bit in the binary representation of the sequence number is * used to select one possible "bit flip" operation to perform on * the name. So for example: * seq = 0: selects no bits to flip * seq = 1: selects the 0th bit to flip * seq = 2: selects the 1st bit to flip * seq = 3: selects the 0th and 1st bit to flip * ... and so on. * * The flip_bit() function takes care of the details of the bit * flipping within the name. Note that the "1st bit" in this * context is a bit sequence number; i.e. it doesn't necessarily * mean bit 0x02 will be changed. * * If a valid name (one that contains no '/' or '\0' characters) is * produced by this process for the given sequence number, this * function returns 1. If the result is not valid, it returns 0. * Returns -1 if the sequence number is beyond the the maximum for * names of the given length. * * * Discussion * ---------- * The number of alternates available for a given name is dependent * on its length. A "bit flip" involves inverting two bits in * a name--the two bits being selected such that their values * affect the name's hash value in the same way. Alternates are * thus generated by inverting the value of pairs of such * "overlapping" bits in the original name. Each byte after the * first in a name adds at least one bit of overlap to work with. * (See comments above flip_bit() for more discussion on this.) * * So the number of alternates is dependent on the number of such * overlapping bits in a name. If there are N bit overlaps, there * 2^N alternates for that hash value. * * Here are the number of overlapping bits available for generating * alternates for names of specific lengths: * 1 0 (must have 2 bytes to have any overlap) * 2 1 One bit overlaps--so 2 possible alternates * 3 2 Two bits overlap--so 4 possible alternates * 4 4 Three bits overlap, so 2^3 alternates * 5 8 8 bits overlap (due to wrapping), 256 alternates * 6 18 2^18 alternates * 7 28 2^28 alternates * ... * It's clear that the number of alternates grows very quickly with * the length of the name. But note that the set of alternates * includes invalid names. And for certain (contrived) names, the * number of valid names is a fairly small fraction of the total * number of alternates. * * The main driver for this infrastructure for coming up with * alternate names is really related to names 5 (or possibly 6) * bytes in length. 5-byte obfuscated names contain no randomly- * generated bytes in them, and the chance of an obfuscated name * matching an already-seen name is too high to just ignore. This * methodical selection of alternates ensures we don't produce * duplicate names unless we have exhausted our options. */ static int find_alternate( size_t name_len, unsigned char *name, uint32_t seq) { uint32_t bitseq = 0; uint32_t bits = seq; if (!seq) return 1; /* alternate 0 is the original name */ if (name_len < 2) /* Must have 2 bytes to flip */ return -1; for (bitseq = 0; bits; bitseq++) { uint32_t mask = 1 << bitseq; int fb; if (!(bits & mask)) continue; fb = flip_bit(name_len, name, bitseq); if (fb < 1) return fb ? -1 : 0; bits ^= mask; } return 1; } /* * Look up the given name in the name table. If it is already * present, iterate through a well-defined sequence of alternate * names and attempt to use an alternate name instead. * * Returns 1 if the (possibly modified) name is not present in the * name table. Returns 0 if the name and all possible alternates * are already in the table. */ static int handle_duplicate_name(xfs_dahash_t hash, size_t name_len, unsigned char *name) { unsigned char new_name[name_len + 1]; uint32_t seq = 1; if (!nametable_find(hash, name_len, name)) return 1; /* No duplicate */ /* Name is already in use. Need to find an alternate. */ do { int found; /* Only change incoming name if we find an alternate */ do { memcpy(new_name, name, name_len); found = find_alternate(name_len, new_name, seq++); if (found < 0) return 0; /* No more to check */ } while (!found); } while (nametable_find(hash, name_len, new_name)); /* * The alternate wasn't in the table already. Pass it back * to the caller. */ memcpy(name, new_name, name_len); return 1; } static void generate_obfuscated_name( xfs_ino_t ino, int namelen, unsigned char *name) { xfs_dahash_t hash; /* * We don't obfuscate "lost+found" or any orphan files * therein. When the name table is used for extended * attributes, the inode number provided is 0, in which * case we don't need to make this check. */ if (ino && in_lost_found(ino, namelen, name)) return; /* * If the name starts with a slash, just skip over it. It * isn't included in the hash and we don't record it in the * name table. Note that the namelen value passed in does * not count the leading slash (if one is present). */ if (*name == '/') name++; /* Obfuscate the name (if possible) */ hash = libxfs_da_hashname(name, namelen); obfuscate_name(hash, namelen, name); /* * Make sure the name is not something already seen. If we * fail to find a suitable alternate, we're dealing with a * very pathological situation, and we may end up creating * a duplicate name in the metadump, so issue a warning. */ if (!handle_duplicate_name(hash, namelen, name)) { print_warning("duplicate name for inode %llu " "in dir inode %llu\n", (unsigned long long) ino, (unsigned long long) cur_ino); return; } /* Create an entry for the new name in the name table. */ if (!nametable_add(hash, namelen, name)) print_warning("unable to record name for inode %llu " "in dir inode %llu\n", (unsigned long long) ino, (unsigned long long) cur_ino); } static void process_sf_dir( xfs_dinode_t *dip) { struct xfs_dir2_sf_hdr *sfp; xfs_dir2_sf_entry_t *sfep; __uint64_t ino_dir_size; int i; sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); ino_dir_size = be64_to_cpu(dip->di_size); if (ino_dir_size > XFS_DFORK_DSIZE(dip, mp)) { ino_dir_size = XFS_DFORK_DSIZE(dip, mp); if (show_warnings) print_warning("invalid size in dir inode %llu", (long long)cur_ino); } sfep = xfs_dir2_sf_firstentry(sfp); for (i = 0; (i < sfp->count) && ((char *)sfep - (char *)sfp < ino_dir_size); i++) { /* * first check for bad name lengths. If they are bad, we * have limitations to how much can be obfuscated. */ int namelen = sfep->namelen; if (namelen == 0) { if (show_warnings) print_warning("zero length entry in dir inode " "%llu", (long long)cur_ino); if (i != sfp->count - 1) break; namelen = ino_dir_size - ((char *)&sfep->name[0] - (char *)sfp); } else if ((char *)sfep - (char *)sfp + M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen) > ino_dir_size) { if (show_warnings) print_warning("entry length in dir inode %llu " "overflows space", (long long)cur_ino); if (i != sfp->count - 1) break; namelen = ino_dir_size - ((char *)&sfep->name[0] - (char *)sfp); } if (obfuscate) generate_obfuscated_name( M_DIROPS(mp)->sf_get_ino(sfp, sfep), namelen, &sfep->name[0]); sfep = (xfs_dir2_sf_entry_t *)((char *)sfep + M_DIROPS(mp)->sf_entsize(sfp, namelen)); } /* zero stale data in rest of space in data fork, if any */ if (zero_stale_data && (ino_dir_size < XFS_DFORK_DSIZE(dip, mp))) memset(sfep, 0, XFS_DFORK_DSIZE(dip, mp) - ino_dir_size); } /* * The pathname may not be null terminated. It may be terminated by the end of * a buffer or inode literal area, and the start of the next region contains * unknown data. Therefore, when we get to the last component of the symlink, we * cannot assume that strlen() will give us the right result. Hence we need to * track the remaining pathname length and use that instead. */ static void obfuscate_path_components( char *buf, __uint64_t len) { unsigned char *comp = (unsigned char *)buf; unsigned char *end = comp + len; xfs_dahash_t hash; while (comp < end) { char *slash; int namelen; /* find slash at end of this component */ slash = strchr((char *)comp, '/'); if (!slash) { /* last (or single) component */ namelen = strnlen((char *)comp, len); hash = libxfs_da_hashname(comp, namelen); obfuscate_name(hash, namelen, comp); break; } namelen = slash - (char *)comp; /* handle leading or consecutive slashes */ if (!namelen) { comp++; len--; continue; } hash = libxfs_da_hashname(comp, namelen); obfuscate_name(hash, namelen, comp); comp += namelen + 1; len -= namelen + 1; } } static void process_sf_symlink( xfs_dinode_t *dip) { __uint64_t len; char *buf; len = be64_to_cpu(dip->di_size); if (len > XFS_DFORK_DSIZE(dip, mp)) { if (show_warnings) print_warning("invalid size (%d) in symlink inode %llu", len, (long long)cur_ino); len = XFS_DFORK_DSIZE(dip, mp); } buf = (char *)XFS_DFORK_DPTR(dip); if (obfuscate) obfuscate_path_components(buf, len); /* zero stale data in rest of space in data fork, if any */ if (zero_stale_data && len < XFS_DFORK_DSIZE(dip, mp)) memset(&buf[len], 0, XFS_DFORK_DSIZE(dip, mp) - len); } static void process_sf_attr( xfs_dinode_t *dip) { /* * with extended attributes, obfuscate the names and fill the actual * values with 'v' (to see a valid string length, as opposed to NULLs) */ xfs_attr_shortform_t *asfp; xfs_attr_sf_entry_t *asfep; int ino_attr_size; int i; asfp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); if (asfp->hdr.count == 0) return; ino_attr_size = be16_to_cpu(asfp->hdr.totsize); if (ino_attr_size > XFS_DFORK_ASIZE(dip, mp)) { ino_attr_size = XFS_DFORK_ASIZE(dip, mp); if (show_warnings) print_warning("invalid attr size in inode %llu", (long long)cur_ino); } asfep = &asfp->list[0]; for (i = 0; (i < asfp->hdr.count) && ((char *)asfep - (char *)asfp < ino_attr_size); i++) { int namelen = asfep->namelen; if (namelen == 0) { if (show_warnings) print_warning("zero length attr entry in inode " "%llu", (long long)cur_ino); break; } else if ((char *)asfep - (char *)asfp + XFS_ATTR_SF_ENTSIZE(asfep) > ino_attr_size) { if (show_warnings) print_warning("attr entry length in inode %llu " "overflows space", (long long)cur_ino); break; } if (obfuscate) { generate_obfuscated_name(0, asfep->namelen, &asfep->nameval[0]); memset(&asfep->nameval[asfep->namelen], 'v', asfep->valuelen); } asfep = (xfs_attr_sf_entry_t *)((char *)asfep + XFS_ATTR_SF_ENTSIZE(asfep)); } /* zero stale data in rest of space in attr fork, if any */ if (zero_stale_data && (ino_attr_size < XFS_DFORK_ASIZE(dip, mp))) memset(asfep, 0, XFS_DFORK_ASIZE(dip, mp) - ino_attr_size); } static void process_dir_data_block( char *block, xfs_fileoff_t offset, int is_block_format) { /* * we have to rely on the fileoffset and signature of the block to * handle it's contents. If it's invalid, leave it alone. * for multi-fsblock dir blocks, if a name crosses an extent boundary, * ignore it and continue. */ int dir_offset; char *ptr; char *endptr; int end_of_data; int wantmagic; struct xfs_dir2_data_hdr *datahdr; datahdr = (struct xfs_dir2_data_hdr *)block; if (is_block_format) { xfs_dir2_leaf_entry_t *blp; xfs_dir2_block_tail_t *btp; btp = xfs_dir2_block_tail_p(mp->m_dir_geo, datahdr); blp = xfs_dir2_block_leaf_p(btp); if ((char *)blp > (char *)btp) blp = (xfs_dir2_leaf_entry_t *)btp; end_of_data = (char *)blp - block; if (xfs_sb_version_hascrc(&mp->m_sb)) wantmagic = XFS_DIR3_BLOCK_MAGIC; else wantmagic = XFS_DIR2_BLOCK_MAGIC; } else { /* leaf/node format */ end_of_data = mp->m_dir_geo->fsbcount << mp->m_sb.sb_blocklog; if (xfs_sb_version_hascrc(&mp->m_sb)) wantmagic = XFS_DIR3_DATA_MAGIC; else wantmagic = XFS_DIR2_DATA_MAGIC; } if (be32_to_cpu(datahdr->magic) != wantmagic) { if (show_warnings) print_warning( "invalid magic in dir inode %llu block %ld", (long long)cur_ino, (long)offset); return; } dir_offset = M_DIROPS(mp)->data_entry_offset; ptr = block + dir_offset; endptr = block + mp->m_dir_geo->blksize; while (ptr < endptr && dir_offset < end_of_data) { xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; int length; dup = (xfs_dir2_data_unused_t *)ptr; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { int length = be16_to_cpu(dup->length); if (dir_offset + length > end_of_data || !length || (length & (XFS_DIR2_DATA_ALIGN - 1))) { if (show_warnings) print_warning( "invalid length for dir free space in inode %llu", (long long)cur_ino); return; } if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) != dir_offset) return; dir_offset += length; ptr += length; /* * Zero the unused space up to the tag - the tag is * actually at a variable offset, so zeroing &dup->tag * is zeroing the free space in between */ if (zero_stale_data) { int zlen = length - sizeof(xfs_dir2_data_unused_t); if (zlen > 0) { memset(&dup->tag, 0, zlen); iocur_top->need_crc = 1; } } if (dir_offset >= end_of_data || ptr >= endptr) return; } dep = (xfs_dir2_data_entry_t *)ptr; length = M_DIROPS(mp)->data_entsize(dep->namelen); if (dir_offset + length > end_of_data || ptr + length > endptr) { if (show_warnings) print_warning( "invalid length for dir entry name in inode %llu", (long long)cur_ino); return; } if (be16_to_cpu(*M_DIROPS(mp)->data_entry_tag_p(dep)) != dir_offset) return; if (obfuscate) generate_obfuscated_name(be64_to_cpu(dep->inumber), dep->namelen, &dep->name[0]); dir_offset += length; ptr += length; /* Zero the unused space after name, up to the tag */ if (zero_stale_data) { /* 1 byte for ftype; don't bother with conditional */ int zlen = (char *)M_DIROPS(mp)->data_entry_tag_p(dep) - (char *)&dep->name[dep->namelen] - 1; if (zlen > 0) { memset(&dep->name[dep->namelen] + 1, 0, zlen); iocur_top->need_crc = 1; } } } } static void process_symlink_block( char *block) { char *link = block; if (xfs_sb_version_hascrc(&(mp)->m_sb)) link += sizeof(struct xfs_dsymlink_hdr); if (obfuscate) obfuscate_path_components(link, XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize)); if (zero_stale_data) { size_t linklen, zlen; linklen = strlen(link); zlen = mp->m_sb.sb_blocksize - linklen; if (xfs_sb_version_hascrc(&mp->m_sb)) zlen -= sizeof(struct xfs_dsymlink_hdr); if (zlen < mp->m_sb.sb_blocksize) memset(link + linklen, 0, zlen); } } #define MAX_REMOTE_VALS 4095 static struct attr_data_s { int remote_val_count; xfs_dablk_t remote_vals[MAX_REMOTE_VALS]; } attr_data; static inline void add_remote_vals( xfs_dablk_t blockidx, int length) { while (length > 0 && attr_data.remote_val_count < MAX_REMOTE_VALS) { attr_data.remote_vals[attr_data.remote_val_count] = blockidx; attr_data.remote_val_count++; blockidx++; length -= mp->m_sb.sb_blocksize; } if (attr_data.remote_val_count >= MAX_REMOTE_VALS) { print_warning( "Overflowed attr obfuscation array. No longer obfuscating remote attrs."); } } /* Handle remote and leaf attributes */ static void process_attr_block( char *block, xfs_fileoff_t offset) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr hdr; int i; int nentries; xfs_attr_leaf_entry_t *entry; xfs_attr_leaf_name_local_t *local; xfs_attr_leaf_name_remote_t *remote; __uint32_t bs = mp->m_sb.sb_blocksize; char *first_name; leaf = (xfs_attr_leafblock_t *)block; /* Remote attributes - attr3 has XFS_ATTR3_RMT_MAGIC, attr has none */ if ((be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC) && (be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR3_LEAF_MAGIC)) { for (i = 0; i < attr_data.remote_val_count; i++) { if (obfuscate && attr_data.remote_vals[i] == offset) /* Macros to handle both attr and attr3 */ memset(block + (bs - XFS_ATTR3_RMT_BUF_SPACE(mp, bs)), 'v', XFS_ATTR3_RMT_BUF_SPACE(mp, bs)); } return; } /* Ok, it's a leaf - get header; accounts for crc & non-crc */ xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &hdr, leaf); nentries = hdr.count; if (nentries * sizeof(xfs_attr_leaf_entry_t) + xfs_attr3_leaf_hdr_size(leaf) > XFS_ATTR3_RMT_BUF_SPACE(mp, bs)) { if (show_warnings) print_warning("invalid attr count in inode %llu", (long long)cur_ino); return; } entry = xfs_attr3_leaf_entryp(leaf); /* We will move this as we parse */ first_name = NULL; for (i = 0; i < nentries; i++, entry++) { int nlen, vlen, zlen; /* Grows up; if this name is topmost, move first_name */ if (!first_name || xfs_attr3_leaf_name(leaf, i) < first_name) first_name = xfs_attr3_leaf_name(leaf, i); if (be16_to_cpu(entry->nameidx) > mp->m_sb.sb_blocksize) { if (show_warnings) print_warning( "invalid attr nameidx in inode %llu", (long long)cur_ino); break; } if (entry->flags & XFS_ATTR_LOCAL) { local = xfs_attr3_leaf_name_local(leaf, i); if (local->namelen == 0) { if (show_warnings) print_warning( "zero length for attr name in inode %llu", (long long)cur_ino); break; } if (obfuscate) { generate_obfuscated_name(0, local->namelen, &local->nameval[0]); memset(&local->nameval[local->namelen], 'v', be16_to_cpu(local->valuelen)); } /* zero from end of nameval[] to next name start */ nlen = local->namelen; vlen = be16_to_cpu(local->valuelen); zlen = xfs_attr_leaf_entsize_local(nlen, vlen) - (sizeof(xfs_attr_leaf_name_local_t) - 1 + nlen + vlen); if (zero_stale_data) memset(&local->nameval[nlen + vlen], 0, zlen); } else { remote = xfs_attr3_leaf_name_remote(leaf, i); if (remote->namelen == 0 || remote->valueblk == 0) { if (show_warnings) print_warning( "invalid attr entry in inode %llu", (long long)cur_ino); break; } if (obfuscate) { generate_obfuscated_name(0, remote->namelen, &remote->name[0]); add_remote_vals(be32_to_cpu(remote->valueblk), be32_to_cpu(remote->valuelen)); } /* zero from end of name[] to next name start */ nlen = remote->namelen; zlen = xfs_attr_leaf_entsize_remote(nlen) - (sizeof(xfs_attr_leaf_name_remote_t) - 1 + nlen); if (zero_stale_data) memset(&remote->name[nlen], 0, zlen); } } /* Zero from end of entries array to the first name/val */ if (zero_stale_data) { struct xfs_attr_leaf_entry *entries; entries = xfs_attr3_leaf_entryp(leaf); memset(&entries[nentries], 0, first_name - (char *)&entries[nentries]); } } /* Processes symlinks, attrs, directories ... */ static int process_single_fsb_objects( xfs_fileoff_t o, xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, xfs_fileoff_t last) { char *dp; int ret = 0; int i; for (i = 0; i < c; i++) { push_cur(); set_cur(&typtab[btype], XFS_FSB_TO_DADDR(mp, s), blkbb, DB_RING_IGN, NULL); if (!iocur_top->data) { xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, s); xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, s); print_warning("cannot read %s block %u/%u (%llu)", typtab[btype].name, agno, agbno, s); if (stop_on_read_error) ret = -EIO; goto out_pop; } if (!obfuscate && !zero_stale_data) goto write; /* Zero unused part of interior nodes */ if (zero_stale_data) { xfs_da_intnode_t *node = iocur_top->data; int magic = be16_to_cpu(node->hdr.info.magic); if (magic == XFS_DA_NODE_MAGIC || magic == XFS_DA3_NODE_MAGIC) { struct xfs_da3_icnode_hdr hdr; int used; M_DIROPS(mp)->node_hdr_from_disk(&hdr, node); used = M_DIROPS(mp)->node_hdr_size; used += hdr.count * sizeof(struct xfs_da_node_entry); if (used < mp->m_sb.sb_blocksize) { memset((char *)node + used, 0, mp->m_sb.sb_blocksize - used); iocur_top->need_crc = 1; } } } /* Handle leaf nodes */ dp = iocur_top->data; switch (btype) { case TYP_DIR2: if (o >= mp->m_dir_geo->leafblk) break; process_dir_data_block(dp, o, last == mp->m_dir_geo->fsbcount); iocur_top->need_crc = 1; break; case TYP_SYMLINK: process_symlink_block(dp); iocur_top->need_crc = 1; break; case TYP_ATTR: process_attr_block(dp, o); iocur_top->need_crc = 1; break; default: break; } write: ret = write_buf(iocur_top); out_pop: pop_cur(); if (ret) break; o++; s++; } return ret; } /* * Static map to aggregate multiple extents into a single directory block. */ static struct bbmap mfsb_map; static int mfsb_length; static int process_multi_fsb_objects( xfs_fileoff_t o, xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, xfs_fileoff_t last) { int ret = 0; switch (btype) { case TYP_DIR2: break; default: print_warning("bad type for multi-fsb object %d", btype); return -EINVAL; } while (c > 0) { unsigned int bm_len; if (mfsb_length + c >= mp->m_dir_geo->fsbcount) { bm_len = mp->m_dir_geo->fsbcount - mfsb_length; mfsb_length = 0; } else { mfsb_length += c; bm_len = c; } mfsb_map.b[mfsb_map.nmaps].bm_bn = XFS_FSB_TO_DADDR(mp, s); mfsb_map.b[mfsb_map.nmaps].bm_len = XFS_FSB_TO_BB(mp, bm_len); mfsb_map.nmaps++; if (mfsb_length == 0) { push_cur(); set_cur(&typtab[btype], 0, 0, DB_RING_IGN, &mfsb_map); if (!iocur_top->data) { xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, s); xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, s); print_warning("cannot read %s block %u/%u (%llu)", typtab[btype].name, agno, agbno, s); if (stop_on_read_error) ret = -1; goto out_pop; } if ((!obfuscate && !zero_stale_data) || o >= mp->m_dir_geo->leafblk) { ret = write_buf(iocur_top); goto out_pop; } process_dir_data_block(iocur_top->data, o, last == mp->m_dir_geo->fsbcount); iocur_top->need_crc = 1; ret = write_buf(iocur_top); out_pop: pop_cur(); mfsb_map.nmaps = 0; if (ret) break; } c -= bm_len; s += bm_len; } return ret; } /* inode copy routines */ static int process_bmbt_reclist( xfs_bmbt_rec_t *rp, int numrecs, typnm_t btype) { int i; xfs_fileoff_t o, op = NULLFILEOFF; xfs_fsblock_t s; xfs_filblks_t c, cp = NULLFILEOFF; int f; xfs_fileoff_t last; xfs_agnumber_t agno; xfs_agblock_t agbno; int error; if (btype == TYP_DATA) return 1; convert_extent(&rp[numrecs - 1], &o, &s, &c, &f); last = o + c; for (i = 0; i < numrecs; i++, rp++) { convert_extent(rp, &o, &s, &c, &f); /* * ignore extents that are clearly bogus, and if a bogus * one is found, stop processing remaining extents */ if (i > 0 && op + cp > o) { if (show_warnings) print_warning("bmap extent %d in %s ino %llu " "starts at %llu, previous extent " "ended at %llu", i, typtab[btype].name, (long long)cur_ino, o, op + cp - 1); break; } if (c > max_extent_size) { /* * since we are only processing non-data extents, * large numbers of blocks in a metadata extent is * extremely rare and more than likely to be corrupt. */ if (show_warnings) print_warning("suspicious count %u in bmap " "extent %d in %s ino %llu", c, i, typtab[btype].name, (long long)cur_ino); break; } op = o; cp = c; agno = XFS_FSB_TO_AGNO(mp, s); agbno = XFS_FSB_TO_AGBNO(mp, s); if (!valid_bno(agno, agbno)) { if (show_warnings) print_warning("invalid block number %u/%u " "(%llu) in bmap extent %d in %s ino " "%llu", agno, agbno, s, i, typtab[btype].name, (long long)cur_ino); break; } if (!valid_bno(agno, agbno + c - 1)) { if (show_warnings) print_warning("bmap extent %i in %s inode %llu " "overflows AG (end is %u/%u)", i, typtab[btype].name, (long long)cur_ino, agno, agbno + c - 1); break; } /* multi-extent blocks require special handling */ if (btype != TYP_DIR2 || mp->m_dir_geo->fsbcount == 1) { error = process_single_fsb_objects(o, s, c, btype, last); } else { error = process_multi_fsb_objects(o, s, c, btype, last); } if (error) return 0; } return 1; } static int scanfunc_bmap( struct xfs_btree_block *block, xfs_agnumber_t agno, xfs_agblock_t agbno, int level, typnm_t btype, void *arg) /* ptr to itype */ { int i; xfs_bmbt_ptr_t *pp; int nrecs; nrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (nrecs > mp->m_bmap_dmxr[0]) { if (show_warnings) print_warning("invalid numrecs (%u) in %s " "block %u/%u", nrecs, typtab[btype].name, agno, agbno); return 1; } return process_bmbt_reclist(XFS_BMBT_REC_ADDR(mp, block, 1), nrecs, *(typnm_t*)arg); } if (nrecs > mp->m_bmap_dmxr[1]) { if (show_warnings) print_warning("invalid numrecs (%u) in %s block %u/%u", nrecs, typtab[btype].name, agno, agbno); return 1; } pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); for (i = 0; i < nrecs; i++) { xfs_agnumber_t ag; xfs_agblock_t bno; ag = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i])); bno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i])); if (bno == 0 || bno > mp->m_sb.sb_agblocks || ag > mp->m_sb.sb_agcount) { if (show_warnings) print_warning("invalid block number (%u/%u) " "in %s block %u/%u", ag, bno, typtab[btype].name, agno, agbno); continue; } if (!scan_btree(ag, bno, level, btype, arg, scanfunc_bmap)) return 0; } return 1; } static int process_btinode( xfs_dinode_t *dip, typnm_t itype) { xfs_bmdr_block_t *dib; int i; xfs_bmbt_ptr_t *pp; int level; int nrecs; int maxrecs; int whichfork; typnm_t btype; whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK; btype = (itype == TYP_ATTR) ? TYP_BMAPBTA : TYP_BMAPBTD; dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); level = be16_to_cpu(dib->bb_level); nrecs = be16_to_cpu(dib->bb_numrecs); if (level > XFS_BM_MAXLEVELS(mp, whichfork)) { if (show_warnings) print_warning("invalid level (%u) in inode %lld %s " "root", level, (long long)cur_ino, typtab[btype].name); return 1; } if (level == 0) { return process_bmbt_reclist(XFS_BMDR_REC_ADDR(dib, 1), nrecs, itype); } maxrecs = libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0); if (nrecs > maxrecs) { if (show_warnings) print_warning("invalid numrecs (%u) in inode %lld %s " "root", nrecs, (long long)cur_ino, typtab[btype].name); return 1; } pp = XFS_BMDR_PTR_ADDR(dib, 1, maxrecs); for (i = 0; i < nrecs; i++) { xfs_agnumber_t ag; xfs_agblock_t bno; ag = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i])); bno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i])); if (bno == 0 || bno > mp->m_sb.sb_agblocks || ag > mp->m_sb.sb_agcount) { if (show_warnings) print_warning("invalid block number (%u/%u) " "in inode %llu %s root", ag, bno, (long long)cur_ino, typtab[btype].name); continue; } if (!scan_btree(ag, bno, level, btype, &itype, scanfunc_bmap)) return 0; } return 1; } static int process_exinode( xfs_dinode_t *dip, typnm_t itype) { int whichfork; int used; xfs_extnum_t nex; whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK; nex = XFS_DFORK_NEXTENTS(dip, whichfork); used = nex * sizeof(xfs_bmbt_rec_t); if (nex < 0 || used > XFS_DFORK_SIZE(dip, mp, whichfork)) { if (show_warnings) print_warning("bad number of extents %d in inode %lld", nex, (long long)cur_ino); return 1; } /* Zero unused data fork past used extents */ if (zero_stale_data && (used < XFS_DFORK_SIZE(dip, mp, whichfork))) memset(XFS_DFORK_PTR(dip, whichfork) + used, 0, XFS_DFORK_SIZE(dip, mp, whichfork) - used); return process_bmbt_reclist((xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork), nex, itype); } static int process_inode_data( xfs_dinode_t *dip, typnm_t itype) { switch (dip->di_format) { case XFS_DINODE_FMT_LOCAL: if (obfuscate || zero_stale_data) switch (itype) { case TYP_DIR2: process_sf_dir(dip); break; case TYP_SYMLINK: process_sf_symlink(dip); break; default: ; } break; case XFS_DINODE_FMT_EXTENTS: return process_exinode(dip, itype); case XFS_DINODE_FMT_BTREE: return process_btinode(dip, itype); } return 1; } /* * when we process the inode, we may change the data in the data and/or * attribute fork if they are in short form and we are obfuscating names. * In this case we need to recalculate the CRC of the inode, but we should * only do that if the CRC in the inode is good to begin with. If the crc * is not ok, we just leave it alone. */ static int process_inode( xfs_agnumber_t agno, xfs_agino_t agino, xfs_dinode_t *dip, bool free_inode) { int success; bool crc_was_ok = false; /* no recalc by default */ bool need_new_crc = false; success = 1; cur_ino = XFS_AGINO_TO_INO(mp, agno, agino); /* we only care about crc recalculation if we will modify the inode. */ if (obfuscate || zero_stale_data) { crc_was_ok = libxfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize, offsetof(struct xfs_dinode, di_crc)); } if (free_inode) { if (zero_stale_data) { /* Zero all of the inode literal area */ memset(XFS_DFORK_DPTR(dip), 0, XFS_LITINO(mp, dip->di_version)); } goto done; } /* copy appropriate data fork metadata */ switch (be16_to_cpu(dip->di_mode) & S_IFMT) { case S_IFDIR: success = process_inode_data(dip, TYP_DIR2); if (dip->di_format == XFS_DINODE_FMT_LOCAL) need_new_crc = 1; break; case S_IFLNK: success = process_inode_data(dip, TYP_SYMLINK); if (dip->di_format == XFS_DINODE_FMT_LOCAL) need_new_crc = 1; break; case S_IFREG: success = process_inode_data(dip, TYP_DATA); break; default: ; } nametable_clear(); /* copy extended attributes if they exist and forkoff is valid */ if (success && XFS_DFORK_DSIZE(dip, mp) < XFS_LITINO(mp, dip->di_version)) { attr_data.remote_val_count = 0; switch (dip->di_aformat) { case XFS_DINODE_FMT_LOCAL: need_new_crc = 1; if (obfuscate || zero_stale_data) process_sf_attr(dip); break; case XFS_DINODE_FMT_EXTENTS: success = process_exinode(dip, TYP_ATTR); break; case XFS_DINODE_FMT_BTREE: success = process_btinode(dip, TYP_ATTR); break; } nametable_clear(); } done: /* Heavy handed but low cost; just do it as a catch-all. */ if (zero_stale_data) need_new_crc = 1; if (crc_was_ok && need_new_crc) libxfs_dinode_calc_crc(mp, dip); return success; } static __uint32_t inodes_copied = 0; static int copy_inode_chunk( xfs_agnumber_t agno, xfs_inobt_rec_t *rp) { xfs_agino_t agino; int off; xfs_agblock_t agbno; xfs_agblock_t end_agbno; int i; int rval = 0; int blks_per_buf; int inodes_per_buf; int ioff; agino = be32_to_cpu(rp->ir_startino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); end_agbno = agbno + mp->m_ialloc_blks; off = XFS_INO_TO_OFFSET(mp, agino); /* * If the fs supports sparse inode records, we must process inodes a * cluster at a time because that is the sparse allocation granularity. * Otherwise, we risk CRC corruption errors on reads of inode chunks. * * Also make sure that that we don't process more than the single record * we've been passed (large block sizes can hold multiple inode chunks). */ if (xfs_sb_version_hassparseinodes(&mp->m_sb)) blks_per_buf = xfs_icluster_size_fsb(mp); else blks_per_buf = mp->m_ialloc_blks; inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, XFS_INODES_PER_CHUNK); /* * Sanity check that we only process a single buffer if ir_startino has * a buffer offset. A non-zero offset implies that the entire chunk lies * within a block. */ if (off && inodes_per_buf != XFS_INODES_PER_CHUNK) { print_warning("bad starting inode offset %d", off); return 0; } if (agino == 0 || agino == NULLAGINO || !valid_bno(agno, agbno) || !valid_bno(agno, XFS_AGINO_TO_AGBNO(mp, agino + XFS_INODES_PER_CHUNK - 1))) { if (show_warnings) print_warning("bad inode number %llu (%u/%u)", XFS_AGINO_TO_INO(mp, agno, agino), agno, agino); return 1; } /* * check for basic assumptions about inode chunks, and if any * assumptions fail, don't process the inode chunk. */ if ((mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK && off != 0) || (mp->m_sb.sb_inopblock > XFS_INODES_PER_CHUNK && off % XFS_INODES_PER_CHUNK != 0) || (xfs_sb_version_hasalign(&mp->m_sb) && mp->m_sb.sb_inoalignmt != 0 && agbno % mp->m_sb.sb_inoalignmt != 0)) { if (show_warnings) print_warning("badly aligned inode (start = %llu)", XFS_AGINO_TO_INO(mp, agno, agino)); return 1; } push_cur(); ioff = 0; while (agbno < end_agbno && ioff < XFS_INODES_PER_CHUNK) { if (xfs_inobt_is_sparse_disk(rp, ioff)) goto next_bp; set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, blks_per_buf), DB_RING_IGN, NULL); if (iocur_top->data == NULL) { print_warning("cannot read inode block %u/%u", agno, agbno); rval = !stop_on_read_error; goto pop_out; } for (i = 0; i < inodes_per_buf; i++) { xfs_dinode_t *dip; dip = (xfs_dinode_t *)((char *)iocur_top->data + ((off + i) << mp->m_sb.sb_inodelog)); /* process_inode handles free inodes, too */ if (!process_inode(agno, agino + ioff + i, dip, XFS_INOBT_IS_FREE_DISK(rp, ioff + i))) goto pop_out; inodes_copied++; } if (write_buf(iocur_top)) goto pop_out; next_bp: agbno += blks_per_buf; ioff += inodes_per_buf; } if (show_progress) print_progress("Copied %u of %u inodes (%u of %u AGs)", inodes_copied, mp->m_sb.sb_icount, agno, mp->m_sb.sb_agcount); rval = 1; pop_out: pop_cur(); return rval; } static int scanfunc_ino( struct xfs_btree_block *block, xfs_agnumber_t agno, xfs_agblock_t agbno, int level, typnm_t btype, void *arg) { xfs_inobt_rec_t *rp; xfs_inobt_ptr_t *pp; int i; int numrecs; int finobt = *(int *) arg; numrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (numrecs > mp->m_inobt_mxr[0]) { if (show_warnings) print_warning("invalid numrecs %d in %s " "block %u/%u", numrecs, typtab[btype].name, agno, agbno); numrecs = mp->m_inobt_mxr[0]; } /* * Only copy the btree blocks for the finobt. The inobt scan * copies the inode chunks. */ if (finobt) return 1; rp = XFS_INOBT_REC_ADDR(mp, block, 1); for (i = 0; i < numrecs; i++, rp++) { if (!copy_inode_chunk(agno, rp)) return 0; } return 1; } if (numrecs > mp->m_inobt_mxr[1]) { if (show_warnings) print_warning("invalid numrecs %d in %s block %u/%u", numrecs, typtab[btype].name, agno, agbno); numrecs = mp->m_inobt_mxr[1]; } pp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]); for (i = 0; i < numrecs; i++) { if (!valid_bno(agno, be32_to_cpu(pp[i]))) { if (show_warnings) print_warning("invalid block number (%u/%u) " "in %s block %u/%u", agno, be32_to_cpu(pp[i]), typtab[btype].name, agno, agbno); continue; } if (!scan_btree(agno, be32_to_cpu(pp[i]), level, btype, arg, scanfunc_ino)) return 0; } return 1; } static int copy_inodes( xfs_agnumber_t agno, xfs_agi_t *agi) { xfs_agblock_t root; int levels; int finobt = 0; root = be32_to_cpu(agi->agi_root); levels = be32_to_cpu(agi->agi_level); /* validate root and levels before processing the tree */ if (root == 0 || root > mp->m_sb.sb_agblocks) { if (show_warnings) print_warning("invalid block number (%u) in inobt " "root in agi %u", root, agno); return 1; } if (levels >= XFS_BTREE_MAXLEVELS) { if (show_warnings) print_warning("invalid level (%u) in inobt root " "in agi %u", levels, agno); return 1; } if (!scan_btree(agno, root, levels, TYP_INOBT, &finobt, scanfunc_ino)) return 0; if (xfs_sb_version_hasfinobt(&mp->m_sb)) { root = be32_to_cpu(agi->agi_free_root); levels = be32_to_cpu(agi->agi_free_level); finobt = 1; if (!scan_btree(agno, root, levels, TYP_INOBT, &finobt, scanfunc_ino)) return 0; } return 1; } static int scan_ag( xfs_agnumber_t agno) { xfs_agf_t *agf; xfs_agi_t *agi; int stack_count = 0; int rval = 0; /* copy the superblock of the AG */ push_cur(); stack_count++; set_cur(&typtab[TYP_SB], XFS_AG_DADDR(mp, agno, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if (!iocur_top->data) { print_warning("cannot read superblock for ag %u", agno); if (stop_on_read_error) goto pop_out; } else { /* Replace any filesystem label with "L's" */ if (obfuscate) { struct xfs_sb *sb = iocur_top->data; memset(sb->sb_fname, 'L', min(strlen(sb->sb_fname), sizeof(sb->sb_fname))); iocur_top->need_crc = 1; } if (write_buf(iocur_top)) goto pop_out; } /* copy the AG free space btree root */ push_cur(); stack_count++; set_cur(&typtab[TYP_AGF], XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); agf = iocur_top->data; if (iocur_top->data == NULL) { print_warning("cannot read agf block for ag %u", agno); if (stop_on_read_error) goto pop_out; } else { if (write_buf(iocur_top)) goto pop_out; } /* copy the AG inode btree root */ push_cur(); stack_count++; set_cur(&typtab[TYP_AGI], XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); agi = iocur_top->data; if (iocur_top->data == NULL) { print_warning("cannot read agi block for ag %u", agno); if (stop_on_read_error) goto pop_out; } else { if (write_buf(iocur_top)) goto pop_out; } /* copy the AG free list header */ push_cur(); stack_count++; set_cur(&typtab[TYP_AGFL], XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if (iocur_top->data == NULL) { print_warning("cannot read agfl block for ag %u", agno); if (stop_on_read_error) goto pop_out; } else { if (agf && zero_stale_data) { /* Zero out unused bits of agfl */ int i; __be32 *agfl_bno; agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, iocur_top->bp); i = be32_to_cpu(agf->agf_fllast); for (;;) { if (++i == XFS_AGFL_SIZE(mp)) i = 0; if (i == be32_to_cpu(agf->agf_flfirst)) break; agfl_bno[i] = cpu_to_be32(NULLAGBLOCK); } iocur_top->need_crc = 1; } if (write_buf(iocur_top)) goto pop_out; } /* copy AG free space btrees */ if (agf) { if (show_progress) print_progress("Copying free space trees of AG %u", agno); if (!copy_free_bno_btree(agno, agf)) goto pop_out; if (!copy_free_cnt_btree(agno, agf)) goto pop_out; if (!copy_rmap_btree(agno, agf)) goto pop_out; if (!copy_refcount_btree(agno, agf)) goto pop_out; } /* copy inode btrees and the inodes and their associated metadata */ if (agi) { if (!copy_inodes(agno, agi)) goto pop_out; } rval = 1; pop_out: while (stack_count--) pop_cur(); return rval; } static int copy_ino( xfs_ino_t ino, typnm_t itype) { xfs_agnumber_t agno; xfs_agblock_t agbno; xfs_agino_t agino; int offset; int rval = 0; if (ino == 0 || ino == NULLFSINO) return 1; agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); offset = XFS_AGINO_TO_OFFSET(mp, agino); if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || offset >= mp->m_sb.sb_inopblock) { if (show_warnings) print_warning("invalid %s inode number (%lld)", typtab[itype].name, (long long)ino); return 1; } push_cur(); set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, agbno), blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { print_warning("cannot read %s inode %lld", typtab[itype].name, (long long)ino); rval = !stop_on_read_error; goto pop_out; } off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize); cur_ino = ino; rval = process_inode_data(iocur_top->data, itype); pop_out: pop_cur(); return rval; } static int copy_sb_inodes(void) { if (!copy_ino(mp->m_sb.sb_rbmino, TYP_RTBITMAP)) return 0; if (!copy_ino(mp->m_sb.sb_rsumino, TYP_RTSUMMARY)) return 0; if (!copy_ino(mp->m_sb.sb_uquotino, TYP_DQBLK)) return 0; if (!copy_ino(mp->m_sb.sb_gquotino, TYP_DQBLK)) return 0; return copy_ino(mp->m_sb.sb_pquotino, TYP_DQBLK); } static int copy_log(void) { struct xlog log; int dirty; xfs_daddr_t logstart; int logblocks; int logversion; int cycle = XLOG_INIT_CYCLE; if (show_progress) print_progress("Copying log"); push_cur(); set_cur(&typtab[TYP_LOG], XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart), mp->m_sb.sb_logblocks * blkbb, DB_RING_IGN, NULL); if (iocur_top->data == NULL) { pop_cur(); print_warning("cannot read log"); return !stop_on_read_error; } /* If not obfuscating or zeroing, just copy the log as it is */ if (!obfuscate && !zero_stale_data) goto done; dirty = xlog_is_dirty(mp, &log, &x, 0); switch (dirty) { case 0: /* clear out a clean log */ if (show_progress) print_progress("Zeroing clean log"); logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); logblocks = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1; if (xfs_sb_version_hascrc(&mp->m_sb)) cycle = log.l_curr_cycle + 1; libxfs_log_clear(NULL, iocur_top->data, logstart, logblocks, &mp->m_sb.sb_uuid, logversion, mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true); break; case 1: /* keep the dirty log */ if (obfuscate) print_warning( _("Filesystem log is dirty; image will contain unobfuscated metadata in log.")); break; case -1: /* log detection error */ if (obfuscate) print_warning( _("Could not discern log; image will contain unobfuscated metadata in log.")); break; } done: return !write_buf(iocur_top); } static int metadump_f( int argc, char **argv) { xfs_agnumber_t agno; int c; int start_iocur_sp; char *p; exitcode = 1; show_progress = 0; show_warnings = 0; stop_on_read_error = 0; if (mp->m_sb.sb_magicnum != XFS_SB_MAGIC) { print_warning("bad superblock magic number %x, giving up", mp->m_sb.sb_magicnum); return 0; } while ((c = getopt(argc, argv, "aegm:ow")) != EOF) { switch (c) { case 'a': zero_stale_data = 0; break; case 'e': stop_on_read_error = 1; break; case 'g': show_progress = 1; break; case 'm': max_extent_size = (int)strtol(optarg, &p, 0); if (*p != '\0' || max_extent_size <= 0) { print_warning("bad max extent size %s", optarg); return 0; } break; case 'o': obfuscate = 0; break; case 'w': show_warnings = 1; break; default: print_warning("bad option for metadump command"); return 0; } } if (optind != argc - 1) { print_warning("too few options for metadump (no filename given)"); return 0; } metablock = (xfs_metablock_t *)calloc(BBSIZE + 1, BBSIZE); if (metablock == NULL) { print_warning("memory allocation failure"); return 0; } metablock->mb_blocklog = BBSHIFT; metablock->mb_magic = cpu_to_be32(XFS_MD_MAGIC); block_index = (__be64 *)((char *)metablock + sizeof(xfs_metablock_t)); block_buffer = (char *)metablock + BBSIZE; num_indices = (BBSIZE - sizeof(xfs_metablock_t)) / sizeof(__be64); /* * A metadump block can hold at most num_indices of BBSIZE sectors; * do not try to dump a filesystem with a sector size which does not * fit within num_indices (i.e. within a single metablock). */ if (mp->m_sb.sb_sectsize > num_indices * BBSIZE) { print_warning("Cannot dump filesystem with sector size %u", mp->m_sb.sb_sectsize); free(metablock); return 0; } cur_index = 0; start_iocur_sp = iocur_sp; if (strcmp(argv[optind], "-") == 0) { if (isatty(fileno(stdout))) { print_warning("cannot write to a terminal"); free(metablock); return 0; } outf = stdout; } else { outf = fopen(argv[optind], "wb"); if (outf == NULL) { print_warning("cannot create dump file"); free(metablock); return 0; } } exitcode = 0; for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { if (!scan_ag(agno)) { exitcode = 1; break; } } /* copy realtime and quota inode contents */ if (!exitcode) exitcode = !copy_sb_inodes(); /* copy log if it's internal */ if ((mp->m_sb.sb_logstart != 0) && !exitcode) exitcode = !copy_log(); /* write the remaining index */ if (!exitcode) exitcode = write_index() < 0; if (progress_since_warning) fputc('\n', (outf == stdout) ? stderr : stdout); if (outf != stdout) fclose(outf); /* cleanup iocur stack */ while (iocur_sp > start_iocur_sp) pop_cur(); free(metablock); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/db/metadump.h0000644000000000000000000000135713063067170015051 0ustar /* * Copyright (c) 2007 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void metadump_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/output.c0000644000000000000000000000451613063067170014570 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include "command.h" #include "output.h" #include "sig.h" #include "malloc.h" #include "init.h" static int log_f(int argc, char **argv); static const cmdinfo_t log_cmd = { "log", NULL, log_f, 0, 2, 0, N_("[stop|start ]"), N_("start or stop logging to a file"), NULL }; int dbprefix; static FILE *log_file; static char *log_file_name; int dbprintf(const char *fmt, ...) { va_list ap; int i; if (seenint()) return 0; va_start(ap, fmt); blockint(); i = 0; if (dbprefix) i += printf("%s: ", fsdevice); i += vprintf(fmt, ap); unblockint(); va_end(ap); if (log_file) { va_start(ap, fmt); vfprintf(log_file, fmt, ap); va_end(ap); } return i; } static int log_f( int argc, char **argv) { if (argc == 1) { if (log_file) dbprintf(_("logging to %s\n"), log_file_name); else dbprintf(_("no log file\n")); } else if (argc == 2 && strcmp(argv[1], "stop") == 0) { if (log_file) { xfree(log_file_name); fclose(log_file); log_file = NULL; } else dbprintf(_("no log file\n")); } else if (argc == 3 && strcmp(argv[1], "start") == 0) { if (log_file) dbprintf(_("already logging to %s\n"), log_file_name); else { log_file = fopen(argv[2], "a"); if (log_file == NULL) dbprintf(_("can't open %s for writing\n"), argv[2]); else log_file_name = xstrdup(argv[1]); } } else dbprintf(_("bad log command, ignored\n")); return 0; } void logprintf(const char *fmt, ...) { va_list ap; if (log_file) { va_start(ap, fmt); (void)vfprintf(log_file, fmt, ap); va_end(ap); } } void output_init(void) { add_command(&log_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/output.h0000644000000000000000000000153713063067170014575 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern int dbprefix; extern int dbprintf(const char *, ...); extern void logprintf(const char *, ...); extern void output_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/print.c0000644000000000000000000001353213063067170014362 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "io.h" #include "print.h" #include "bit.h" #include "flist.h" #include "strvec.h" #include "output.h" #include "sig.h" #include "write.h" static void print_allfields(const struct field *fields); static int print_f(int argc, char **argv); static void print_flist_1(struct flist *flist, char **pfx, int parentoff); static void print_somefields(const struct field *fields, int argc, char **argv); static const cmdinfo_t print_cmd = { "print", "p", print_f, 0, -1, 0, N_("[value]..."), N_("print field values"), NULL }; static void print_allfields( const field_t *fields) { flist_t *flist; #ifdef DEBUG int i; #endif flist = flist_make(""); flist->fld = fields; #ifndef DEBUG (void)flist_parse(fields, flist, iocur_top->data, 0); #else i = flist_parse(fields, flist, iocur_top->data, 0); ASSERT(i == 1); #endif flist_print(flist); print_flist(flist); flist_free(flist); } static int print_f( int argc, char **argv) { pfunc_t pf; if (cur_typ == NULL) { dbprintf(_("no current type\n")); return 0; } pf = cur_typ->pfunc; if (pf == NULL) { dbprintf(_("no print function for type %s\n"), cur_typ->name); return 0; } argc--; argv++; (*pf)(DB_READ, cur_typ->fields, argc, argv); return 0; } void print_flist( flist_t *flist) { char **pfx; pfx = new_strvec(0); print_flist_1(flist, pfx, 0); free_strvec(pfx); } static void print_flist_1( flist_t *flist, char **ppfx, int parentoff) { char buf[16]; const field_t *f; const ftattr_t *fa; flist_t *fl; int low; int count; int neednl; char **pfx; for (fl = flist; fl && !seenint(); fl = fl->sibling) { pfx = copy_strvec(ppfx); if (fl->name[0]) add_strvec(&pfx, fl->name); if (fl->flags & FL_OKLOW) { add_strvec(&pfx, "["); snprintf(buf, sizeof(buf), "%d", fl->low); add_strvec(&pfx, buf); if (fl->low != fl->high) { add_strvec(&pfx, "-"); snprintf(buf, sizeof(buf), "%d", fl->high); add_strvec(&pfx, buf); } add_strvec(&pfx, "]"); } if (fl->child) { if (fl->name[0]) add_strvec(&pfx, "."); print_flist_1(fl->child, pfx, fl->offset); } else { f = fl->fld; fa = &ftattrtab[f->ftyp]; ASSERT(fa->ftyp == f->ftyp); print_strvec(pfx); dbprintf(" = "); if (fl->flags & FL_OKLOW) low = fl->low; else low = 0; count = fcount(f, iocur_top->data, parentoff); if (fl->flags & FL_OKHIGH) count = min(count, fl->high - low + 1); if (fa->prfunc) { neednl = fa->prfunc(iocur_top->data, fl->offset, count, fa->fmtstr, fsize(f, iocur_top->data, parentoff, 0), fa->arg, low, (f->flags & FLD_ARRAY) != 0); if (neednl) dbprintf("\n"); } else { ASSERT(fa->arg & FTARG_OKEMPTY); dbprintf(_("(empty)\n")); } } free_strvec(pfx); } } void print_init(void) { add_command(&print_cmd); } void print_sarray( void *obj, int bit, int count, int size, int base, int array, const field_t *flds, int skipnms) { int bitoff; const field_t *f; const ftattr_t *fa; int first; int i; ASSERT(bitoffs(bit) == 0); if (skipnms == 0) { for (f = flds, first = 1; f->name; f++) { if (f->flags & FLD_SKIPALL) continue; dbprintf("%c%s", first ? '[' : ',', f->name); first = 0; } dbprintf("] "); } for (i = 0, bitoff = bit; i < count && !seenint(); i++, bitoff += size) { if (array) dbprintf("\n%d:", i + base); for (f = flds, first = 1; f->name; f++) { if (f->flags & FLD_SKIPALL) continue; fa = &ftattrtab[f->ftyp]; ASSERT(fa->ftyp == f->ftyp); dbprintf("%c", first ? '[' : ','); first = 0; if (fa->prfunc) fa->prfunc(obj, bitoff + bitoffset(f, obj, bitoff, i + base), fcount(f, obj, bitoff), fa->fmtstr, fsize(f, obj, bitoff, i + base), fa->arg, (f->flags & FLD_ABASE1) != 0, f->flags & FLD_ARRAY); else { ASSERT(fa->arg & FTARG_OKEMPTY); dbprintf(_("(empty)")); } } dbprintf("]"); if (i < count - 1) dbprintf(" "); } } static void print_somefields( const field_t *fields, int argc, char **argv) { const ftattr_t *fa; flist_t *fl; flist_t *lfl; flist_t *nfl; fl = lfl = NULL; while (argc > 0) { nfl = flist_scan(*argv); if (!nfl) { if (fl) flist_free(fl); return; } if (lfl) lfl->sibling = nfl; else fl = nfl; lfl = nfl; argc--; argv++; } if (fields->name[0] == '\0') { fa = &ftattrtab[fields->ftyp]; ASSERT(fa->ftyp == fields->ftyp); fields = fa->subfld; } if (!flist_parse(fields, fl, iocur_top->data, 0)) { flist_free(fl); return; } flist_print(fl); print_flist(fl); flist_free(fl); } /*ARGSUSED*/ void print_string( const field_t *fields, int argc, char **argv) { char *cp; if (argc != 0) dbprintf(_("no arguments allowed\n")); dbprintf("\""); for (cp = iocur_top->data; cp < (char *)iocur_top->data + iocur_top->len && *cp && !seenint(); cp++) dbprintf("%c", *cp); dbprintf("\"\n"); } void print_struct( const field_t *fields, int argc, char **argv) { if (argc == 0) print_allfields(fields); else print_somefields(fields, argc, argv); } xfsprogs-4.9.0+nmu1ubuntu2/db/print.h0000644000000000000000000000213513063067167014372 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ struct field; struct flist; extern void print_flist(struct flist *flist); extern void print_init(void); extern void print_sarray(void *obj, int bit, int count, int size, int base, int array, const field_t *flds, int skipnms); extern void print_struct(const struct field *fields, int argc, char **argv); extern void print_string(const struct field *fields, int argc, char **argv); xfsprogs-4.9.0+nmu1ubuntu2/db/quit.c0000644000000000000000000000202513063067170014203 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "command.h" #include "quit.h" static int quit_f(int argc, char **argv); static const cmdinfo_t quit_cmd = { "quit", "q", quit_f, 0, 0, 0, NULL, N_("exit xfs_db"), NULL }; static int quit_f( int argc, char **argv) { return 1; } void quit_init(void) { add_command(&quit_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/db/quit.h0000644000000000000000000000136513063067167014224 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void quit_init(void); xfsprogs-4.9.0+nmu1ubuntu2/db/sb.c0000644000000000000000000005663513063067167013653 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "io.h" #include "sb.h" #include "bit.h" #include "output.h" #include "init.h" #define uuid_equal(s,d) (platform_uuid_compare((s),(d)) == 0) static int sb_f(int argc, char **argv); static void sb_help(void); static int uuid_f(int argc, char **argv); static void uuid_help(void); static int label_f(int argc, char **argv); static void label_help(void); static int version_f(int argc, char **argv); static void version_help(void); static const cmdinfo_t sb_cmd = { "sb", NULL, sb_f, 0, 1, 1, N_("[agno]"), N_("set current address to sb header"), sb_help }; static const cmdinfo_t uuid_cmd = { "uuid", NULL, uuid_f, 0, 1, 1, N_("[uuid]"), N_("write/print FS uuid"), uuid_help }; static const cmdinfo_t label_cmd = { "label", NULL, label_f, 0, 1, 1, N_("[label]"), N_("write/print FS label"), label_help }; static const cmdinfo_t version_cmd = { "version", NULL, version_f, 0, -1, 1, N_("[feature | [vnum fnum]]"), N_("set feature bit(s) in the sb version field"), version_help }; void sb_init(void) { add_command(&sb_cmd); add_command(&uuid_cmd); add_command(&label_cmd); add_command(&version_cmd); } #define OFF(f) bitize(offsetof(xfs_sb_t, sb_ ## f)) #define SZC(f) szcount(xfs_sb_t, sb_ ## f) const field_t sb_flds[] = { { "magicnum", FLDT_UINT32X, OI(OFF(magicnum)), C1, 0, TYP_NONE }, { "blocksize", FLDT_UINT32D, OI(OFF(blocksize)), C1, 0, TYP_NONE }, { "dblocks", FLDT_DRFSBNO, OI(OFF(dblocks)), C1, 0, TYP_NONE }, { "rblocks", FLDT_DRFSBNO, OI(OFF(rblocks)), C1, 0, TYP_NONE }, { "rextents", FLDT_DRTBNO, OI(OFF(rextents)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE }, { "logstart", FLDT_DFSBNO, OI(OFF(logstart)), C1, 0, TYP_LOG }, { "rootino", FLDT_INO, OI(OFF(rootino)), C1, 0, TYP_INODE }, { "rbmino", FLDT_INO, OI(OFF(rbmino)), C1, 0, TYP_INODE }, { "rsumino", FLDT_INO, OI(OFF(rsumino)), C1, 0, TYP_INODE }, { "rextsize", FLDT_AGBLOCK, OI(OFF(rextsize)), C1, 0, TYP_NONE }, { "agblocks", FLDT_AGBLOCK, OI(OFF(agblocks)), C1, 0, TYP_NONE }, { "agcount", FLDT_AGNUMBER, OI(OFF(agcount)), C1, 0, TYP_NONE }, { "rbmblocks", FLDT_EXTLEN, OI(OFF(rbmblocks)), C1, 0, TYP_NONE }, { "logblocks", FLDT_EXTLEN, OI(OFF(logblocks)), C1, 0, TYP_NONE }, { "versionnum", FLDT_UINT16X, OI(OFF(versionnum)), C1, 0, TYP_NONE }, { "sectsize", FLDT_UINT16D, OI(OFF(sectsize)), C1, 0, TYP_NONE }, { "inodesize", FLDT_UINT16D, OI(OFF(inodesize)), C1, 0, TYP_NONE }, { "inopblock", FLDT_UINT16D, OI(OFF(inopblock)), C1, 0, TYP_NONE }, { "fname", FLDT_CHARNS, OI(OFF(fname)), CI(SZC(fname)), 0, TYP_NONE }, { "blocklog", FLDT_UINT8D, OI(OFF(blocklog)), C1, 0, TYP_NONE }, { "sectlog", FLDT_UINT8D, OI(OFF(sectlog)), C1, 0, TYP_NONE }, { "inodelog", FLDT_UINT8D, OI(OFF(inodelog)), C1, 0, TYP_NONE }, { "inopblog", FLDT_UINT8D, OI(OFF(inopblog)), C1, 0, TYP_NONE }, { "agblklog", FLDT_UINT8D, OI(OFF(agblklog)), C1, 0, TYP_NONE }, { "rextslog", FLDT_UINT8D, OI(OFF(rextslog)), C1, 0, TYP_NONE }, { "inprogress", FLDT_UINT8D, OI(OFF(inprogress)), C1, 0, TYP_NONE }, { "imax_pct", FLDT_UINT8D, OI(OFF(imax_pct)), C1, 0, TYP_NONE }, { "icount", FLDT_UINT64D, OI(OFF(icount)), C1, 0, TYP_NONE }, { "ifree", FLDT_UINT64D, OI(OFF(ifree)), C1, 0, TYP_NONE }, { "fdblocks", FLDT_UINT64D, OI(OFF(fdblocks)), C1, 0, TYP_NONE }, { "frextents", FLDT_UINT64D, OI(OFF(frextents)), C1, 0, TYP_NONE }, { "uquotino", FLDT_INO, OI(OFF(uquotino)), C1, 0, TYP_INODE }, { "gquotino", FLDT_INO, OI(OFF(gquotino)), C1, 0, TYP_INODE }, { "qflags", FLDT_UINT16X, OI(OFF(qflags)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT8X, OI(OFF(flags)), C1, 0, TYP_NONE }, { "shared_vn", FLDT_UINT8D, OI(OFF(shared_vn)), C1, 0, TYP_NONE }, { "inoalignmt", FLDT_EXTLEN, OI(OFF(inoalignmt)), C1, 0, TYP_NONE }, { "unit", FLDT_UINT32D, OI(OFF(unit)), C1, 0, TYP_NONE }, { "width", FLDT_UINT32D, OI(OFF(width)), C1, 0, TYP_NONE }, { "dirblklog", FLDT_UINT8D, OI(OFF(dirblklog)), C1, 0, TYP_NONE }, { "logsectlog", FLDT_UINT8D, OI(OFF(logsectlog)), C1, 0, TYP_NONE }, { "logsectsize", FLDT_UINT16D, OI(OFF(logsectsize)), C1, 0, TYP_NONE }, { "logsunit", FLDT_UINT32D, OI(OFF(logsunit)), C1, 0, TYP_NONE }, { "features2", FLDT_UINT32X, OI(OFF(features2)), C1, 0, TYP_NONE }, { "bad_features2", FLDT_UINT32X, OI(OFF(bad_features2)), C1, 0, TYP_NONE }, { "features_compat", FLDT_UINT32X, OI(OFF(features_compat)), C1, 0, TYP_NONE }, { "features_ro_compat", FLDT_UINT32X, OI(OFF(features_ro_compat)), C1, 0, TYP_NONE }, { "features_incompat", FLDT_UINT32X, OI(OFF(features_incompat)), C1, 0, TYP_NONE }, { "features_log_incompat", FLDT_UINT32X, OI(OFF(features_log_incompat)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE }, { "spino_align", FLDT_EXTLEN, OI(OFF(spino_align)), C1, 0, TYP_NONE }, { "pquotino", FLDT_INO, OI(OFF(pquotino)), C1, 0, TYP_INODE }, { "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE }, { "meta_uuid", FLDT_UUID, OI(OFF(meta_uuid)), C1, 0, TYP_NONE }, { NULL } }; const field_t sb_hfld[] = { { "", FLDT_SB, OI(0), C1, 0, TYP_NONE }, { NULL } }; static void sb_help(void) { dbprintf(_( "\n" " set allocation group superblock\n" "\n" " Example:\n" "\n" " 'sb 7' - set location to 7th allocation group superblock, set type to 'sb'\n" "\n" " Located in the first sector of each allocation group, the superblock\n" " contains the base information for the filesystem.\n" " The superblock in allocation group 0 is the primary. The copies in the\n" " remaining allocation groups only serve as backup for filesystem recovery.\n" " The icount/ifree/fdblocks/frextents are only updated in superblock 0.\n" "\n" )); } static int sb_f( int argc, char **argv) { xfs_agnumber_t agno; char *p; if (argc > 1) { agno = (xfs_agnumber_t)strtoul(argv[1], &p, 0); if (*p != '\0' || agno >= mp->m_sb.sb_agcount) { dbprintf(_("bad allocation group number %s\n"), argv[1]); return 0; } cur_agno = agno; } else if (cur_agno == NULLAGNUMBER) cur_agno = 0; ASSERT(typtab[TYP_SB].typnm == TYP_SB); set_cur(&typtab[TYP_SB], XFS_AG_DADDR(mp, cur_agno, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), DB_RING_ADD, NULL); return 0; } /*ARGSUSED*/ int sb_size( void *obj, int startoff, int idx) { return bitize(mp->m_sb.sb_sectsize); } static int get_sb(xfs_agnumber_t agno, xfs_sb_t *sb) { push_cur(); set_cur(&typtab[TYP_SB], XFS_AG_DADDR(mp, agno, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL); if (!iocur_top->data) { dbprintf(_("can't read superblock for AG %u\n"), agno); pop_cur(); return 0; } libxfs_sb_from_disk(sb, iocur_top->data); if (sb->sb_magicnum != XFS_SB_MAGIC) { dbprintf(_("bad sb magic # %#x in AG %u\n"), sb->sb_magicnum, agno); return 0; } if (!xfs_sb_good_version(sb)) { dbprintf(_("bad sb version # %#x in AG %u\n"), sb->sb_versionnum, agno); return 0; } if (agno == 0 && sb->sb_inprogress != 0) { dbprintf(_("mkfs not completed successfully\n")); return 0; } return 1; } /* workaround craziness in the xlog routines */ int xlog_recover_do_trans(struct xlog *log, xlog_recover_t *t, int p) { return 0; } int sb_logcheck(void) { int dirty; if (mp->m_sb.sb_logstart) { if (x.logdev && x.logdev != x.ddev) { dbprintf(_("aborting - external log specified for FS " "with an internal log\n")); return 0; } } else { if (!x.logdev || (x.logdev == x.ddev)) { dbprintf(_("aborting - no external log specified for FS " "with an external log\n")); return 0; } } libxfs_buftarg_init(mp, x.ddev, x.logdev, x.rtdev); dirty = xlog_is_dirty(mp, mp->m_log, &x, 0); if (dirty == -1) { dbprintf(_("ERROR: cannot find log head/tail, run xfs_repair\n")); return 0; } else if (dirty == 1) { dbprintf(_( "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running %s. If you are unable to mount the filesystem, then use\n" "the xfs_repair -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n"), progname); return 0; } /* Log is clean */ return 1; } static int sb_logzero(uuid_t *uuidp) { int cycle = XLOG_INIT_CYCLE; int error; if (!sb_logcheck()) return 0; /* * The log must always move forward on v5 superblocks. Bump it to the * next cycle. */ if (xfs_sb_version_hascrc(&mp->m_sb)) cycle = mp->m_log->l_curr_cycle + 1; dbprintf(_("Clearing log and setting UUID\n")); error = libxfs_log_clear(mp->m_logdev_targp, NULL, XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart), (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks), uuidp, xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1, mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true); if (error) { dbprintf(_("ERROR: cannot clear the log\n")); return 0; } return 1; } static void uuid_help(void) { dbprintf(_( "\n" " write/print FS uuid\n" "\n" " Example:\n" "\n" " 'uuid' - print UUID\n" " 'uuid 01234567-0123-0123-0123-0123456789ab' - write UUID\n" " 'uuid generate' - generate and write\n" " 'uuid rewrite' - copy UUID from SB 0\n" "\n" "The print function checks the UUID in each SB and will warn if the UUIDs\n" "differ between AGs (the log is not checked). The write commands will\n" "set the uuid in all AGs to either a specified value, a newly generated\n" "value or the value found in the first superblock (SB 0) respectively.\n" "As a side effect of writing the UUID, the log is cleared (which is fine\n" "on a CLEANLY unmounted FS).\n" "\n" )); } static uuid_t * do_uuid(xfs_agnumber_t agno, uuid_t *uuid) { xfs_sb_t tsb; static uuid_t uu; if (!get_sb(agno, &tsb)) return NULL; if (!uuid) { /* get uuid */ memcpy(&uu, &tsb.sb_uuid, sizeof(uuid_t)); pop_cur(); return &uu; } /* set uuid */ if (!xfs_sb_version_hascrc(&tsb)) goto write; /* * If we have CRCs, and this UUID differs from that stamped in the * metadata, set the incompat flag and copy the old one to the * metadata-specific location. * * If we are setting the user-visible UUID back to match the metadata * UUID, clear the metadata-specific location and the incompat flag. */ if (!xfs_sb_version_hasmetauuid(&tsb) && !uuid_equal(uuid, &mp->m_sb.sb_meta_uuid)) { mp->m_sb.sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_META_UUID; tsb.sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_META_UUID; memcpy(&tsb.sb_meta_uuid, &tsb.sb_uuid, sizeof(uuid_t)); } else if (xfs_sb_version_hasmetauuid(&tsb) && uuid_equal(uuid, &mp->m_sb.sb_meta_uuid)) { memset(&tsb.sb_meta_uuid, 0, sizeof(uuid_t)); /* Write those zeros now; it's ignored once we clear the flag */ libxfs_sb_to_disk(iocur_top->data, &tsb); mp->m_sb.sb_features_incompat &= ~XFS_SB_FEAT_INCOMPAT_META_UUID; tsb.sb_features_incompat &= ~XFS_SB_FEAT_INCOMPAT_META_UUID; } write: memcpy(&tsb.sb_uuid, uuid, sizeof(uuid_t)); libxfs_sb_to_disk(iocur_top->data, &tsb); write_cur(); return uuid; } static int uuid_f( int argc, char **argv) { char bp[40]; xfs_agnumber_t agno; uuid_t uu; uuid_t *uup = NULL; if (argc != 1 && argc != 2) { dbprintf(_("invalid parameters\n")); return 0; } if (argc == 2) { /* WRITE UUID */ if ((x.isreadonly & LIBXFS_ISREADONLY) || !expert_mode) { dbprintf(_("%s: not in expert mode, writing disabled\n"), progname); return 0; } if (!strcasecmp(argv[1], "generate")) { platform_uuid_generate(&uu); } else if (!strcasecmp(argv[1], "nil")) { platform_uuid_clear(&uu); } else if (!strcasecmp(argv[1], "rewrite")) { uup = do_uuid(0, NULL); if (!uup) { dbprintf(_("failed to read UUID from AG 0\n")); return 0; } memcpy(&uu, uup, sizeof(uuid_t)); platform_uuid_unparse(&uu, bp); dbprintf(_("old UUID = %s\n"), bp); } else if (!strcasecmp(argv[1], "restore")) { xfs_sb_t tsb; if (!get_sb(0, &tsb)) return 0; /* Not set; nothing to do. Success! */ if (!xfs_sb_version_hasmetauuid(&tsb)) return 0; memcpy(&uu, mp->m_sb.sb_meta_uuid, sizeof(uuid_t)); } else { if (platform_uuid_parse(argv[1], &uu)) { dbprintf(_("invalid UUID\n")); return 0; } } /* clear the log (setting uuid) if it's not dirty */ if (!sb_logzero(&uu)) return 0; dbprintf(_("writing all SBs\n")); for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) if (!do_uuid(agno, &uu)) { dbprintf(_("failed to set UUID in AG %d\n"), agno); break; } platform_uuid_unparse(&uu, bp); dbprintf(_("new UUID = %s\n"), bp); return 0; } else { /* READ+CHECK UUID */ for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { uup = do_uuid(agno, NULL); if (!uup) { dbprintf(_("failed to read UUID from AG %d\n"), agno); return 0; } if (agno) { if (memcmp(&uu, uup, sizeof(uuid_t))) { dbprintf(_("warning: UUID in AG %d " "differs to the primary SB\n"), agno); break; } } else { memcpy(&uu, uup, sizeof(uuid_t)); } } if (mp->m_sb.sb_logstart) { if (x.logdev && x.logdev != x.ddev) dbprintf(_("warning - external log specified " "for FS with an internal log\n")); } else if (!x.logdev || (x.logdev == x.ddev)) { dbprintf(_("warning - no external log specified " "for FS with an external log\n")); } platform_uuid_unparse(&uu, bp); dbprintf(_("UUID = %s\n"), bp); } return 0; } static void label_help(void) { dbprintf(_( "\n" " write/print FS label\n" "\n" " Example:\n" "\n" " 'label' - print label\n" " 'label 123456789012' - write label\n" " 'label --' - write an empty label\n" "\n" "The print function checks the label in each SB and will warn if the labels\n" "differ between AGs. The write commands will set the label in all AGs to the\n" "specified value. The maximum length of a label is 12 characters - use of a\n" "longer label will result in truncation and a warning will be issued.\n" "\n" )); } static char * do_label(xfs_agnumber_t agno, char *label) { size_t len; xfs_sb_t tsb; static char lbl[sizeof(tsb.sb_fname) + 1]; if (!get_sb(agno, &tsb)) return NULL; memset(&lbl[0], 0, sizeof(lbl)); if (!label) { /* get label */ pop_cur(); memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname)); return &lbl[0]; } /* set label */ if ((len = strlen(label)) > sizeof(tsb.sb_fname)) { if (agno == 0) dbprintf(_("%s: truncating label length from %d to %d\n"), progname, (int)len, (int)sizeof(tsb.sb_fname)); len = sizeof(tsb.sb_fname); } if ( len == 2 && (strcmp(label, "\"\"") == 0 || strcmp(label, "''") == 0 || strcmp(label, "--") == 0) ) label[0] = label[1] = '\0'; memset(&tsb.sb_fname, 0, sizeof(tsb.sb_fname)); memcpy(&tsb.sb_fname, label, len); memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname)); libxfs_sb_to_disk(iocur_top->data, &tsb); write_cur(); return &lbl[0]; } static int label_f( int argc, char **argv) { char *p = NULL; xfs_sb_t sb; xfs_agnumber_t ag; if (argc != 1 && argc != 2) { dbprintf(_("invalid parameters\n")); return 0; } if (argc == 2) { /* WRITE LABEL */ if ((x.isreadonly & LIBXFS_ISREADONLY) || !expert_mode) { dbprintf(_("%s: not in expert mode, writing disabled\n"), progname); return 0; } dbprintf(_("writing all SBs\n")); for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) if ((p = do_label(ag, argv[1])) == NULL) { dbprintf(_("failed to set label in AG %d\n"), ag); break; } dbprintf(_("new label = \"%s\"\n"), p); } else { /* READ LABEL */ for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { p = do_label(ag, NULL); if (!p) { dbprintf(_("failed to read label in AG %d\n"), ag); return 0; } if (!ag) memcpy(&sb.sb_fname, p, sizeof(sb.sb_fname)); else if (memcmp(&sb.sb_fname, p, sizeof(sb.sb_fname))) dbprintf(_("warning: AG %d label differs\n"), ag); } dbprintf(_("label = \"%s\"\n"), p); } return 0; } static void version_help(void) { dbprintf(_( "\n" " set/print feature bits in sb version\n" "\n" " Example:\n" "\n" " 'version' - print current feature bits\n" " 'version extflg' - enable unwritten extents\n" " 'version attr1' - enable v1 inline extended attributes\n" " 'version attr2' - enable v2 inline extended attributes\n" " 'version log2' - enable v2 log format\n" "\n" "The version function prints currently enabled features for a filesystem\n" "according to the version field of its primary superblock.\n" "It can also be used to enable selected features, such as support for\n" "unwritten extents. The updated version is written into all AGs.\n" "\n" )); } static int do_version(xfs_agnumber_t agno, __uint16_t version, __uint32_t features) { xfs_sb_t tsb; if (!get_sb(agno, &tsb)) return 0; if (xfs_sb_has_mismatched_features2(&tsb)) { dbprintf(_("Superblock has mismatched features2 fields, " "skipping modification\n")); return 0; } if ((version & XFS_SB_VERSION_LOGV2BIT) && !xfs_sb_version_haslogv2(&tsb)) { tsb.sb_logsunit = 1; } tsb.sb_versionnum = version; tsb.sb_features2 = features; tsb.sb_bad_features2 = features; libxfs_sb_to_disk(iocur_top->data, &tsb); write_cur(); return 1; } static char * version_string( xfs_sb_t *sbp) { static char s[1024]; if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_1) strcpy(s, "V1"); else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_2) strcpy(s, "V2"); else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_3) strcpy(s, "V3"); else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) strcpy(s, "V4"); else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) strcpy(s, "V5"); /* * We assume the state of these features now, so macros don't exist for * them any more. */ if (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT) strcat(s, ",NLINK"); if (sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) strcat(s, ",SHARED"); if (sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT) strcat(s, ",DIRV2"); if (xfs_sb_version_hasattr(sbp)) strcat(s, ",ATTR"); if (xfs_sb_version_hasquota(sbp)) strcat(s, ",QUOTA"); if (xfs_sb_version_hasalign(sbp)) strcat(s, ",ALIGN"); if (xfs_sb_version_hasdalign(sbp)) strcat(s, ",DALIGN"); if (xfs_sb_version_haslogv2(sbp)) strcat(s, ",LOGV2"); if (xfs_sb_version_hasextflgbit(sbp)) strcat(s, ",EXTFLG"); if (xfs_sb_version_hassector(sbp)) strcat(s, ",SECTOR"); if (xfs_sb_version_hasasciici(sbp)) strcat(s, ",ASCII_CI"); if (xfs_sb_version_hasmorebits(sbp)) strcat(s, ",MOREBITS"); if (xfs_sb_version_hasattr2(sbp)) strcat(s, ",ATTR2"); if (xfs_sb_version_haslazysbcount(sbp)) strcat(s, ",LAZYSBCOUNT"); if (xfs_sb_version_hasprojid32bit(sbp)) strcat(s, ",PROJID32BIT"); if (xfs_sb_version_hascrc(sbp)) strcat(s, ",CRC"); if (xfs_sb_version_hasftype(sbp)) strcat(s, ",FTYPE"); if (xfs_sb_version_hasfinobt(sbp)) strcat(s, ",FINOBT"); if (xfs_sb_version_hassparseinodes(sbp)) strcat(s, ",SPARSE_INODES"); if (xfs_sb_version_hasmetauuid(sbp)) strcat(s, ",META_UUID"); if (xfs_sb_version_hasreflink(sbp)) strcat(s, ",REFLINK"); return s; } /* * XXX: this only supports reading and writing to version 4 superblock fields. * V5 superblocks always define certain V4 feature bits - they are blocked from * being changed if a V5 sb is detected, but otherwise v5 superblock features * are not handled here. */ static int version_f( int argc, char **argv) { __uint16_t version = 0; __uint32_t features = 0; xfs_agnumber_t ag; if (argc == 2) { /* WRITE VERSION */ if ((x.isreadonly & LIBXFS_ISREADONLY) || !expert_mode) { dbprintf(_("%s: not in expert mode, writing disabled\n"), progname); return 0; } /* Logic here derived from the IRIX xfs_chver(1M) script. */ if (!strcasecmp(argv[1], "extflg")) { switch (XFS_SB_VERSION_NUM(&mp->m_sb)) { case XFS_SB_VERSION_1: version = 0x0004 | XFS_SB_VERSION_EXTFLGBIT; break; case XFS_SB_VERSION_2: version = 0x0014 | XFS_SB_VERSION_EXTFLGBIT; break; case XFS_SB_VERSION_3: version = 0x0034 | XFS_SB_VERSION_EXTFLGBIT; break; case XFS_SB_VERSION_4: if (xfs_sb_version_hasextflgbit(&mp->m_sb)) dbprintf( _("unwritten extents flag is already enabled\n")); else version = mp->m_sb.sb_versionnum | XFS_SB_VERSION_EXTFLGBIT; break; case XFS_SB_VERSION_5: dbprintf( _("unwritten extents always enabled for v5 superblocks.\n")); break; } } else if (!strcasecmp(argv[1], "log2")) { switch (XFS_SB_VERSION_NUM(&mp->m_sb)) { case XFS_SB_VERSION_1: version = 0x0004 | XFS_SB_VERSION_LOGV2BIT; break; case XFS_SB_VERSION_2: version = 0x0014 | XFS_SB_VERSION_LOGV2BIT; break; case XFS_SB_VERSION_3: version = 0x0034 | XFS_SB_VERSION_LOGV2BIT; break; case XFS_SB_VERSION_4: if (xfs_sb_version_haslogv2(&mp->m_sb)) dbprintf( _("version 2 log format is already in use\n")); else version = mp->m_sb.sb_versionnum | XFS_SB_VERSION_LOGV2BIT; break; case XFS_SB_VERSION_5: dbprintf( _("Version 2 logs always enabled for v5 superblocks.\n")); break; } } else if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5) { dbprintf( _("%s: Cannot change %s on v5 superblocks.\n"), progname, argv[1]); return 0; } else if (!strcasecmp(argv[1], "attr1")) { if (xfs_sb_version_hasattr2(&mp->m_sb)) { if (!(mp->m_sb.sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT)) mp->m_sb.sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT; } xfs_sb_version_addattr(&mp->m_sb); version = mp->m_sb.sb_versionnum; features = mp->m_sb.sb_features2; } else if (!strcasecmp(argv[1], "attr2")) { xfs_sb_version_addattr(&mp->m_sb); xfs_sb_version_addattr2(&mp->m_sb); version = mp->m_sb.sb_versionnum; features = mp->m_sb.sb_features2; } else if (!strcasecmp(argv[1], "projid32bit")) { xfs_sb_version_addprojid32bit(&mp->m_sb); version = mp->m_sb.sb_versionnum; features = mp->m_sb.sb_features2; } else { dbprintf(_("%s: invalid version change command \"%s\"\n"), progname, argv[1]); return 0; } if (version) { dbprintf(_("writing all SBs\n")); for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) if (!do_version(ag, version, features)) { dbprintf(_("failed to set versionnum " "in AG %d\n"), ag); break; } mp->m_sb.sb_versionnum = version; mp->m_sb.sb_features2 = features; } } if (argc == 3) { /* VERSIONNUM + FEATURES2 */ char *sp; version = mp->m_sb.sb_versionnum; features = mp->m_sb.sb_features2; mp->m_sb.sb_versionnum = strtoul(argv[1], &sp, 0); mp->m_sb.sb_features2 = strtoul(argv[2], &sp, 0); } dbprintf(_("versionnum [0x%x+0x%x] = %s\n"), mp->m_sb.sb_versionnum, mp->m_sb.sb_features2, version_string(&mp->m_sb)); if (argc == 3) { /* now reset... */ mp->m_sb.sb_versionnum = version; mp->m_sb.sb_features2 = features; return 0; } return 0; } xfsprogs-4.9.0+nmu1ubuntu2/db/sb.h0000644000000000000000000000162213063067170013634 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern const struct field sb_flds[]; extern const struct field sb_hfld[]; extern void sb_init(void); extern int sb_logcheck(void); extern int sb_size(void *obj, int startoff, int idx); xfsprogs-4.9.0+nmu1ubuntu2/db/sig.c0000644000000000000000000000244313063067167014015 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include "sig.h" static int gotintr; static sigset_t intrset; static void interrupt(int sig, siginfo_t *info, void *uc) { gotintr = 1; } void blockint(void) { sigprocmask(SIG_BLOCK, &intrset, NULL); } void clearint(void) { gotintr = 0; } void init_sig(void) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = interrupt; sigaction(SIGINT, &sa, NULL); sigemptyset(&intrset); sigaddset(&intrset, SIGINT); } int seenint(void) { return gotintr; } void unblockint(void) { sigprocmask(SIG_UNBLOCK, &intrset, NULL); } xfsprogs-4.9.0+nmu1ubuntu2/db/sig.h0000644000000000000000000000154413063067170014015 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void blockint(void); extern void clearint(void); extern void init_sig(void); extern int seenint(void); extern void unblockint(void); xfsprogs-4.9.0+nmu1ubuntu2/db/strvec.c0000644000000000000000000000327613063067170014540 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "strvec.h" #include "output.h" #include "malloc.h" static int count_strvec(char **vec); void add_strvec( char ***vecp, char *str) { char *dup; int i; char **vec; dup = xstrdup(str); vec = *vecp; i = count_strvec(vec); vec = xrealloc(vec, sizeof(*vec) * (i + 2)); vec[i] = dup; vec[i + 1] = NULL; *vecp = vec; } char ** copy_strvec( char **vec) { int i; char **rval; i = count_strvec(vec); rval = new_strvec(i); for (i = 0; vec[i] != NULL; i++) rval[i] = xstrdup(vec[i]); return rval; } static int count_strvec( char **vec) { int i; for (i = 0; vec[i] != NULL; i++) continue; return i; } void free_strvec( char **vec) { int i; for (i = 0; vec[i] != NULL; i++) xfree(vec[i]); xfree(vec); } char ** new_strvec( int count) { char **rval; rval = xmalloc(sizeof(*rval) * (count + 1)); rval[count] = NULL; return rval; } void print_strvec( char **vec) { int i; for (i = 0; vec[i] != NULL; i++) dbprintf("%s", vec[i]); } xfsprogs-4.9.0+nmu1ubuntu2/db/strvec.h0000644000000000000000000000164013063067170014536 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void add_strvec(char ***vecp, char *str); extern char **copy_strvec(char **vec); extern void free_strvec(char **vec); extern char **new_strvec(int count); extern void print_strvec(char **vec); xfsprogs-4.9.0+nmu1ubuntu2/db/symlink.c0000644000000000000000000000447613063067170014723 0ustar /* * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "bit.h" #include "init.h" /* * XXX: no idea how to handle multiple contiguous block symlinks here. */ static int symlink_count( void *obj, int startoff) { struct xfs_dsymlink_hdr *hdr = obj; ASSERT(startoff == 0); if (hdr->sl_magic != cpu_to_be32(XFS_SYMLINK_MAGIC)) return 0; if (be32_to_cpu(hdr->sl_bytes) + sizeof(*hdr) > mp->m_sb.sb_blocksize) return mp->m_sb.sb_blocksize - sizeof(*hdr); return be32_to_cpu(hdr->sl_bytes); } int symlink_size( void *obj, int startoff, int idx) { struct xfs_dsymlink_hdr *hdr = obj; ASSERT(startoff == 0); if (hdr->sl_magic != cpu_to_be32(XFS_SYMLINK_MAGIC)) return 0; return be32_to_cpu(hdr->sl_bytes) + sizeof(*hdr); } const struct field symlink_crc_hfld[] = { { "", FLDT_SYMLINK_CRC, OI(0), C1, 0, TYP_NONE }, { NULL } }; #define OFF(f) bitize(offsetof(struct xfs_dsymlink_hdr, sl_ ## f)) #define SZOF(f) bitize(sizeof(struct xfs_dsymlink_hdr)) const struct field symlink_crc_flds[] = { { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, { "offset", FLDT_UINT32D, OI(OFF(offset)), C1, 0, TYP_NONE }, { "bytes", FLDT_UINT32D, OI(OFF(bytes)), C1, 0, TYP_NONE }, { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE }, { "owner", FLDT_INO, OI(OFF(owner)), C1, 0, TYP_NONE }, { "bno", FLDT_DFSBNO, OI(OFF(blkno)), C1, 0, TYP_BMAPBTD }, { "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE }, { "data", FLDT_CHARNS, OI(bitize(sizeof(struct xfs_dsymlink_hdr))), symlink_count, FLD_COUNT, TYP_NONE }, { NULL } }; xfsprogs-4.9.0+nmu1ubuntu2/db/symlink.h0000644000000000000000000000166413063067170014724 0ustar /* * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_DB_SYMLINK_H #define __XFS_DB_SYMLINK_H extern const struct field symlink_crc_hfld[]; extern const struct field symlink_crc_flds[]; extern int symlink_size(void *obj, int startoff, int idx); #endif /* __XFS_DB_SYMLINK_H */ xfsprogs-4.9.0+nmu1ubuntu2/db/text.c0000644000000000000000000000351513063067170014212 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include "block.h" #include "bmap.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "inode.h" #include "io.h" #include "output.h" #include "init.h" static void print_rawtext(void *data, int len); void print_text( const field_t *fields, int argc, char **argv) { print_rawtext(iocur_top->data, iocur_top->len); } static void print_rawtext( void *data, int len) { int i; int j; int lastaddr; int offchars; unsigned char *p; lastaddr = (len - 1) & ~(16 - 1); if (lastaddr < 0x10) offchars = 1; else if (lastaddr < 0x100) offchars = 2; else if (lastaddr < 0x1000) offchars = 3; else offchars = 4; for (i = 0, p = data; i < len; i += 16) { unsigned char *s = p; dbprintf("%-0*.*x: ", offchars, offchars, i); for (j = 0; j < 16 && i + j < len; j++, p++) { dbprintf("%02x ", *p); } dbprintf(" "); for (j = 0; j < 16 && i + j < len; j++, s++) { if (isalnum(*s)) dbprintf("%c", *s); else dbprintf(".", *s); } dbprintf("\n"); } } xfsprogs-4.9.0+nmu1ubuntu2/db/text.h0000644000000000000000000000144713063067170014221 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern void print_text(const struct field *fields, int argc, char **argv); xfsprogs-4.9.0+nmu1ubuntu2/db/type.c0000644000000000000000000002235113063067170014206 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "block.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "print.h" #include "sb.h" #include "inode.h" #include "btblock.h" #include "bmroot.h" #include "agf.h" #include "agfl.h" #include "agi.h" #include "io.h" #include "output.h" #include "write.h" #include "attr.h" #include "dquot.h" #include "dir2.h" #include "text.h" #include "symlink.h" static const typ_t *findtyp(char *name); static int type_f(int argc, char **argv); const typ_t *cur_typ; static const cmdinfo_t type_cmd = { "type", NULL, type_f, 0, 1, 1, N_("[newtype]"), N_("set/show current data type"), NULL }; static const typ_t __typtab[] = { { TYP_AGF, "agf", handle_struct, agf_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_AGFL, "agfl", handle_struct, agfl_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_AGI, "agi", handle_struct, agi_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_ATTR, "attr", handle_struct, attr_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_RMAPBT, NULL }, { TYP_REFCBT, NULL }, { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_DIR2, "dir2", handle_struct, dir2_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_INOBT, "inobt", handle_struct, inobt_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_INODATA, "inodata", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_INODE, "inode", handle_struct, inode_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_LOG, "log", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_RTBITMAP, "rtbitmap", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_RTSUMMARY, "rtsummary", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_SB, "sb", handle_struct, sb_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_SYMLINK, "symlink", handle_string, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_TEXT, "text", handle_text, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_FINOBT, "finobt", handle_struct, inobt_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_NONE, NULL } }; static const typ_t __typtab_crc[] = { { TYP_AGF, "agf", handle_struct, agf_hfld, &xfs_agf_buf_ops, XFS_AGF_CRC_OFF }, { TYP_AGFL, "agfl", handle_struct, agfl_crc_hfld, &xfs_agfl_buf_ops, XFS_AGFL_CRC_OFF }, { TYP_AGI, "agi", handle_struct, agi_hfld, &xfs_agi_buf_ops, XFS_AGI_CRC_OFF }, { TYP_ATTR, "attr3", handle_struct, attr3_hfld, &xfs_attr3_db_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_crc_hfld, &xfs_bmbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_crc_hfld, &xfs_bmbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_BNOBT, "bnobt", handle_struct, bnobt_crc_hfld, &xfs_allocbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_crc_hfld, &xfs_allocbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, &xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld, &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, &xfs_dquot_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_INOBT, "inobt", handle_struct, inobt_crc_hfld, &xfs_inobt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_INODATA, "inodata", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_INODE, "inode", handle_struct, inode_crc_hfld, &xfs_inode_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_LOG, "log", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_RTBITMAP, "rtbitmap", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_RTSUMMARY, "rtsummary", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_SB, "sb", handle_struct, sb_hfld, &xfs_sb_buf_ops, XFS_SB_CRC_OFF }, { TYP_SYMLINK, "symlink", handle_struct, symlink_crc_hfld, &xfs_symlink_buf_ops, XFS_SYMLINK_CRC_OFF }, { TYP_TEXT, "text", handle_text, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_FINOBT, "finobt", handle_struct, inobt_crc_hfld, &xfs_inobt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_NONE, NULL } }; static const typ_t __typtab_spcrc[] = { { TYP_AGF, "agf", handle_struct, agf_hfld, &xfs_agf_buf_ops, XFS_AGF_CRC_OFF }, { TYP_AGFL, "agfl", handle_struct, agfl_crc_hfld, &xfs_agfl_buf_ops , XFS_AGFL_CRC_OFF }, { TYP_AGI, "agi", handle_struct, agi_hfld, &xfs_agi_buf_ops , XFS_AGI_CRC_OFF }, { TYP_ATTR, "attr3", handle_struct, attr3_hfld, &xfs_attr3_db_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_crc_hfld, &xfs_bmbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_crc_hfld, &xfs_bmbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_BNOBT, "bnobt", handle_struct, bnobt_crc_hfld, &xfs_allocbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_crc_hfld, &xfs_allocbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, &xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld, &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, &xfs_dquot_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_INOBT, "inobt", handle_struct, inobt_spcrc_hfld, &xfs_inobt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_INODATA, "inodata", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_INODE, "inode", handle_struct, inode_crc_hfld, &xfs_inode_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_LOG, "log", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_RTBITMAP, "rtbitmap", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_RTSUMMARY, "rtsummary", NULL, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_SB, "sb", handle_struct, sb_hfld, &xfs_sb_buf_ops, XFS_SB_CRC_OFF }, { TYP_SYMLINK, "symlink", handle_struct, symlink_crc_hfld, &xfs_symlink_buf_ops, XFS_SYMLINK_CRC_OFF }, { TYP_TEXT, "text", handle_text, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_FINOBT, "finobt", handle_struct, inobt_crc_hfld, &xfs_inobt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_NONE, NULL } }; const typ_t *typtab = __typtab; void type_set_tab_crc(void) { typtab = __typtab_crc; } void type_set_tab_spcrc(void) { typtab = __typtab_spcrc; } static const typ_t * findtyp( char *name) { const typ_t *tt; for (tt = typtab; tt->typnm != TYP_NONE; tt++) { ASSERT(tt->typnm == (typnm_t)(tt - typtab)); if (tt->name && strcmp(tt->name, name) == 0) return tt; } return NULL; } static int type_f( int argc, char **argv) { const typ_t *tt; int count = 0; if (argc == 1) { if (cur_typ == NULL) dbprintf(_("no current type\n")); else dbprintf(_("current type is \"%s\"\n"), cur_typ->name); dbprintf(_("\n supported types are:\n ")); for (tt = typtab, count = 0; tt->typnm != TYP_NONE; tt++) { if (tt->name == NULL) continue; if ((tt+1)->name != NULL) { dbprintf("%s, ", tt->name); if ((++count % 8) == 0) dbprintf("\n "); } else if ((tt+1)->typnm == TYP_NONE) { dbprintf("%s\n", tt->name); } } } else { tt = findtyp(argv[1]); if (tt == NULL) { dbprintf(_("no such type %s\n"), argv[1]); } else { if (iocur_top->typ == NULL) dbprintf(_("no current object\n")); else { cur_typ = tt; set_iocur_type(tt); } } } return 0; } void type_init(void) { add_command(&type_cmd); } /* read/write selectors for each major data type */ void handle_struct( int action, const field_t *fields, int argc, char **argv) { if (action == DB_WRITE) write_struct(fields, argc, argv); else print_struct(fields, argc, argv); } void handle_string( int action, const field_t *fields, int argc, char **argv) { if (action == DB_WRITE) write_string(fields, argc, argv); else print_string(fields, argc, argv); } void handle_block( int action, const field_t *fields, int argc, char **argv) { if (action == DB_WRITE) write_block(fields, argc, argv); else print_block(fields, argc, argv); } void handle_text( int action, const field_t *fields, int argc, char **argv) { if (action != DB_WRITE) print_text(fields, argc, argv); } xfsprogs-4.9.0+nmu1ubuntu2/db/type.h0000644000000000000000000000402113063067167014213 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ struct field; #define szof(x,y) sizeof(((x *)0)->y) #define szcount(x,y) (szof(x,y) / szof(x,y[0])) typedef enum typnm { TYP_AGF, TYP_AGFL, TYP_AGI, TYP_ATTR, TYP_BMAPBTA, TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_RMAPBT, TYP_REFCBT, TYP_DATA, TYP_DIR2, TYP_DQBLK, TYP_INOBT, TYP_INODATA, TYP_INODE, TYP_LOG, TYP_RTBITMAP, TYP_RTSUMMARY, TYP_SB, TYP_SYMLINK, TYP_TEXT, TYP_FINOBT, TYP_NONE } typnm_t; #define DB_WRITE 1 #define DB_READ 0 typedef void (*opfunc_t)(const struct field *fld, int argc, char **argv); typedef void (*pfunc_t)(int action, const struct field *fld, int argc, char **argv); typedef struct typ { typnm_t typnm; char *name; pfunc_t pfunc; const struct field *fields; const struct xfs_buf_ops *bops; unsigned long crc_off; #define TYP_F_NO_CRC_OFF (-1UL) } typ_t; extern const typ_t *typtab, *cur_typ; extern void type_init(void); extern void type_set_tab_crc(void); extern void type_set_tab_spcrc(void); extern void handle_block(int action, const struct field *fields, int argc, char **argv); extern void handle_string(int action, const struct field *fields, int argc, char **argv); extern void handle_struct(int action, const struct field *fields, int argc, char **argv); extern void handle_text(int action, const struct field *fields, int argc, char **argv); xfsprogs-4.9.0+nmu1ubuntu2/db/write.c0000644000000000000000000004344513063067170014366 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include #include "bit.h" #include "block.h" #include "command.h" #include "type.h" #include "faddr.h" #include "fprint.h" #include "field.h" #include "flist.h" #include "io.h" #include "init.h" #include "output.h" #include "print.h" #include "write.h" #include "malloc.h" static int write_f(int argc, char **argv); static void write_help(void); static const cmdinfo_t write_cmd = { "write", NULL, write_f, 0, -1, 0, N_("[-c] [field or value]..."), N_("write value to disk"), write_help }; void write_init(void) { if (!expert_mode) return; add_command(&write_cmd); srand48(clock()); } static void write_help(void) { dbprintf(_( "\n" " The 'write' command takes on different personalities depending on the\n" " type of object being worked with.\n\n" " Write has 3 modes:\n" " 'struct mode' - is active anytime you're looking at a filesystem object\n" " which contains individual fields (ex: an inode).\n" " 'data mode' - is active anytime you set a disk address directly or set\n" " the type to 'data'.\n" " 'string mode' - only used for writing symlink blocks.\n" "\n" " Examples:\n" " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n" " 'write fname \"hello\\000\"' - write superblock fname.\n" " (note: in struct mode strings are not null terminated)\n" " 'write fname #6669736800' - write superblock fname with hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - write superblock uuid.\n" " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n" " 'write lshift 3' - shift the block 3 bytes to the left\n" " 'write sequence 1 5' - write a cycle of number [1-5] through\n" " the entire block.\n" " String mode: 'write \"This_is_a_filename\" - write null terminated string.\n" "\n" " In data mode type 'write' by itself for a list of specific commands.\n\n" " Specifying the -c option will allow writes of invalid (corrupt) data with\n" " an invalid CRC. Specifying the -d option will allow writes of invalid data,\n" " but still recalculate the CRC so we are forced to check and detect the\n" " invalid data appropriately.\n\n" )); } static int write_f( int argc, char **argv) { pfunc_t pf; extern char *progname; int c; bool corrupt = false; /* Allow write of bad data w/ invalid CRC */ bool invalid_data = false; /* Allow write of bad data w/ valid CRC */ struct xfs_buf_ops local_ops; const struct xfs_buf_ops *stashed_ops = NULL; if (x.isreadonly & LIBXFS_ISREADONLY) { dbprintf(_("%s started in read only mode, writing disabled\n"), progname); return 0; } if (cur_typ == NULL) { dbprintf(_("no current type\n")); return 0; } pf = cur_typ->pfunc; if (pf == NULL) { dbprintf(_("no handler function for type %s, write unsupported.\n"), cur_typ->name); return 0; } while ((c = getopt(argc, argv, "cd")) != EOF) { switch (c) { case 'c': corrupt = true; break; case 'd': invalid_data = true; break; default: dbprintf(_("bad option for write command\n")); return 0; } } if (corrupt && invalid_data) { dbprintf(_("Cannot specify both -c and -d options\n")); return 0; } if (invalid_data && iocur_top->typ->crc_off == TYP_F_NO_CRC_OFF) { dbprintf(_("Cannot recalculate CRCs on this type of object\n")); return 0; } argc -= optind; argv += optind; /* * If the buffer has no verifier or we are using standard verifier * paths, then just write it out and return */ if (!iocur_top->bp->b_ops || !(corrupt || invalid_data)) { (*pf)(DB_WRITE, cur_typ->fields, argc, argv); return 0; } /* Temporarily remove write verifier to write bad data */ stashed_ops = iocur_top->bp->b_ops; local_ops.verify_read = stashed_ops->verify_read; iocur_top->bp->b_ops = &local_ops; if (corrupt) { local_ops.verify_write = xfs_dummy_verify; dbprintf(_("Allowing write of corrupted data and bad CRC\n")); } else { /* invalid data */ local_ops.verify_write = xfs_verify_recalc_crc; dbprintf(_("Allowing write of corrupted data with good CRC\n")); } (*pf)(DB_WRITE, cur_typ->fields, argc, argv); iocur_top->bp->b_ops = stashed_ops; return 0; } /* compare significant portions of commands */ static int sigcmp( char *s1, char *s2, int sig) { int sigcnt; if (!s1 || !s2) return 0; for (sigcnt = 0; *s1 == *s2; s1++, s2++) { sigcnt++; if (*s1 == '\0') return 1; } if (*s1 && *s2) return 0; if (sig && (sigcnt >= sig)) return 1; return 0; } /* ARGSUSED */ static void bwrite_lshift( int start, int len, int shift, int from, int to) { char *base; if (shift == -1) shift = 1; if (start == -1) start = 0; if (len == -1) len = iocur_top->len - start; if (len+start > iocur_top->len) { dbprintf(_("length (%d) too large for data block size (%d)"), len, iocur_top->len); } base = (char *)iocur_top->data + start; memcpy(base, base+shift, len-shift); memset(base+(len-shift), 0, shift); } /* ARGSUSED */ static void bwrite_rshift( int start, int len, int shift, int from, int to) { char *base; if (shift == -1) shift = 1; if (start == -1) start = 0; if (len == -1) len = iocur_top->len - start; if (len+start > iocur_top->len) { dbprintf(_("length (%d) too large for data block size (%d)"), len, iocur_top->len); } base = (char *)iocur_top->data + start; memcpy(base+shift, base, len-shift); memset(base, 0, shift); } /* ARGSUSED */ static void bwrite_lrot( int start, int len, int shift, int from, int to) { char *base; char *hold_region; if (shift == -1) shift = 1; if (start == -1) start = 0; if (len == -1) len = iocur_top->len - start; if (len+start > iocur_top->len) { dbprintf(_("length (%d) too large for data block size (%d)"), len, iocur_top->len); } base = (char *)iocur_top->data + start; hold_region = xmalloc(shift); memcpy(hold_region, base, shift); memcpy(base, base+shift, len-shift); memcpy(base+(len-shift), hold_region, shift); free(hold_region); } /* ARGSUSED */ static void bwrite_rrot( int start, int len, int shift, int from, int to) { char *base; char *hold_region; if (shift == -1) shift = 1; if (start == -1) start = 0; if (len == -1) len = iocur_top->len - start; if (len+start > iocur_top->len) { dbprintf(_("length (%d) too large for data block size (%d)"), len, iocur_top->len); } base = (char *)iocur_top->data + start; hold_region = xmalloc(shift); memcpy(hold_region, base+(len-shift), shift); memmove(base+shift, base, len-shift); memcpy(base, hold_region, shift); free(hold_region); } /* ARGSUSED */ static void bwrite_seq( int start, int len, int step, int from, int to) { int i; int tmp; int base; int range; int top; char *buf; if (start == -1) start = 0; if (len == -1) len = iocur_top->len - start; if (len+start > iocur_top->len) { dbprintf(_("length (%d) too large for data block size (%d)"), len, iocur_top->len); } if (from == -1 || from > 255) from = 0; if (to == -1 || to > 255) to = 255; if (step == -1) step = 1; base = from; top = to; if (from > to) { base = to; top = from; if (step > 0) step = -step; } range = top - base; buf = (char *)iocur_top->data + start; tmp = 0; for (i = start; i < start+len; i++) { *buf++ = tmp + base; tmp = (tmp + step)%(range+1); } } /* ARGSUSED */ static void bwrite_random( int start, int len, int shift, int from, int to) { int i; char *buf; if (start == -1) start = 0; if (len == -1) len = iocur_top->len - start; if (len+start > iocur_top->len) { dbprintf(_("length (%d) too large for data block size (%d)"), len, iocur_top->len); } buf = (char *)iocur_top->data + start; for (i = start; i < start+len; i++) *buf++ = (char)lrand48(); } /* ARGSUSED */ static void bwrite_fill( int start, int len, int value, int from, int to) { char *base; if (value == -1) value = 0; if (start == -1) start = 0; if (len == -1) len = iocur_top->len - start; if (len+start > iocur_top->len) { dbprintf(_("length (%d) too large for data block size (%d)"), len, iocur_top->len); } base = (char *)iocur_top->data + start; memset(base, value, len); } static struct bw_cmd { void (*cmdfunc)(int,int,int,int,int); char *cmdstr; int sig_chars; int argmin; int argmax; int shiftcount_arg; int from_arg; int to_arg; int start_arg; int len_arg; char *usage; } bw_cmdtab[] = { /* cmd sig min max sh frm to start len */ { bwrite_lshift, "lshift", 2, 0, 3, 1, 0, 0, 2, 3, "[shiftcount] [start] [len]", }, { bwrite_rshift, "rshift", 2, 0, 3, 1, 0, 0, 2, 3, "[shiftcount] [start] [len]", }, { bwrite_lrot, "lrot", 2, 0, 3, 1, 0, 0, 2, 3, "[shiftcount] [start] [len]", }, { bwrite_rrot, "rrot", 2, 0, 3, 1, 0, 0, 2, 3, "[shiftcount] [start] [len]", }, { bwrite_seq, "sequence", 3, 0, 4, 0, 1, 2, 3, 4, "[from] [to] [start] [len]", }, { bwrite_random, "random", 3, 0, 2, 0, 0, 0, 1, 2, "[start] [len]", }, { bwrite_fill, "fill", 1, 1, 3, 1, 0, 0, 2, 3, "num [start] [len]" } }; #define BWRITE_CMD_MAX (sizeof(bw_cmdtab)/sizeof(bw_cmdtab[0])) static int convert_oct( char *arg, int *ret) { int count; int i; int val = 0; /* only allow 1 case, '\' and 3 octal digits (or less) */ for (count = 0; count < 3; count++) { if (arg[count] == '\0') break; if ((arg[count] < '0') && (arg[count] > '7')) break; } for (i = 0; i < count; i++) { val |= ((arg[(count-1)-i]-'0')&0x07)<<(i*3); } *ret = val&0xff; return(count); } #define NYBBLE(x) (isdigit(x)?(x-'0'):(tolower(x)-'a'+0xa)) /* * convert_arg allows input in the following forms: * * - A string ("ABTB") whose ASCII value is placed in an array in the order * matching the input. * * - An even number of hex numbers. If the length is greater than 64 bits, * then the output is an array of bytes whose top nibble is the first hex * digit in the input, the lower nibble is the second hex digit in the * input. UUID entries are entered in this manner. * * - A decimal or hexadecimal integer to be used with setbitval(). * * Numbers that are passed to setbitval() need to be in big endian format and * are adjusted in the buffer so that the first input bit is to be be written to * the first bit in the output. */ static char * convert_arg( char *arg, int bit_length) { int i; int alloc_size; int octval; int offset; int ret; static char *buf = NULL; char *endp; char *rbuf; char *ostr; __u64 *value; __u64 val = 0; if (bit_length <= 64) alloc_size = 8; else alloc_size = (bit_length + 7) / 8; buf = xrealloc(buf, alloc_size); memset(buf, 0, alloc_size); value = (__u64 *)buf; rbuf = buf; if (*arg == '\"') { /* input a string and output ASCII array of characters */ /* zap closing quote if there is one */ ostr = strrchr(arg + 1, '\"'); if (ostr) *ostr = '\0'; ostr = arg + 1; for (i = 0; i < alloc_size; i++) { if (!*ostr) break; /* do octal conversion */ if (*ostr == '\\') { if (*(ostr + 1) >= '0' || *(ostr + 1) <= '7') { ret = convert_oct(ostr + 1, &octval); *rbuf++ = octval; ostr += ret + 1; continue; } } *rbuf++ = *ostr++; } return buf; } if (arg[0] == '#' || ((arg[0] != '-') && strchr(arg,'-'))) { /* * handle hex blocks ie * #00112233445566778899aabbccddeeff * and uuids ie * 1122334455667788-99aa-bbcc-ddee-ff00112233445566778899 * * (but if it starts with "-" assume it's just an integer) */ int bytes = bit_length / NBBY; /* is this an array of hec numbers? */ if (bit_length % NBBY) return NULL; /* skip leading hash */ if (*arg == '#') arg++; while (*arg && bytes--) { /* skip hypens */ while (*arg == '-') arg++; /* get first nybble */ if (!isxdigit((int)*arg)) return NULL; *rbuf = NYBBLE((int)*arg) << 4; arg++; /* skip more hyphens */ while (*arg == '-') arg++; /* get second nybble */ if (!isxdigit((int)*arg)) return NULL; *rbuf++ |= NYBBLE((int)*arg); arg++; } if (bytes < 0 && *arg) return NULL; return buf; } /* handle decimal / hexadecimal integers */ val = strtoll(arg, &endp, 0); /* return if not a clean number */ if (*endp != '\0') return NULL; /* Does the value fit into the range of the destination bitfield? */ if (bit_length < 64 && (val >> bit_length) > 0) return NULL; /* * If the length of the field is not a multiple of a byte, push * the bits up in the field, so the most signicant field bit is * the most significant bit in the byte: * * before: * val |----|----|----|----|----|--MM|mmmm|llll| * after * val |----|----|----|----|----|MMmm|mmll|ll00| */ offset = bit_length % NBBY; if (offset) val <<= (NBBY - offset); /* * convert to big endian and copy into the array * rbuf |----|----|----|----|----|MMmm|mmll|ll00| */ *value = cpu_to_be64(val); /* * Align the array to point to the field in the array. * rbuf = |MMmm|mmll|ll00| */ offset = sizeof(__be64) - 1 - ((bit_length - 1) / sizeof(__be64)); rbuf += offset; return rbuf; } /* ARGSUSED */ void write_struct( const field_t *fields, int argc, char **argv) { const ftattr_t *fa; flist_t *fl; flist_t *sfl; int bit_length; char *buf; int parentoffset; if (argc != 2) { dbprintf(_("usage: write fieldname value\n")); return; } fl = flist_scan(argv[0]); if (!fl) { dbprintf(_("unable to parse '%s'.\n"), argv[0]); return; } /* if we're a root field type, go down 1 layer to get field list */ if (fields->name[0] == '\0') { fa = &ftattrtab[fields->ftyp]; ASSERT(fa->ftyp == fields->ftyp); fields = fa->subfld; } /* run down the field list and set offsets into the data */ if (!flist_parse(fields, fl, iocur_top->data, 0)) { flist_free(fl); dbprintf(_("parsing error\n")); return; } sfl = fl; parentoffset = 0; while (sfl->child) { parentoffset = sfl->offset; sfl = sfl->child; } /* * For structures, fsize * fcount tells us the size of the region we are * modifying, which is usually a single structure member and is pointed * to by the last child in the list. * * However, if the base structure is an array and we have a direct index * into the array (e.g. write bno[5]) then we are returned a single * flist object with the offset pointing directly at the location we * need to modify. The length of the object we are modifying is then * determined by the size of the individual array entry (fsize) and the * indexes defined in the object, not the overall size of the array * (which is what fcount returns). */ bit_length = fsize(sfl->fld, iocur_top->data, parentoffset, 0); if (sfl->fld->flags & FLD_ARRAY) bit_length *= sfl->high - sfl->low + 1; else bit_length *= fcount(sfl->fld, iocur_top->data, parentoffset); /* convert this to a generic conversion routine */ /* should be able to handle str, num, or even labels */ buf = convert_arg(argv[1], bit_length); if (!buf) { dbprintf(_("unable to convert value '%s'.\n"), argv[1]); flist_free(fl); return; } setbitval(iocur_top->data, sfl->offset, bit_length, buf); write_cur(); flist_print(fl); print_flist(fl); flist_free(fl); } /* ARGSUSED */ void write_string( const field_t *fields, int argc, char **argv) { char *buf; int i; if (argc != 1) { dbprintf(_("usage (in string mode): write \"string...\"\n")); return; } buf = convert_arg(argv[0], (int)((strlen(argv[0])+1)*8)); for (i = 0; i < iocur_top->len; i++) { ((char *)iocur_top->data)[i] = *buf; if (*buf++ == '\0') break; } /* write back to disk */ write_cur(); } /* ARGSUSED */ void write_block( const field_t *fields, int argc, char **argv) { int i; int shiftcount = -1; int start = -1; int len = -1; int from = -1; int to = -1; struct bw_cmd *cmd = NULL; if (argc <= 1 || argc > 5) goto block_usage; for (i = 0; i < BWRITE_CMD_MAX; i++) { if (sigcmp(argv[0], bw_cmdtab[i].cmdstr, bw_cmdtab[i].sig_chars)) { cmd = &bw_cmdtab[i]; break; } } if (!cmd) { dbprintf(_("write: invalid subcommand\n")); goto block_usage; } if ((argc < cmd->argmin + 1) || (argc > cmd->argmax + 1)) { dbprintf(_("write %s: invalid number of arguments\n"), cmd->cmdstr); goto block_usage; } if (cmd->shiftcount_arg && (cmd->shiftcount_arg < argc)) shiftcount = (int)strtoul(argv[cmd->shiftcount_arg], NULL, 0); if (cmd->start_arg && (cmd->start_arg < argc)) start = (int)strtoul(argv[cmd->start_arg], NULL, 0); if (cmd->len_arg && (cmd->len_arg < argc)) len = (int)strtoul(argv[cmd->len_arg], NULL, 0); if (cmd->from_arg && (cmd->len_arg < argc)) from = (int)strtoul(argv[cmd->from_arg], NULL, 0); if (cmd->to_arg && (cmd->len_arg < argc)) to = (int)strtoul(argv[cmd->to_arg], NULL, 0); cmd->cmdfunc(start, len, shiftcount, from, to); /* write back to disk */ write_cur(); return; block_usage: dbprintf(_("usage: write (in data mode)\n")); for (i = 0; i < BWRITE_CMD_MAX; i++) { dbprintf(" %-9.9s %s\n", bw_cmdtab[i].cmdstr, bw_cmdtab[i].usage); } dbprintf("\n"); return; } xfsprogs-4.9.0+nmu1ubuntu2/db/write.h0000644000000000000000000000173413063067170014366 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ struct field; extern void write_init(void); extern void write_block(const field_t *fields, int argc, char **argv); extern void write_struct(const field_t *fields, int argc, char **argv); extern void write_string(const field_t *fields, int argc, char **argv); xfsprogs-4.9.0+nmu1ubuntu2/db/xfs_admin.sh0000755000000000000000000000254413063067170015372 0ustar #!/bin/sh -f # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # status=0 DB_OPTS="" REPAIR_OPTS="" USAGE="Usage: xfs_admin [-efjlpuV] [-c 0|1] [-L label] [-U uuid] device" while getopts "efjlpuc:L:U:V" c do case $c in c) REPAIR_OPTS=$REPAIR_OPTS" -c lazycount="$OPTARG;; e) DB_OPTS=$DB_OPTS" -c 'version extflg'";; f) DB_OPTS=$DB_OPTS" -f";; j) DB_OPTS=$DB_OPTS" -c 'version log2'";; l) DB_OPTS=$DB_OPTS" -r -c label";; L) DB_OPTS=$DB_OPTS" -c 'label "$OPTARG"'";; p) DB_OPTS=$DB_OPTS" -c 'version projid32bit'";; u) DB_OPTS=$DB_OPTS" -r -c uuid";; U) DB_OPTS=$DB_OPTS" -c 'uuid "$OPTARG"'";; V) xfs_db -p xfs_admin -V status=$? exit $status ;; \?) echo $USAGE 1>&2 exit 2 ;; esac done set -- extra $@ shift $OPTIND case $# in 1) if [ -n "$DB_OPTS" ] then eval xfs_db -x -p xfs_admin $DB_OPTS $1 status=$? fi if [ -n "$REPAIR_OPTS" ] then # Hide normal repair output which is sent to stderr # assuming the filesystem is fine when a user is # running xfs_admin. # Ideally, we need to improve the output behaviour # of repair for this purpose (say a "quiet" mode). eval xfs_repair $REPAIR_OPTS $1 2> /dev/null status=`expr $? + $status` if [ $status -ne 0 ] then echo "Conversion failed, is the filesystem unmounted?" fi fi ;; *) echo $USAGE 1>&2 exit 2 ;; esac exit $status xfsprogs-4.9.0+nmu1ubuntu2/db/xfs_metadump.sh0000755000000000000000000000135313063067170016113 0ustar #!/bin/sh -f # # Copyright (c) 2007 Silicon Graphics, Inc. All Rights Reserved. # OPTS=" " DBOPTS=" " USAGE="Usage: xfs_metadump [-aefFogwV] [-m max_extents] [-l logdev] source target" while getopts "aefgl:m:owFV" c do case $c in a) OPTS=$OPTS"-a ";; e) OPTS=$OPTS"-e ";; g) OPTS=$OPTS"-g ";; m) OPTS=$OPTS"-m "$OPTARG" ";; o) OPTS=$OPTS"-o ";; w) OPTS=$OPTS"-w ";; f) DBOPTS=$DBOPTS" -f";; l) DBOPTS=$DBOPTS" -l "$OPTARG" ";; F) DBOPTS=$DBOPTS" -F";; V) xfs_db -p xfs_metadump -V status=$? exit $status ;; \?) echo $USAGE 1>&2 exit 2 ;; esac done set -- extra $@ shift $OPTIND case $# in 2) xfs_db$DBOPTS -i -p xfs_metadump -c "metadump$OPTS $2" $1 status=$? ;; *) echo $USAGE 1>&2 exit 2 ;; esac exit $status xfsprogs-4.9.0+nmu1ubuntu2/db/xfs_ncheck.sh0000755000000000000000000000121213063067170015524 0ustar #!/bin/sh -f # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # OPTS=" " DBOPTS=" " USAGE="usage: xfs_ncheck [-sfV] [-l logdev] [-i ino]... special" while getopts "b:fi:l:svV" c do case $c in s) OPTS=$OPTS"-s ";; i) OPTS=$OPTS"-i "$OPTARG" ";; v) OPTS=$OPTS"-v ";; f) DBOPTS=$DBOPTS" -f";; l) DBOPTS=$DBOPTS" -l "$OPTARG" ";; V) xfs_db -p xfs_ncheck -V status=$? exit $status ;; \?) echo $USAGE 1>&2 exit 2 ;; esac done set -- extra $@ shift $OPTIND case $# in 1) xfs_db$DBOPTS -r -p xfs_ncheck -c "blockget -ns" -c "ncheck$OPTS" $1 status=$? ;; *) echo $USAGE 1>&2 exit 2 ;; esac exit $status xfsprogs-4.9.0+nmu1ubuntu2/debian/0000755000000000000000000000000013265564517013726 5ustar xfsprogs-4.9.0+nmu1ubuntu2/debian/Makefile0000644000000000000000000000172013063067172015355 0ustar # # Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LSRCFILES = changelog compat control copyright rules watch DEV_DOC_DIR = $(PKG_DOC_DIR)/../xfslibs-dev BOOT_MKFS_BIN = $(TOPDIR)/mkfs/mkfs.xfs-xfsprogs-udeb LDIRDIRT = xfslibs-dev xfsprogs xfsprogs-udeb LDIRT = files *.log *.substvars *.debhelper default: include $(BUILDRULES) install: default ifeq ($(PKG_DISTRIBUTION), debian) $(INSTALL) -m 755 -d $(PKG_DOC_DIR) $(INSTALL) -m 644 changelog $(PKG_DOC_DIR)/changelog.Debian endif install-dev: default ifeq ($(PKG_DISTRIBUTION), debian) $(INSTALL) -m 755 -d $(PKG_DOC_DIR) $(INSTALL) -m 755 -d $(DEV_DOC_DIR) $(INSTALL) -m 644 copyright $(DEV_DOC_DIR) $(INSTALL) -m 644 changelog $(DEV_DOC_DIR)/changelog.Debian endif install-d-i: default ifeq ($(PKG_DISTRIBUTION), debian) $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(INSTALL) -m 755 $(BOOT_MKFS_BIN) $(PKG_ROOT_SBIN_DIR)/mkfs.xfs endif xfsprogs-4.9.0+nmu1ubuntu2/debian/changelog0000644000000000000000000006526513265564517015616 0ustar xfsprogs (4.9.0+nmu1ubuntu2) bionic; urgency=medium * io/copy_file_range.c: cherry-pick upstream change for compatibility with glibc 2.27. -- Steve Langasek Tue, 17 Apr 2018 23:44:31 -0700 xfsprogs (4.9.0+nmu1ubuntu1) artful; urgency=low * Merge from Debian unstable. - Fixes a metadata corruption bug. LP: #1696102. * Remaining changes: - Enable blkid in d-i, by dropping explicitly passed configure option (broken configure). - Drop trying to create upstream distribution. * Dropped changes, included in Debian: - Add autotools check for struct fsxattr to fix FTBFS. - Use FIFREEZE and FITHAW when defined. - 2be9e939868400 "linux.h: include " - 721948f7688e7d "xfs.h: define XFS_IOC_FREEZE even if FIFREEZE is defined" - 83f4b5ac15fa3d "xfs_fs.h: XFS_IOC_FS[SG]SETXATTR to FS_IOC_FS[SG]ETXATTR promotion" -- Steve Langasek Tue, 25 Jul 2017 22:33:17 -0700 xfsprogs (4.9.0+nmu1) unstable; urgency=medium * Non-maintainer upload. * Remove code in include/buildmacros which creates bogus symlinks for libraries. (Closes: #766811) -- Michael Biebl Fri, 17 Mar 2017 19:27:58 +0100 xfsprogs (4.9.0) unstable; urgency=low * New upstream release -- Nathan Scott Thu, 05 Jan 2017 16:05:55 -0600 xfsprogs (4.8.0) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 17 Oct 2016 14:13:45 +1100 xfsprogs (4.7.0) unstable; urgency=low * New upstream release -- Nathan Scott Fri, 05 Aug 2016 11:35:57 +1000 xfsprogs (4.5.0) unstable; urgency=low * New upstream release -- Nathan Scott Tue, 15 Mar 2016 12:05:21 +1100 xfsprogs (4.3.0+nmu1ubuntu4) yakkety; urgency=low * switch to upstream fixes for struct xfsattr redefinition: - 2be9e939868400 "linux.h: include " - 721948f7688e7d "xfs.h: define XFS_IOC_FREEZE even if FIFREEZE is defined" - 83f4b5ac15fa3d "xfs_fs.h: XFS_IOC_FS[SG]SETXATTR to FS_IOC_FS[SG]ETXATTR promotion" -- Andy Whitcroft Wed, 12 Oct 2016 15:52:47 +0100 xfsprogs (4.3.0+nmu1ubuntu3) yakkety; urgency=low * Add autotools check for struct fsxattr to fix FTBFS. * Use FIFREEZE and FITHAW when defined. -- Andy Whitcroft Tue, 11 Oct 2016 09:34:49 +0100 xfsprogs (4.3.0+nmu1ubuntu2) yakkety; urgency=medium * No-change rebuild with PIE as the default. -- Matthias Klose Wed, 28 Sep 2016 00:54:50 +0200 xfsprogs (4.3.0+nmu1ubuntu1) xenial; urgency=medium * Enable blkid in d-i, by dropping explicitly passed configure option (broken configure). (LP: #1544574). * Drop trying to create upstream distribution. -- Dimitri John Ledkov Tue, 16 Feb 2016 00:20:02 +0000 xfsprogs (4.3.0+nmu1) unstable; urgency=medium * Non-maintainer upload. * Disabled the code in include/buildmacros which creates bogus symlinks for libraries. (Closes: #766811) -- Marco d'Itri Wed, 10 Feb 2016 04:24:23 +0100 xfsprogs (4.3.0) unstable; urgency=low * New upstream release * Add a postinst to update the initramfs on install/upgrade. (Closes: #804255) -- Nathan Scott Mon, 23 Nov 2015 15:22:56 +1100 xfsprogs (4.2.0) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 07 Sep 2015 10:13:54 +1000 xfsprogs (3.2.4) unstable; urgency=low * New upstream release * Fix xfs_metadump information leak (CVE-2012-2150) -- Nathan Scott Wed, 29 Jul 2015 15:31:27 +1000 xfsprogs (3.2.3) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 01 Jun 2015 11:35:02 +1000 xfsprogs (3.2.2) unstable; urgency=low * New upstream release * Rework dh-autoreconf invocation (closes: #757455) * Update licensing words for headers (closes: #751511) -- Nathan Scott Mon, 10 Nov 2014 20:35:27 +1100 xfsprogs (3.2.1) unstable; urgency=low * New upstream release (closes: #747080) * Add a watch file (closes: #748483) -- Nathan Scott Wed, 16 Jul 2014 13:47:49 +1000 xfsprogs (3.2.0) unstable; urgency=low * New upstream release * Add dh-autoreconf invocation (closes: #725971) -- Nathan Scott Sat, 03 May 2014 15:59:55 +1000 xfsprogs (3.1.11) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 08 May 2013 12:59:56 -0500 xfsprogs (3.1.9) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 31 Oct 2012 13:29:00 +1100 xfsprogs (3.1.8) unstable; urgency=low * New upstream release * Numerous xfs_repair fixes -- Nathan Scott Mon, 19 Mar 2012 14:21:00 +1100 xfsprogs (3.1.7) unstable; urgency=low * New upstream release * Fix libreadline build dependency (closes: #553875) -- Nathan Scott Thu, 17 Nov 2011 08:47:00 +1100 xfsprogs (3.1.6) unstable; urgency=low * New upstream release * Handle upcoming libreadline5-dev removal (closes: #553875) -- Nathan Scott Wed, 11 Oct 2011 16:47:10 +1100 xfsprogs (3.1.5) unstable; urgency=low * New upstream release * No more xfsquota error message for non-quota mounts (closes: #618730) -- Nathan Scott Wed, 31 Mar 2011 09:00:00 +1100 xfsprogs (3.1.4) unstable; urgency=low * New upstream release (32 projid resolution, fsr uses /proc/mounts) * Annotate Debian packages as being team maintained now. * Resolve Lenny upgrade issue with xfsdump (closes: #601988, #601710) -- Nathan Scott Tue, 09 Nov 2010 22:39:04 +1100 xfsprogs (3.1.3) unstable; urgency=low * New upstream release * Enforce building with libblkid (closes: #593320) -- Nathan Scott Thu, 26 Aug 2010 23:06:46 +1000 xfsprogs (3.1.2) unstable; urgency=low * New upstream release * Allow for building on GNU/kFreeBSD (closes: #485796) -- Nathan Scott Mon, 3 May 2010 14:25:43 +1100 xfsprogs (3.1.1) unstable; urgency=low * New upstream release -- Nathan Scott Thu, 28 Jan 2010 20:54:22 +1100 xfsprogs (3.1.0) unstable; urgency=low * New upstream release * Merged German translation (closes: #521389) * Merged German translation update (closes: #557100) * Uptodate po file is provided now (closes: #538962) * Fixed typos in xfs_quota man page (closes: #481715) * Tighten permissions on temp fsr files (closes: #559490) -- Nathan Scott Thu, 10 Dec 2009 09:19:37 +1100 xfsprogs (3.0.4) unstable; urgency=low * New bugfix release * Resolve a libxfs unaligned access (closes: #517553) -- Nathan Scott Thu, 17 Sep 2009 14:32:48 +1000 xfsprogs (3.0.2) unstable; urgency=low * New bugfix release -- Nathan Scott Wed, 06 May 2009 11:29:18 +1000 xfsprogs (3.0.0-1) unstable; urgency=low * New upstream release (closes: #263170) * Remove watch file, xfsprogs is native * Updated dependencies as this requires xfsdump 3 also -- Nathan Scott Wed, 28 Jan 2009 21:15:07 +1100 xfsprogs (2.10.2-1) unstable; urgency=low * New upstream release * No longer ignore -i maxpct option in mkfs.xfs (closes: #500593) * Correct features2 superblock field handling (closes: #473135) * 32 bit emulation on 64 bit kernels works (closes: #485020) * Fix up large sector handling in mkfs (closes: #489421) -- Nathan Scott Sat, 20 Dec 2008 10:14:27 +1100 xfsprogs (2.9.10-1) unstable; urgency=low * New upstream release -- Anibal Monsalve Salazar Fri, 05 Sep 2008 14:02:20 +1000 xfsprogs (2.9.8-1) unstable; urgency=low * New upstream release * xfsprogs and xfsprogs-udeb depend on ${misc:Depends} * Add Homepage control header * Add watch file * Fix the following lintian issues: W: xfsprogs source: package-uses-deprecated-debhelper-compat-version 1 W: xfsprogs source: ancient-standards-version 3.5.9 (current is 3.7.3) W: xfslibs-dev: package-contains-empty-directory usr/share/doc/xfsprogs/ -- Anibal Monsalve Salazar Tue, 22 Apr 2008 13:04:05 +1000 xfsprogs (2.9.7-1) unstable; urgency=high * New upstream release. * Add -y fsck option (closes: #463810) * Lazy superblock counters not yet mkfs default (closes: #465737, #468184) * xfs_repair memory requirements significantly reduced (closes: #289665) -- Nathan Scott Sat, 01 Mar 2008 06:24:21 +1100 xfsprogs (2.9.5-1) unstable; urgency=low * New upstream release. -- Nathan Scott Tue, 22 Jan 2008 16:46:18 +1100 xfsprogs (2.9.0-1) unstable; urgency=low * New upstream release. -- Nathan Scott Tue, 12 Jun 2007 07:22:21 +1000 xfsprogs (2.8.20-1) unstable; urgency=low * New upstream release (closes: #414079) * Fixed up autoconf version dependency (closes: #414073) -- Nathan Scott Fri, 16 Mar 2007 08:24:33 +1100 xfsprogs (2.8.19-1) unstable; urgency=low * New upstream release (closes: #409063) -- Nathan Scott Wed, 31 Jan 2007 08:53:32 +1100 xfsprogs (2.8.18-1) unstable; urgency=low * New upstream release (closes: #399888) -- Nathan Scott Fri, 08 Dec 2006 08:30:29 +1100 xfsprogs (2.8.12-1) unstable; urgency=low * New upstream release. -- Nathan Scott Tue, 29 Aug 2006 14:28:05 +1000 xfsprogs (2.8.11-1) unstable; urgency=low * New upstream release. * More efficient use of buffer cache memory (closes: #382935) -- Nathan Scott Tue, 08 Aug 2006 17:06:58 +1000 xfsprogs (2.8.10-1) unstable; urgency=low * New upstream release. -- Nathan Scott Wed, 02 Aug 2006 11:17:07 +1000 xfsprogs (2.8.4-1) unstable; urgency=low * New upstream release. * Improved udeb packaging, thanks to Frans Pop (closes: #375439) * Fix filesystem-from-path detection logic (closes: #374687) -- Nathan Scott Mon, 26 Jun 2006 10:04:18 +1000 xfsprogs (2.8.3-1) unstable; urgency=low * New upstream release. * Fix segv in xfs_growfs command (closes: #374686) * Ensure source tarball in correct location (closes: #374696) -- Nathan Scott Wed, 21 Jun 2006 15:19:56 +1000 xfsprogs (2.7.16-1) unstable; urgency=low * New upstream release. -- Nathan Scott Wed, 05 Apr 2006 11:45:58 +1000 xfsprogs (2.7.14-1) unstable; urgency=low * New upstream release. * Switch from debmake to debhelper -- Nathan Scott Wed, 15 Feb 2006 20:04:55 +1100 xfsprogs (2.7.12-1) unstable; urgency=low * New upstream release. * Includes polish translation from Jakub Bogusz. -- Nathan Scott Tue, 31 Jan 2006 13:35:39 +1100 xfsprogs (2.7.7-1) unstable; urgency=low * New upstream release. * Add support for (optional) ATTR2 format extension (closes: #336350) * Allow gcc -pedantic option for C++ users (closes: #249429) * Fix segv in xfs_db frag command (closes: #338207) -- Nathan Scott Wed, 16 Nov 2005 16:32:35 +1100 xfsprogs (2.7.4-1) unstable; urgency=low * New upstream release. -- Nathan Scott Sat, 08 Oct 2005 10:34:10 +1000 xfsprogs (2.6.36-1) unstable; urgency=low * New upstream release. * Fix xfs_repair secondary SB search 32 bit wrap (closes: #320081) -- Nathan Scott Thu, 28 Jul 2005 14:01:50 +1000 xfsprogs (2.6.28-1) unstable; urgency=low * New upstream release. * Fix compilation with gcc version 4 (closes: #300544) -- Nathan Scott Wed, 30 Mar 2005 10:52:07 +1000 xfsprogs (2.6.26-2) unstable; urgency=low * No code differences, recompiled with a more recent gcc version. -- Nathan Scott Tue, 29 Mar 2005 11:57:57 +1000 xfsprogs (2.6.26-1) unstable; urgency=low * New upstream release. * Man page updates (closes: #295397) * Fix compilation with gcc version 4 (closes: #297876) * Switch build dependency from readline4 to readline5. -- Nathan Scott Tue, 08 Mar 2005 16:56:35 +1100 xfsprogs (2.6.23-1) unstable; urgency=low * New upstream release. -- Nathan Scott Fri, 17 Sep 2004 17:04:45 +1000 xfsprogs (2.6.21-1) unstable; urgency=low * New upstream release. * Fix xfs_io build for older glibc versions (current stable). -- Nathan Scott Mon, 09 Aug 2004 16:09:42 +1000 xfsprogs (2.6.20-1) unstable; urgency=low * New upstream release. * Fix xfs_io segfault on non-XFS files. (closes: #260470) * Fix packaging botch, deleted files included. (closes: #260491) -- Nathan Scott Wed, 28 Jul 2004 21:11:38 +1000 xfsprogs (2.6.19-1) unstable; urgency=low * New upstream release. -- Nathan Scott Sat, 17 Jul 2004 11:28:39 +1000 xfsprogs (2.6.18-1) unstable; urgency=low * New upstream release. -- Nathan Scott Fri, 25 Jun 2004 16:57:09 +1000 xfsprogs (2.6.15-1) unstable; urgency=low * New upstream release. -- Nathan Scott Wed, 09 Jun 2004 21:10:14 +1000 xfsprogs (2.6.14-1) unstable; urgency=low * New upstream release. * Add a Provides: fsck-backend clause as requested in the context of bug number 111651. -- Nathan Scott Thu, 13 May 2004 09:56:19 +1000 xfsprogs (2.6.11-1) unstable; urgency=low * New upstream release. -- Nathan Scott Fri, 16 Apr 2004 11:50:56 +1000 xfsprogs (2.6.5-1) unstable; urgency=low * New upstream release. -- Nathan Scott Thu, 26 Feb 2004 14:44:41 +1100 xfsprogs (2.6.3-1) unstable; urgency=low * New upstream release. * Add support for debian-installer. (closes: #225444) Author: Steve Langasek. * Use debhelper instead of debmake, for proper udeb building. Author: Steve Langasek. * Drop boot-floppies support. (closes: #112715) Author: Steve Langasek. * Add support for the security attribute namespace. -- Nathan Scott Mon, 19 Jan 2004 10:08:59 +1100 xfsprogs (2.6.0-1) unstable; urgency=low * New upstream release. * Note: change in the mkfs algorithm for sizing allocation groups. -- Nathan Scott Tue, 28 Oct 2003 15:23:48 +1100 xfsprogs (2.5.11-1) unstable; urgency=low * New upstream release. -- Nathan Scott Fri, 10 Oct 2003 09:37:57 +1000 xfsprogs (2.5.6-1) unstable; urgency=low * New upstream release. -- Nathan Scott Tue, 19 Aug 2003 09:44:48 +1000 xfsprogs (2.5.5-1) unstable; urgency=low * New upstream release. -- Nathan Scott Thu, 07 Aug 2003 12:58:36 +1000 xfsprogs (2.5.4-1) unstable; urgency=low * New upstream release, includes xfs_copy command * Fix shell quoting in xfs_bmap, from Kai S. Juse (closes: #202588) -- Nathan Scott Wed, 23 Jul 2003 10:36:28 +1000 xfsprogs (2.5.3-1) unstable; urgency=low * New upstream release * Changed mkfs.xfs default log size scaling algorithm slightly, to create larger logs at smaller filesystem sizes by default * Enable support for sector sizes larger than 512 bytes -- Nathan Scott Mon, 7 Jul 2003 16:06:21 +1000 xfsprogs (2.4.12-1) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 2 Jun 2003 13:51:06 +1000 xfsprogs (2.4.10-1) unstable; urgency=low * New upstream release * Add missing xfslibs-dev dependency on uuid-dev (closes: #193309) -- Nathan Scott Thu, 15 May 2003 08:50:22 +1000 xfsprogs (2.4.9-1) unstable; urgency=low * New upstream release -- Nathan Scott Fri, 2 May 2003 09:34:17 +1000 xfsprogs (2.4.4-1) unstable; urgency=low * New upstream release * Dependencies on libreadline4 and libreadline4-dev added -- Nathan Scott Sun, 30 Mar 2003 10:30:18 +1000 xfsprogs (2.4.1-1) unstable; urgency=low * New upstream release * Updated policy version to which this package conforms * Note: unwritten extents are now enabled by default in mkfs.xfs -- Nathan Scott Tue, 18 Mar 2003 16:16:43 +1100 xfsprogs (2.3.11-1) unstable; urgency=low * Add missing build dependency on gettext (closes: #181331) -- Nathan Scott Tue, 18 Feb 2003 08:57:46 +1100 xfsprogs (2.3.10-1) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 17 Feb 2003 14:52:20 +1100 xfsprogs (2.3.6-1) unstable; urgency=low * New upstream release -- Nathan Scott Thu, 31 Oct 2002 17:26:44 +1100 xfsprogs (2.3.5-1) unstable; urgency=low * New upstream release * Fix mkfs bug, patch from Anton Blanchard (closes: #163897) -- Nathan Scott Mon, 7 Oct 2002 05:19:51 +1000 xfsprogs (2.3.4-1) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 7 Oct 2002 05:19:51 +1000 xfsprogs (2.3.0-1) unstable; urgency=low * New upstream release * Improve backwards compatibility of tools using the XFS geometry ioctl for older kernel versions which don't support the new ioctl -- Nathan Scott Tue, 3 Sep 2002 09:55:48 +1000 xfsprogs (2.2.1-1) unstable; urgency=low * New upstream release * Default mkfs.xfs blocksize is now 4096 bytes, not getpagesize(2) * Fix to allow install process to work for newer autoconf versions -- Nathan Scott Wed, 7 Aug 2002 11:37:23 +1000 xfsprogs (2.1.2-1) unstable; urgency=low * New upstream release * Support for the XFS version 2 log format -- Nathan Scott Tue, 30 Jul 2002 09:49:08 +1000 xfsprogs (2.0.6-2) unstable; urgency=low * Fix a problem in xfs_repair's handling of ACLs -- Nathan Scott Thu, 30 May 2002 17:22:05 +1000 xfsprogs (2.0.6-1) unstable; urgency=low * New upstream release -- Nathan Scott Thu, 30 May 2002 14:31:30 +1000 xfsprogs (2.0.4-1) unstable; urgency=low * New upstream release, minor changes only -- Nathan Scott Wed, 17 Apr 2002 15:30:52 +1000 xfsprogs (2.0.3-1) unstable; urgency=low * New upstream bugfix release -- Nathan Scott Sat, 13 Apr 2002 09:45:06 +1000 xfsprogs (2.0.2-1) unstable; urgency=low * New upstream bugfix release -- Nathan Scott Thu, 4 Apr 2002 12:11:01 +1100 xfsprogs (2.0.1-1) unstable; urgency=low * New upstream bugfix (minor) release -- Nathan Scott Tue, 12 Mar 2002 13:25:32 +1100 xfsprogs (2.0.0-1) unstable; urgency=low * New upstream release with support for new libhandle interfaces * Major release for switch to official extended attributes syscalls -- Nathan Scott Thu, 7 Feb 2002 13:25:26 +1100 xfsprogs (1.3.18-1) unstable; urgency=low * New upstream bugfix (minor) release -- Nathan Scott Thu, 17 Jan 2002 11:13:19 +1100 xfsprogs (1.3.17-1) unstable; urgency=low * New upstream release * mkfs.xfs overwrites other filesystem signatures * xfs_repair fix for "avl_insert: duplicate range" bug -- Nathan Scott Mon, 14 Jan 2002 10:59:50 +1100 xfsprogs (1.3.16-1) unstable; urgency=low * Remove temporary file use in xfs_db * Add "type text" command into xfs_db -- Nathan Scott Mon, 17 Dec 2001 12:17:54 +1100 xfsprogs (1.3.15-1) unstable; urgency=low * Fix minor package version numbering issue (closes: #117545) * Fix bug in mkfs.xfs device size cross-check for realtime device * Reenable use of the BLKBSZSET ioctl in libxfs -- Nathan Scott Wed, 12 Dec 2001 09:25:42 +1100 xfsprogs (1.3.14-1) unstable; urgency=low * Fix minor package version numbering issue (closes: #117545) * Fix bug in mkfs.xfs device size cross-check for realtime device -- Nathan Scott Wed, 5 Dec 2001 17:13:06 +1100 xfsprogs (1.3.13-0) unstable; urgency=low * New upstream release * Fixes an important mkfs.xfs bug for >1TB filesystems * xfs_repair will no longer blindly zero a dirty log -- Nathan Scott Fri, 26 Oct 2001 10:42:26 +1000 xfsprogs (1.3.11-0) unstable; urgency=low * Upstream release fixing several issues on 64 bit platforms -- Nathan Scott Wed, 17 Oct 2001 10:00:35 +1000 xfsprogs (1.3.10-0) unstable; urgency=low * New upstream release * Fix up some issues building the bootfloppies package -- Nathan Scott Fri, 12 Oct 2001 17:43:20 +1000 xfsprogs (1.3.9-0) unstable; urgency=low * Upstream bug fix release * Additional and updated manual page entries -- Nathan Scott Fri, 5 Oct 2001 14:39:47 +1000 xfsprogs (1.3.8-0) unstable; urgency=low * New upstream release * Fix inclusion of mkfs man page in boot floppies package (closes: #112634) -- Nathan Scott Wed, 19 Sep 2001 14:49:30 +1000 xfsprogs (1.3.7-0) unstable; urgency=low * New upstream release * Change to libhandle licensing (was GPL, now LGPL-2.1) * Create a boot-floppies package with smaller mkfs.xfs (closes: #111426) * Make install-sh posix compliant so ash as /bin/sh works (closes: #111985) -- Nathan Scott Mon, 10 Sep 2001 10:52:04 +1000 xfsprogs (1.3.5-0) unstable; urgency=low * Upstream bugfix release; fixes listed below * Fix bug in xfs_db bit handling on big endian platforms * Fix mkfs.xfs bug related to too-small final allocation group * Fix signedness bug in DMAPI ioctl structure definition -- Nathan Scott Mon, 13 Aug 2001 09:38:27 +1000 xfsprogs (1.3.4-0) unstable; urgency=low * Upstream bugfix release; fixes listed below * Fix endian bug in xfs_db "frag" command * Several man pages updated to document external log usage * IA64 build issues fixed (use -fno-strict-aliasing for libraries) * Fixed several minor compiler warnings when building on IA64 * Added a Suggests entry for dvhtool (for those using SGI disks) * configure.in changes to allow cross compilation -- Nathan Scott Sat, 4 Aug 2001 10:32:00 +1000 xfsprogs (1.3.3-0) unstable; urgency=low * New upstream release -- Nathan Scott Fri, 27 Jul 2001 07:59:49 +1000 xfsprogs (1.3.2-0) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 23 Jul 2001 10:27:37 +1000 xfsprogs (1.3.1-0) unstable; urgency=low * Reworked package slightly so that it's not Debian native * Debian-specific changes now documented in changelog.Debian.gz * New upstream release (see /usr/share/doc/xfsprogs/changelog.gz) * Checked standards compliance - update standards version to 3.5.5 -- Nathan Scott Sat, 15 Jul 2001 16:34:43 +1000 xfsprogs (1.3.0) unstable; urgency=low * Reworked Makefiles to use libtool * New libdisk to allow sharing of generic mount/disk code and * Also abstracts individual driver support (LVM, MD, XVM..) * Partition table detection so mkfs.xfs doesn't blindly overwrite * Small xfs_repair bug fix from Steve -- Nathan Scott Thu, 19 Jul 2001 10:12:03 +1000 xfsprogs (1.2.8) unstable; urgency=low * Fixed a bug in libxfs /etc/mtab read-only mount detection * First try procfs, fall back to /etc/mtab, for read-only mounts * Sync with recent mount code changes for reiserfs and ext3 probes * Fix logprint build problem under gcc 3.0 -- Nathan Scott Mon, 2 Jul 2001 13:59:08 +1000 xfsprogs (1.2.7) unstable; urgency=low * New xfs_freeze(8) command - volume manager snapshot helper -- Nathan Scott Tue, 22 May 2001 17:22:32 +1000 xfsprogs (1.2.6) unstable; urgency=low * Merge support for -d agsize=/su=/sw= (AG, stripe unit/width size) * Merge support for dynamic configuration of default log size * Document these updates, and fix a couple of man page typos too -- Nathan Scott Tue, 15 May 2001 12:34:17 +1000 xfsprogs (1.2.5) unstable; urgency=low * Fix missing Makefile include entries for LVM headers * Add experimental xfs_rtcp (realtime copy) command * PowerPC build failure fixups - thanks to Robert Ramiega * Cleanup arch-specific code, esp. the byteswab routines * Suggests xfsdump and attr packages -- Nathan Scott Tue, 8 May 2001 15:50:27 +1000 xfsprogs (1.2.4) unstable; urgency=low * Add -L option to mkfs.xfs (filesystem label) -- Nathan Scott Tue, 1 May 2001 14:03:14 +1000 xfsprogs (1.2.3) unstable; urgency=low * Add dquot and quotaoff log item support into xfs_logprint * Fix logprint core dump reporting AGI in "continue"'d transactions -- Nathan Scott Fri, 27 Apr 2001 10:17:25 +1000 xfsprogs (1.2.2) unstable; urgency=low * Fix problem in xfs_db (check) group quota logic * Fixes to warnings from recent gcc and/or 64-bit builds -- Nathan Scott Fri, 13 Apr 2001 09:50:37 +1000 xfsprogs (1.2.1) unstable; urgency=low * Support for group quota added * Stripe unit/stripe width extraction for MD devices * Added mkfs.xfs heuristics for size of internal log * Sync up with recent changes to XFS kernel headers -- Nathan Scott Wed, 4 Apr 2001 13:54:00 +1000 xfsprogs (1.1.6) unstable; urgency=low * Fix sparc build failure - fcntl.h missing O_DIRECT (closes: #90211) * Added README.quota describing the use of quota with XFS -- Nathan Scott Tue, 20 Mar 2001 11:25:03 +1100 xfsprogs (1.1.5) unstable; urgency=low * Upgraded LVM stripe unit/width support to 0.9beta2 (IOP 10) * Kernel now supports O_DIRECT - re-enable its use in xfs_mkfile * BLKSETSIZE ioctl replaced by BLKBSZSET ioctl in libxfs * libxfs_init extended so only mkfs and xfs_repair use BLKBSZSET * NOTE: this requires an XFS kernel from 9 March '01 or later -- Nathan Scott Sun, 18 Mar 2001 14:31:17 +1100 xfsprogs (1.1.3) unstable; urgency=low * Minor changes to xfs_logprint tail verification * Update build Makefile to pick up extra dirt before packaging -- Nathan Scott Thu, 1 Mar 2001 12:24:28 +1100 xfsprogs (1.1.2) unstable; urgency=low * Fix stdarg.h issue causing build failure with glibc 2.2.2 * Changes to libhandle for supporting extended attributes -- Nathan Scott Tue, 20 Feb 2001 08:29:36 +1100 xfsprogs (1.1.0) unstable; urgency=low * Initial release (closes: #83829) -- Nathan Scott Thu, 4 Jan 2001 11:15:11 -0500 Local variables: mode: debian-changelog End: xfsprogs-4.9.0+nmu1ubuntu2/debian/compat0000644000000000000000000000000213063067172015113 0ustar 5 xfsprogs-4.9.0+nmu1ubuntu2/debian/control0000644000000000000000000000467213136024635015327 0ustar Source: xfsprogs Section: admin Priority: optional Maintainer: Ubuntu Developers XSBC-Original-Maintainer: XFS Development Team Uploaders: Nathan Scott , Anibal Monsalve Salazar Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev Standards-Version: 3.9.1 Homepage: http://xfs.org/ Package: xfsprogs Depends: ${shlibs:Depends}, ${misc:Depends} Provides: fsck-backend Suggests: xfsdump, acl, attr, quota Breaks: xfsdump (<< 3.0.0) Replaces: xfsdump (<< 3.0.0) Architecture: any Description: Utilities for managing the XFS filesystem A set of commands to use the XFS filesystem, including mkfs.xfs. . XFS is a high performance journaling filesystem which originated on the SGI IRIX platform. It is completely multi-threaded, can support large files and large filesystems, extended attributes, variable block sizes, is extent based, and makes extensive use of Btrees (directories, extents, free space) to aid both performance and scalability. . Refer to the documentation at http://oss.sgi.com/projects/xfs/ for complete details. Package: xfslibs-dev Section: libdevel Priority: extra Depends: libc6-dev | libc-dev, uuid-dev, xfsprogs (>= 3.0.0), ${misc:Depends} Breaks: xfsprogs (<< 3.0.0) Architecture: any Description: XFS filesystem-specific static libraries and headers xfslibs-dev contains the libraries and header files needed to develop XFS filesystem-specific programs. . XFS is a high performance journaling filesystem which originated on the SGI IRIX platform. It is completely multi-threaded, can support large files and large filesystems, extended attributes, variable block sizes, is extent based, and makes extensive use of Btrees (directories, extents, free space) to aid both performance and scalability. . Refer to the documentation at http://xfs.org/ for complete details. Package: xfsprogs-udeb XC-Package-Type: udeb Section: debian-installer Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: A stripped-down version of xfsprogs, for debian-installer This package is an xfsprogs package built for reduced size, so that it can help to save space in debian-installer. . Don't attempt to install this package, it has no support for a couple of features you surely want. Anyway, it should fail to install. xfsprogs-4.9.0+nmu1ubuntu2/debian/copyright0000644000000000000000000000133413063067172015651 0ustar This package was debianized by Nathan Scott nathans@debian.org on Sun, 19 Nov 2000 07:37:09 -0500. It can be downloaded from ftp://oss.sgi.com/projects/xfs/download/ Copyright: Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. You are free to distribute this software under the terms of the GNU General Public License. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL file. The library named "libhandle" and the headers in "xfslibs-dev" are licensed under Version 2.1 of the GNU Lesser General Public License. On Debian systems, refer to /usr/share/common-licenses/LGPL-2.1 for the complete text of the GNU Lesser General Public License. xfsprogs-4.9.0+nmu1ubuntu2/debian/postinst0000644000000000000000000000051113063067172015520 0ustar #!/bin/sh set -e case "${1}" in configure) if [ -x /usr/sbin/update-initramfs ] && [ -e /etc/initramfs-tools/initramfs.conf ] then update-initramfs -u fi ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`${1}'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 xfsprogs-4.9.0+nmu1ubuntu2/debian/rules0000755000000000000000000000467313063067172015007 0ustar #!/usr/bin/make -f export DH_VERBOSE=1 package = xfsprogs develop = xfslibs-dev bootpkg = xfsprogs-udeb version = $(shell dpkg-parsechangelog | grep ^Version: | cut -d ' ' -f 2) target ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) udebpkg = $(bootpkg)_$(version)_$(target).udeb dirme = debian/$(package) dirdev = debian/$(develop) dirdi = debian/$(bootpkg) pkgme = DIST_ROOT=`pwd`/$(dirme); export DIST_ROOT; pkgdev = DIST_ROOT=`pwd`/$(dirdev); export DIST_ROOT; pkgdi = DIST_ROOT=`pwd`/$(dirdi); export DIST_ROOT; stdenv = @GZIP=-q; export GZIP; options = export DEBUG=-DNDEBUG DISTRIBUTION=debian \ INSTALL_USER=root INSTALL_GROUP=root \ LOCAL_CONFIGURE_OPTIONS="--enable-readline=yes --enable-blkid=yes" ; diopts = $(options) \ export OPTIMIZER=-Os LOCAL_CONFIGURE_OPTIONS="--enable-gettext=no" ; checkdir = test -f debian/rules build: built built: reconf dibuild config @echo "== dpkg-buildpackage: build" 1>&2 $(MAKE) default touch built reconf: .reconf .reconf: $(checkdir) AUTOHEADER=/bin/true dh_autoreconf touch $@ config: .census .reconf .census: @echo "== dpkg-buildpackage: configure" 1>&2 $(checkdir) $(options) $(MAKE) include/platform_defs.h touch .census dibuild: .reconf $(checkdir) @echo "== dpkg-buildpackage: installer" 1>&2 if [ ! -f mkfs/mkfs.xfs-$(bootpkg) ]; then \ $(diopts) $(MAKE) include/platform_defs.h; \ mkdir -p include/xfs; \ for dir in include libxfs; do \ $(MAKE) -C $$dir NODEP=1 install-headers; \ done; \ for dir in include libxfs libxcmd mkfs; do \ $(MAKE) -C $$dir; \ done; \ mv mkfs/mkfs.xfs mkfs/mkfs.xfs-$(bootpkg); \ $(MAKE) distclean; \ fi clean: @echo "== dpkg-buildpackage: clean" 1>&2 $(checkdir) -rm -f built .census .reconf mkfs/mkfs.xfs-$(bootpkg) $(MAKE) distclean -rm -rf $(dirme) $(dirdev) $(dirdi) -rm -f debian/*substvars debian/files* debian/*.debhelper dh_autoreconf_clean dh_clean binary-indep: binary-arch: checkroot built @echo "== dpkg-buildpackage: binary-arch" 1>&2 $(checkdir) -rm -rf $(dirme) $(dirdev) $(dirdi) $(pkgme) $(MAKE) -C . install $(pkgdev) $(MAKE) -C . install-dev $(pkgdi) $(MAKE) -C debian install-d-i rmdir debian/xfslibs-dev/usr/share/doc/xfsprogs dh_installdocs dh_installchangelogs dh_strip dh_compress dh_fixperms dh_makeshlibs dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch checkroot: test 0 -eq `id -u` .PHONY: binary binary-arch binary-indep clean checkroot xfsprogs-4.9.0+nmu1ubuntu2/debian/watch0000644000000000000000000000022713063067172014747 0ustar version=3 opts=uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \ ftp://oss.sgi.com/projects/xfs/cmd_tars/xfsprogs-(.+)\.tar\.gz xfsprogs-4.9.0+nmu1ubuntu2/doc/0000755000000000000000000000000013063067174013242 5ustar xfsprogs-4.9.0+nmu1ubuntu2/doc/CHANGES0000644000000000000000000023442413063067170014242 0ustar xfsprogs-4.9.0 (5 Jan 2017) - no changes from v4.9.0-rc1 xfsprogs-4.9.0-rc1 (22 Dec 2016) - add reflink and dedupe support (Darrick Wong) - Convert from off64_t to off_t (Felix Janda) - xfs_io: add command line option to start an idle thread (Amir Goldstein) - xfs_repair: junk leaf attribute if count == 0 (Eric Sandeen) - xfs_quota: handle wrapped id from GETNEXTQUOTA (Eric Sandeen) - xfs_repair: fix some potential null pointer deferences (Darrick Wong) - libxfs_apply: filtering fixes (Dave Chinner) xfsprogs-4.8.0 (17 Oct 2016) - no changes from v4.8.0-rc3 xfsprogs-4.8.0-rc3 (3 Oct 2016) - xfs_io: clean up inode command (Eric Sandeen) - xfs_repair: fix phase 5 btree size overestimation (Darrick Wong) - xfs_repair: fix phase 5 AGFL rmap update (Darrick Wong) - libxfs: libxfs_iget() cleanup (Eric Sandeen) - libxcmd: fix count of XFS filesystems in path table (Eryu Guan) xfsprogs-4.8.0-rc2 (23 Sep 2016) - xfs_copy: uuid handling fixes (Eric Sandeen) - xfs_repair: directory rebuild segfault fix (Eric Sandeen) - xfs_repair: report log dirtiness correctly (Eric Sandeen) - libxfs: mounted filesystem detection cleanups (Eric Sandeen) - xfs_logprint: don't print transaction types anymore (Hou Tao) - xfs_quota: allow operation on non-XFS filesystems (Bill O'Donnell) - xfs_io: allow project quota operations on non-XFS (Eric Sandeen) - mkfs.xfs: man page calrification for ftype defaults (Eric Sandeen) xfsprogs-4.8.0-rc1 (9 Sep 2016) - change contact emails to linux-xfs@vger.kernel.org - libxfs: kernel sync up to 4.8-rc1 - Initial reverse mapping support (Darrick Wong) - buffer lock trace analysis tool (Darrick Wong) - logprint: cleanups and fixes (Darrick Wong) - man page updates (various) - libxcmd: mount option parsing fixes (Darrick Wong) - xfs_quota: use XFS_GETQSTATV (Eric Sandeen) - xfs_quota: allow use on non-XFS filesystems (Bill O'Donnell) - xfs_db: allow direct manipulation of CRCs (Eric Sandeen) - libxfs: get rid of ustat() calls (Felix Janda) xfsprogs-4.7.0 (5 Aug 2016) - xfs_io: man page for copy_file_range (Anna Schumaker) - xfs_quota: handle XFS_GETNEXTQUOTA failure sanely (Zorro Lang) - mkfs: remove old glibc build failure workaround (Felix Janda) xfsprogs-4.7.0-rc2 (20 Jul 2016) - xfs_io: add support for copy_file_range (Anna Schumaker) - repair: fix exit value after low memory is detected (Zorro Lang) - repair: fix quota inode detection issue (Eric Sandeen) - fix coverity issues from 4.7-rc1 (Bill O'Donnell) xfsprogs-4.7.0-rc1 (22 Jun 2016) - libxfs kernel sync up to 4.7-rc1 - quota: new efficient iteration mechanism (Eric Sandeen) - quota: support usernames starting with digits (Zorro Lang) - xfs_io: mmap/mremap fixes (Zorro Lang) - build/translation fixes (Mike Frysinger) - repair: error messge cleanups (Eric Sandeen) - mkfs: table based option parsing (Jan Tulak, Eric Sandeen) - metadump: sector size support fixes (Eric Sandeen) - db: unaligned acces fixes (Eric Sandeen) - db: add CRC recalculation for corrupt blocks - db: fix array notation handling in print commands - db: Note that fragmenation factor is meaningless (Eric Sandeen) - repair: more efficient secondary superblock search (Bill O'Donnell) - quota: timer reporting corner case fixes (Eric Sandeen) - headers: struct fsxattr redifinition fixes (Christoph Hellwig) - man page updates (Eric Sandeen, Jan Tulak, Zorro Lang) - repair: RT summary inode rebuild fix (Eric Sandeen) - db: sparse inode check fixes (Brian Foster) xfsprogs-4.5.0 (15 Mar 2016) - xfs_io: prevent divide-by-zero on random IO (Dmitry Monakhov) - xfs_db: dquot command documentation fixes (Eric Sandeen) - xfs_quota: better command line parsing and documentation (Zorro Lang) xfsprogs-4.5.0-rc1 (17 Feb 2016) - libxfs: update to match kernel 4.5-rc1 code base - xfs_io: add DAX inode flag support - repair: scalability improvements on large corrupt filesystems - repair: directory rebuild fixes - mdrestore: progress accounting now works - metadump: fix btree block unused region zeroing - quota: timer command fixes (Eric Sandeen) - mkfs: man page cleanups (Eric Sandeen) - xfs_io: reflink, dedupe and other fixes (Darrick Wong) - quota: Q_XGETNEXTQUOTA support (Eric Sandeen) - build cleanups for alternate C librarys (Joshua Kinard, Felix Janda) - db: check fixes for sparse inodes (Darrick Wong) - various: Fixes for Coverity reports (Vivek Trivedi) - xfs_io: Document zero and help commands (Eric Sandeen) - mkfs: DIO can use logical sector size limits (Eric Sandeen) - repair: don't reset log cycle numbers when zeroing (Brian Foster) - db: add ability to format log to a specific cycle (Brian Foster) xfsprogs-4.3.0 (23 Nov 2015) - xfs_fsr: cleanups to recent changes (Eric Sandeen) - xfs_fsr: improved temp file attr fork handling (Eric Sandeen) - libxfs: output verifier names in warnings (Eric Sandeen) - xfs_repair: enable verifier corruption warnings on very verbose output settings (Eric Sandeen) - debian: update initramfs in postinst script (Steve McIntyre) xfsprogs-4.3.0-rc2 (10 Nov 2015) - xfs_fsr: abstract mntinfo/mntent differences (Jan Tulak) - xfs_io: update reflink/dedupe ioctl definitions and implementation (Darrick Wong) - libxcmd: factoring of runtime reporting (Darrick Wong) - man page fixes (Ville Skyttä) - removal of ASSERT from exported headers xfsprogs-4.3.0-rc1 (14 Oct 2015) - xfs_io: reflink and dedupe operation support (Darrick Wong) - xfs_db: blockget/blocktrash support for v5 filesystems (Darrick Wong) - xfs_repair: many directory/attr cleanups and fixes (Eric Sandeen) - More OS X build improvements (Jan Tulak) - Log zeroing rework for v5 filesystems to prevent log sequence numbers from going backwards (Brain Foster) xfsprogs-4.2.0 (7 Sep 2015) - repair: fix crashes due to missing geometry pointer (Eric Sandeen) - repair: fix node handling on large attribute btrees (Brian Foster) - repair: attribute block header verification fixes (Darrick Wong) - libxfs: more error negation fixes (Darrick Wong) - libxfs: cancelled readahead buffer state initialisation fixes (Darrick Wong) - build: include/xfs header path fix (Lucas Stach) xfsprogs-4.2.0-rc3 (25 Aug 2015) - xfs_repair: directory verification fixes (Darrick Wong) - libxfs: errno negation fixes (Darrick Wong) - xfs_db: corrupt inode handling fixes (Darrick Wong) - repair: memory leak fixes (Eric Sandeen) - libxfs: directory corruption fix (Jan Kara) - libxfs: gcc miscompile fixes (Jan Kara) - libxfs: merge across bug fixes from 4.2 kernel code - man pages: minor updates (Eric Sandeen) xfsprogs-4.2.0-rc2 (18 Aug 2015) - OS X build improvements (Jan Tulak) - libxfs: fix code miscompilation w/ gcc 4.8.3 (Jan Kara) - mkfs.xfs: default to using ftype=1 for all filesystems - mkfs.xfs: CLI options parsing order fix (Eric Sandeen) - xfs_repair: improve inode version checks (Roger Willcocks) - libxfs: remove excessive EXPERIMENTAL feature warnings for sparse inodes (Brian Foster) - xfs_db: fix new gcc 4.9.3 build warnings xfsprogs-4.2.0-rc1 (4 Aug 2015) - update libxfs to match kernel 4.2-rc1 - libxfs and include restructuring to match kernel code - sparse inode support (Brian Foster) - Android build support (Ted Tso) - Mac OS X build fixes (Jan Tulak) - changing UUIDs on v5 filesystems (Eric Sandeen) - libxfs-apply script for keeping kernel/progs libxfs in sync (Eric Sandeen) - lots of header and type cleanups (Christoph Hellwig) - libblkid now mandatory (Jan Tulak) - lots of bug fixes (Brian Foster, Eric Sandeen, Christoph Hellwig, Mike Grant) xfsprogs-3.2.4 (30 Jul 2015) - xfs_metadump: information leakage fixes (CVE-2012-2150) (Eric Sandeen) xfsprogs-3.2.3 (10 Jun 2015) - Debian packaging updates (Nathan Scott) xfsprogs-3.2.3-rc2 (1 Jun 2015) - xfs_repair: handle speciall atribute names correctly (Eric Sandeen) - xfs_repair: handle v5 format feature flags correctly (Darrick Wong) - xfs_repair: Better v5 format validation for directories (Darrick Wong) xfsprogs-3.2.3-rc1 (11 May 2015) - mkfs.xfs: enable metadata CRCs by default - mkfs.xfs: enable free inode btrees by default - build: glibc support updates (Jan Tulak) - man page updates (Sage Weil, Namjae Jeon, Eric Sandeen) - xfs_admin: Changing UUIDs disable for CRC enabled filesystems (Eric Sandeen) - xfs_repair: Separate pquota inode fixes (Brian Foster) - xfs_db: inode alignment fixes (Brian Foster) - mkfs.xfs: fix failures creating file images (Brian Foster) - libxfs: zero new buffers before use (Darrick J. Wong) - xfs_repair: handle directory leaf CRC errors gracefully (Darrick J. Wong) - xfs_repair: validate and repair inode CRCs (Eric Sandeen) - xfs_repair: lots of broken directory repair fixes (Eric Sandeen) - xfs_db: handle v3 inodes properly (Eric Sandeen) - xfs_db: allow writing corrupted metadata on CRC enabled filesystems (Eric Sandeen) - xfs_repair: gracefully handle > 512 byte sector superblocks - mkfs.xfs: take into acocunt log stripe unit when sizing log - xfs_metadump: inode alignment and null inode fixes (Brian Foster) - xfs_io: FALLOC_FL_INSERT_RANGE support (Namjae Jeon) - build: libtool static library build fixes (Romain Naour) - mkfs.xfs: large block size inode alignment fixes (Brian Foster) - xfs_repair: secondary superblock scan fixes (Brian Foster) - xfs_repair: don't care about symlink compenent lengths (Eric Sandeen) xfsprogs-3.2.2 (4 December 2014) - Debian packaging updates (Nathan Scott) - xfs_repair, mkfs.xfs stripe geometry fixes (Eric Sandeen) - libxcmd path handling fixes (Eric Sandeen) - xfs_crash crash fix (Jie Liu) - xfs_logprint AGI/AGF handling improvements (Jan Kara) - libhandle support for symlinked /usr (Jan Tulak) - fix multiple Coverity and sparse reported issues (Eric Sandeen) - new mremap, sync, syncfs commands for xfs_io (Eric Sandeen) - man page updates (Eric Sandeen, Mark Tinguely) - xfs_repair sets ftype in lost+found dirents (Jan Kara) - xfs_repair handles bad inodes better (Eric Sandeen) - xfs_repair freelist rebuild improvements - xfs_repair finobt crash fixes (Brian Foster) - xfs_copy handles 4k sector devices better (Eric Sandeen) xfsprogs-3.2.1 (15 July 2014) - Added support for new on-disk free inode btree (Brian Foster) - libxfs inode use-after free fixes (Mark Tinguely) - xfs_copy threading cleanups (Junxiao Bi) - xfs_check has been removed - C++ header compiler fixes (Roger Willcocks) - xfs_repair prefetch fixes (Eric Sandeen) - xfs_repair directory block CRC detection fixes (Jan Kara) - xfs_repair directory rebuild fixes - libxfs buffer error handling fixes - xfs_repair quota inode handling fixes - removed incorrect asserts from phase 2 of xfs_repair - updated Polish translations (Jakub Bogusz) - xfs_mkfs 4k sector device fixes (Eric Sandeen) - xfs_fsr cleanups nd fixes (Eric Sandeen) - mount options described in xfs(5) man page (Eric Sandeen) xfsprogs-3.2.0 (16 May 2014) - First release with full support of CRC enabled filesystems - No code changes from 3.2.0-rc3 xfsprogs-3.2.0-rc3 (9 May 2014) - Third release candidate for full support of CRC enabled filesystems - Updated Debian change logs in preparation for release (Nathan Scott) - Build warning fixes (Nathan Scott) - xfs_repair prefetch fix (Eric Sandeen) - xfs_repair block tracking scalability fix xfsprogs-3.2.0-rc2 (2 May 2014) - Second release candidate for full support of CRC enabled filesystems - xfs_repair has full CRC validation and repair - Coverity related cleanups and fixes xfsprogs-3.2.0-rc1 (14 April 2014) - First release candidate for full support of CRC enabled filesystems - Large number of Coverity related fixes and cleanups - disambiguous of CRC validation errors from IO errors. - Improved dangerous mode handling in repair - repair handles garbage in zeroed areas of superblocks better - repair validates dirent ftype field fully - metadump fully supports discontiguous directory blocks - metadump only recalculates CRCs on metadata it obfuscates so as to preserve errors in the metadata where possible. - default log size that mkfs creates is now reverted to the same size as 3.1.x releases create. - mkfs sets the ftype on directory entries correctly during protofile population - xfs_io support O_TMPFILE, flink, FALLOC_FL_ZERO_RANGE and FALLOC_FL_COLLAPSE_RANGE, - logprint handles split entries better xfsprogs-3.2.0-alpha2 (25 November 2013) - Alpha release for the purpose of testing the CRC feature in kernels 3.10 and newer. - Enable xfs_db write support and xfs_metadump support for CRC enabled filesystems. - Add directory entry filetype support for non-CRC filesystems. - Remove experimental warnings for CRC filesystems. - Ensure all inodes created by xfs_repair have a proper d_type set. - Fix build on big endian machines. - Properly handle symlinks to devices on various tool commandlines. - Fix xfs_repair's dirty log detection for 4k sector logs, broken in Alpha1. - Fix a potential segfault in xfs_repair when issuing progress reports. - Fix potential xfs_fsr failures when running w/ selinux. - Update config.guess/config.sub for arm64, thanks to Colin Watson. - Stop wasting memory by caching inode structures in xfs_repair - they are never re-used. Thanks to Christoph Hellwig. - Fix several Coverity-found defects, thanks to Li Zhong. - Fix platform_test_xfs_fd to return false on special files which cannot take an xfs ioctl. - Sync up libxfs with kernel code. - Improved xfs_repair performance on large filesystems (always use prefetch and strided AG scanning functionality) xfsprogs-3.2.0-alpha1 (26 September 2013) - Alpha release for the purpose of testing the CRC feature in kernels 3.10 and newer. - Remove all vestiges of old, unsupported version 1 directory code. - Add a "readdir" command to xfs_io, thanks to Brian Foster. - Fix potential segfault in xfs_repair when creating lost+found. - Zero out unused parts of on-disk superblocks during repair, to avoid metadata verifier failures at runtime. - Add directory entry type support to mkfs.xfs and xfs_db. - Add the icreate transaction to xfs_logprint, and fix continuation transactions. - Add the lseek SEEK_DATA/SEEK_HOLE support into xfs_io. - Print all AGI unlinked buckets in xfs_logprint. - Fix mkfs.xfs ENOSPC with protofile which creates a very large directory. - Fix several Coverity-found defects, thanks to Li Zhong. - Do all file reads in xfs_fsr using O_DIRECT. - Sync up libxfs with kernel code. - Add support for concurrent group and project quota usage on CRC enabled filesystems. - Ensure mkfs creates log sizes that are always large enough for the configured fileystem geometry. xfsprogs-3.1.11 (8 May 2013) - Support for relative paths in xfs_quota thanks to Satoru Takeuchi. - mkfs.xfs will always go into multidisk mode when filesystem geometry is specified on the command line. - Document all commands in xfs_io. - Remove setfl command from xfs_io. - xfs_metadump will obfuscate symlinks by path component. - mkfs.xfs no longer accepts geometry settings smaller than the physical sector size. - xfs_logprint now supports multiply-logged inode fields and handles continued inode transactions correctly. - kill XLOG_SET - Update release scripts to use git archive to address a missing source file reported by Arkadiusz Mi?kiewicz - Fix a build error with -Werror=format-security, reported by Arkadiusz Mi?kiewicz - mkfs.xfs no longer attempts to discard when -N option is used. - Update 'make deb' to use tarball - Sync up with log reservation changes in the kernel. - Fix possible unallocated memory access in fiemap. - Guard against string overflow in path_to_fspath. - Fix setup_cursor array allocation. - Fix free of unintialized pointer in xfs_acl_valid error path. - Guard against path string overflows. - Check strdup results properly in initallfs(). - Fix attribute no_change_count logic. - Remove extraneous close() in fsrallfs(). - xfs_repair now skips the freelist scan of a corrupt agf when in no-modify mode. - xfs_db now skips freelist scans of corrupt agfs. - Remove unconditional ASSERT(0) in xfs_repair. - Reduce bb_numrecs in bno/cnt btrees when log consumes all agf space. - Add depraction message for xfs_check. - xfs_quota allow user or group names beginning with digits reported by James Carter. - Fix manpages and usage() spelling, errors and omissions. - Validate the extent count is at least within the positive range of a signed 32 bit integer before using it. xfsprogs-3.1.10 (13 December 2012) - Update release script to make a source tarball. xfsprogs-3.1.9 (31 October 2012) - Print nice details if agsize is out of bounds in mkfs.xfs. - Various fixes for fragmented multi-block dir2 handling in xfs_repair. - Fix extent record printing in xfs_db on big endian arches. - Use the correct macros when dumping block maps in extent form in xfs_db, thanks to Peter Watkins. - Add sync file range support to xfs_io. - Implement preadv/pwritev in xfs_io. - Link against libreadline for libxcmd, thanks to Mike Frysinger. - Clean up mkfs.xfs output on invalid inode size. - Various build fixes, thanks to Mike Frysinger and Jan Engelhardt. xfsprogs-3.1.8 (20 March 2012) - Fix xfs_repair segfault on a corrupted filesystem by validating the acl count before reading it. - Avoid xfs_repair deadlocks on prefetched buffers. - Fix various incorrect printf formats, thanks to Jakub Bogusz for reporting. - Polish translation update, thanks to Jakub Bogusz. - Refuse mkfs.xfs on misaligned devices when using 4k sectors, unless the -f option is specified, and then force 512b sector size, thanks to Carlos Maiolino. - Avoid a possible loop on the unlinked inode list in phase 3 of xfs_repair, thanks to Stefan Pfetzing for reporting. - Allocate inode and free extent records individually in xfs_repair. - Fix a possible deadlock btree nodes in xfs_repair by using recursive locking, thanks to Arkadiusz MiÅ›kiewicz for reporting and testing. - Fix possible xfs_repair deadlocks in inode prefetching, thanks to Arkadiusz MiÅ›kiewicz for reporting and testing. - Make xfs_repair handle filesystems with the log in ag 0, thanks to Sindre Skogen for reporting. - Deprecate the -F foreign flag to xfs_io. - Add debian linux-libc-dev build dependancy. - Add an extended fiemap configure check. - Various cleanups in xfs_repair. - Update xfs_check man page to recommend xfs_repair over xfs_check, thanks to Arkadiusz MiÅ›kiewicz. - Update the on-disk extent count as part of inode repair when moving inodes to lost+found to avoid to avoid tripping over a check in xfs_iformat, thanks to Arkadiusz MiÅ›kiewicz for reporting and testing. - Check for size parsing errors in xfs_quota, thanks to James Lawrie for reporting. - Fix fiemap loop continuation in xfs_io. - Make mkfs.xfs properly handle physical sector size. - Fix /proc/mounts parsing in xfs_fsr. - Fix xfs_repair when ag_stride options with attributes and dirv1 code, thanks to Tom Crane for reporting and testing. - Fix message formats in process_dinode_int. - Fix xfs_repair handling of link counts when the on-disk count overflows 8 bits. - Fix messages from set_nlinks in xfs_repair. xfsprogs-3.1.7 (17 November 2011) - Pull in fix for debian/control - Polish translation update, thanks to Jakub Bogusz - Fix xfs_repair link count on lost+found, thanks to Carlos Maiolino - Fix various incorrect printf formats xfsprogs-3.1.6 (14 October 2011) - Re-synch of the header and libxfs files with the kernel code as of Linux 2.6.37, including reviving xfs_repair radix tree code. - Fix a xfs_repair phase 4 hang, thanks to Ajeet Yadav. - Subcommand names within various programs are no longer translated/localized, thanks to Arkadiusz Mi?kiewicz. - Build system fixes, thanks to Ted Ts'o. - Updates to teh xfs_info(8)/xfs_growfs(8) man page, thanks to Roman Ovchinnikov. - xfs_quota "df" no longer reports values twice what they should have been for project quotas. - mkfs.xfs now requires that sub-options are non-empty strings; thanks to Chris Pearson for reporting. - Better handling of short reads in libxfs. - xfs_quota now prints "N/A" rather than a large number for the quota file inode number for disabled quota types. - Bogus (unrelated) mount point entries no longer cause xfs_growfs, xfs_quota, and xfs_io to quit early. - xfs_repair no longer fails when the sector size of an underlying device is larger than the sector size in a hosted filesystem image. - Various other internal improvements, including refactoring and eliminating more build warnings. xfsprogs-3.1.5 (30 March 2011) - Polish translation update, thanks to Jakub Bogusz - xfs_repair now warns if running in low memory mode - Phase 2 of xfs_repair is now multithreaded - xfs_quota no longer attempts to get quota information if not enabled - Inode flags are now properly validated by xfs_repair - Metadump now obfuscates all file names reliably - xfs_io now supports the "fiemap" command, a more generic form of the "bmap" command - xfs_io now supports the "fpunch" command, as well as a "-p" flag to the "fallocate command. Both implement hole punching. Thanks to Josef Bacik - A number of other bug fixes thanks to Ajeet Yadav xfsprogs-3.1.4 (9 November 2010) - Add projid32bit handling to userspace, resolving type sizing issues when dealing with 32 bit project ids. - Make xfs_fsr use /proc/mounts if available. - Annotate that Debian packages are group maintained. - Fix a Debian packaging issue causing upgrade pain. xfsprogs-3.1.3 (26 August 2010) - Add xfs_io support for XFS_IOC_ZERO_RANGE - Fix depend targets. - Allow xfs_io resvsp command for foreign filesystems. - Fix configure --prefix. - Make xfs_db check for valid inode data pointer before dereferencing. - Validate btree block magic in the xfs_db freesp command, thanks to Peter Watkins. - Unbreak make update-po, permissions problem, thanks to Arkadiusz MiÅ›kiewicz. - Fix linking of libxfs and librt detection (needs pthread), thanks to Arkadiusz MiÅ›kiewicz. - Add a platform_discard_blocks stub for GNU/kFreebsd. xfsprogs-3.1.2 (6 May 2010) - Fix missing thread synchronization in xfs_repair duplicate extent tracking. - Fix handling of dynamic attribute fork roots in xfs_fsr. - Fix sb_bad_features2 manipulations when tweaking the lazy count flag. - Add support for building on Debian GNU/kFreeBSD, thanks to Petr Salinger. - Improvements to the mkfs.xfs manpage, thanks to Wengang Wang. - Various small blkid integration fixes in mkfs.xfs. - Fix build against stricter system headers. xfsprogs-3.1.1 (29 January 2010) - Fix various blkid topology support problems in mkfs.xfs. - Fix various build warnings. - Add automatic build dependency calculations. - Cleaner build system output. - Add missing aclocal m4 file to the package generation. - Arrange for release tags to be digitally signed. xfsprogs-3.1.0 (13 January 2010) - Reduce memory usage in xfs_repair by using better data structures. - Add additional checks in xfs_repair to detect freespace btree corruption instead of only rebuilding the btrees. Useful for the no-modify mode. - Fix libhandle to use the right path to issue by-handle ioctls for symbolic links and special files. - Use lazy superblock counters by default. At least kernel 2.6.22 is needed for this feature. - Use physical device sector size if available in mkfs.xfs, so 4K sector devices are handed more gracefully. - Add a German translation, thanks to Chris Leick. - Enable the madvise and mincor commands in xfs_io. - Fix unsafe temporary file creation in xfs_fsr. - Add support for discarding unused space on SSDs or thin provisioned arrays in mkfs.xfs. - Allow linking against libblkid for topology information. - Add symbol versioning for libhandle. - Remove the included RPM and binary tarball built infrastructure. - Various build system improvements. - Small fixes to xfs_db and xfs_io. xfsprogs-3.0.4 (17 September 2009) - Fix a memory leak in xfsprogs. - Increase hash chain length in xfsprogs when running out of memory. - Fix dmsetup invocation in libdisk to avoid warnings during mkfs on multipath devices. - Fix the -V option to various installed tools. - Small internal fixes to please the clang semantical analysis tool. - Debian packaging updates. - Rework Makepkgs and Makefiles to improve deb generation. xfsprogs-3.0.3 (30 August 2009) - Fix unaligned accesses in libxfs. - Various small fixes to xfs_db, xfs_repair and xfs_io. - Add fallocate command to xfs_io. - Enable readline support in xfs_io and xfs_quota. - Allow log sizes up to 2GiB (minus 1 byte) in xfs_mkfs. - Open the block device in xfs_repair exclusively, thanks to Nathaniel W. Turner. xfsprogs-3.0.2 (6 May 2009) - Updates to Debian build process after recent autoconf tweaks. - Fix a couple of minor man page syntax issues. xfsprogs-3.0.1 (4 May 2009) - Update the Makepkgs script to generate proper source tarballs. - New project(5) and projid(5) man pages. - Fix extent array reallocation in the xfs_io bmap command, thanks to Tomasz Majkowski. - Small specfile improvements, thanks to Jan Engelhardt. - Allow xfs_freeze to freeze non-XFS filesystems. - Fix the xfs_db bmbta command. - Fix parallel builds, thanks to Mike Frysinger. - Various autoconf/libtool fixes, thanks to Andreas Gruenbacher. xfsprogs-3.0.0 (4 February 2009) - Various smaller xfs_repair improvements. - Various gettext improvements, thanks to Jakub Bogusz. - Polish translation update, thanks to Jakub Bogusz. - Various xfs_quota fixes, thanks to Arkadiusz Miskiewicz. - Support parallel builds. - Detection of btrfs, gfs and gfs2 in libdisk. - Addition of the xfs_fsr and xfs_estimate tools previous found in the xfsdump package. - Resync libxfs to latest kernel implemenation. - Update all of xfsprogs to latest kernel interfaces. - Add sparse support to xfsprogs build. - Cleanup devel package for xfsctl, libhandle and libdisk only (remove libxfs interfaces). xfsprogs-2.10.1 (5 September 2008) - Improve xfs_repair -P option to disable xfs_buf_t locking. - Fix inode cluster I/O size for > 8KB block size filesystems. - Fix up ASCII CI output for mkfs.xfs and xfs_growfs. - Fix buffer handling in error cases in xfs_db (includes xfs_check and xfs_metadump). - Add packed on-disk shortform directory for ARM's old ABI, thanks to Eric Sandeen. - Increase default valid block count for a directory extent in xfs_metadump (from 20 to 1000). - Fix up mkfs.xfs -N option with "-d file" so it doesn't resize the target file (thanks to Michal Marek). - Improve libxfs cache handling with (un)referenced blocks. - Check that directory size is not too big in xfs_repair. - Improve xfs_repair to restore bad or missing ".." entries. xfsprogs-2.10.0 (26 May 2008) - Add ASCII case-insensitive support to xfsprogs. xfsprogs-2.9.8 (21 April 2008) - Add support for sb_features2 in wrong location in mkfs.xfs, xfs_repair and xfs_db. - Improve memory limits for libxfs cache in xfs_repair and added a -m option to manually limit usage of xfs_repair. - Add -c option to xfs_admin to turn lazy-counters on/off. - Added support for mdp in libdisk/mkfs.xfs, thanks to Hubert Verstraete. - Add -p option to fsck.xfs, thanks to Markus Rothe. - Cleanup sys v3 bzero/bcopy calls, thanks to Nigel Kukard. xfsprogs-2.9.7 (1 Mar 2008) - Lazy superblock counters not yet the default with mkfs.xfs. - Add -y (another no-op) fsck option. - Resolve mkfs allocation group count issue with small devices. - Fix mkfs to sector align the device size so zeroing the end of the device doesn't fail. xfsprogs-2.9.6 (7 Feb 2008) - Fix regression introduced by changing the mkfs.xfs defaults. - Made lazy superblock counters the default with mkfs.xfs. xfsprogs-2.9.5 (21 Jan 2008) - Updated mkfs.xfs defaults. - Make xfs_info handle mount points with spaces. - Improve xfs_repair's handling of invalid freespace btree extents. - Rebuild directories in xfs_repair if "." and ".." aren't the first two directory entries. This guarantees a directory is deletable. - Changed mkfs.xfs -f to wipe all old AG headers, not just the ones up to the end of the new filesystem size. - Purged the end of device whack buffer in mkfs.xfs to prevent a warning in certain device sizes. - Man page fixes. Thanks to Utako Kusaka for this. - Disable the ability to turn off unwritten extents in mkfs. xfsprogs-2.9.4 (7 Sep 2007) - Fixed xfs_repair segfaulting with directory block size different to the filesystem blocksize. - Fixed xfs_quota disable, enable, off and remove commands. Thanks to Utako Kusaka for this. - Improved the robustness of xfs_metadump. - Fix link issues with pthread library. xfsprogs-2.9.3 (23 July 2007) - Make xfs_repair support > 512 byte sector sizes. - Fixed include Makefile for new common header (xfs_metadump.h). - Fixed xfs_quota state command segfaulting with no mounted XFS filesystems. - Fixed xfs_quota printing out unusual message with "path n" command with no mounted XFS filesystems. - Fixed "quota -n" command with project IDs. - Improved "free" output when project quotas are defined, but haven't been enable on the filesystem. Thanks to Utako Kusaka for the above four fixes. xfsprogs-2.9.2 (18 July 2007) - Next major round of xfs_repair performance improvements: - Cache disk nlink values in Phase 3 for Phase 7. - Do multithreaded prefetch/processing based on AG stride option (ie. for concats). - Don't trash lost+found at the start of Phase 4, eliminates repeated "moving disconnected inode to lost+found" with successive xfs_repair runs. - Do multi-threaded sequential metadata prefetch. Method based on Agami patches posted for 2.7.18 xfsprogs. - Improve the libxfs cache with priority tagging to keep blocks around that have unfavourable I/O characteristics. - Make mkfs.xfs -f zero the old secondary superblocks before writing the new superblocks. - Fix up xfs_info and xfs_quota's -c handling with global commands. - Improve xfs_bmap -vp output to always show the FLAGS column. - Update man pages. xfsprogs-2.9.1 (28 June 2007) - Added filestreams support to xfs_io. - Fix up libattr Makefile to append to LTLDFLAGS. Thanks to Arfrever Frehtes Taifersar Arahesis for this. - Fix up build not to ignore LDFLAGS generated by configure. Thanks to SpanKY for this. xfsprogs-2.9.0 (5 June 2007) - Added new tools: xfs_metadump and xfs_mdrestore. - Fix up the HAVE___U32 fix from 2.8.20 Thanks to Eric Sandeen for pointing this out. xfsprogs-2.8.21 (28 May 2007) - Add support for lazy superblock counters in mkfs.xfs, xfs_db, xfs_repair, xfs_growfs and also libxfs. - Fix xfs_quota project command to stop it operating on special files. Thanks to Leo Baltus. xfsprogs-2.8.20 (23 February 2007) - Fix xfs_repair not detecting invalid btree root in inodes. - Fix xfs_repair restoring corrupted superblock after repairing it. - Fix xfs_repair crashing on invalid quota inode values. - Fix xfs_quota gracetime reporting. Thanks to Utako Kusaka for this. - Fix libxfs IO_DEBUG output. - Instead of using AC_CHECK_TYPES which isn't supported for older versions of autoconf, add our own type check in the m4/package_types.m4 file for __u32. Suggested by Nathan Scott and discovered by wookey@aleph1.co.uk. xfsprogs-2.8.19 (31 January 2007) - Fix pthread stack size setting in xfs_repair. - Fix xfs_bmap -n option displaying a truncated extent. - Fix xfs_io mwrite segfault. Thanks to Utako Kusaka for these two fixes. - Fix errors in xfs_quota(8) man page. xfsprogs-2.8.18 (8 December 2006) - is an installed file, we cannot simply rename it, as other applications using it (accidentally or not) may break. The xfs_list.h name was inconsistent with everything else too. - Fix "pointer targets in assignment differ in signedness" warnings - Update Debian packaging. - Fix up two issues with xfs_db and bmap. If the data/attr fork is local, it either infinite loops or crashes. If both are displayed, the attrs are wrong. - Fix up xfs_io mmap read that read from the wrong offset. - Updated xfs_io man page. Thanks to Utako Kusaka for the above three fixes. xfsprogs-2.8.17 (5 December 2006) - Fix up libxfs SEGV when attempting to mount a non-XFS filesystem. Thanks to Utako Kusaka for this. - Fix up xfs_repair aborting if it finds an inode with an invalid inode type. - Fix up default realtime extent size for large block sizes. - Rename include/list.h to xfs_list.h so that other applications do not accidentally use it. xfsprogs-2.8.16 (30 October 2006) - Fix up an endian problem for nlink setting in phase 7 for xfs_repair. xfsprogs-2.8.15 (19 October 2006) - Fix up nlink checks and repairs in phase 7 for xfs_repair. - Remove a bogus LEAFN warning for a single leaf node v2 dir. Thanks to Roger Willcocks for this. xfsprogs-2.8.14 (6 October 2006) - Fix up the ring command in xfs_db, Thanks to Utako Kusaka for this. - Set the blocksize on the device to the given sector size which is _not_ necessarily 512 bytes; idea suggested by Shailendra Tripathi. - Fix up xfs_copy and its variable argument handling around vfprintf; xfs_copy was seg faulting on x86_64. xfsprogs-2.8.13 (21 September 2006) - Fix v2 directory checking with holes and unreadable blocks. - Fix a memory leak in dir2 checking. - Update libdisk/md support to work out the stripe width based on (# raid-disks - # parity disks) which doesn't include any spare disks (which we mistakenly did before). Thanks to Shailendra Tripathi's suggestions. - Get the kernel int types of __u32 and friends from if we can, otherwise define them ourselves. xfsprogs-2.8.12 (29 August 2006) - Multi-thread modifications to xfs_repair. - Updated Polish translation, thanks to Jakub Bogusz. - Change default mkfs realtime extent size setting to perform better for buffered writes. xfsprogs-2.8.11 (08 August 2006) - xfs_repair prefetch optimisations. - Make many tools use direct I/O on Linux if the underlying device supports it. Mainly for speeding up xfs_repair as libxfs does its own internal metadata buffering now. - Fix warnings from mkfs.xfs on ramdisk devices. - Fix issues with symbolic link handling in Makefiles. xfsprogs-2.8.10 (02 August 2006) - Fix v2 directory rebuilds in phase6 of xfs_repair. - Fix buffer sizing issue for large pagesize systems, affecting mkfs auto-device-type-detection heuristics. xfsprogs-2.8.9 (18 July 2006) - Fix rpm issue with install targets as uid/gid zero (we now using symbolic names rather than the numeric versions). xfsprogs-2.8.8 (14 July 2006) - Fix issues with makedepend on libtool libraries. xfsprogs-2.8.7 (10 July 2006) - Fix build of xfs_logprint for different uuid_t definitions; thanks to Craig Rodrigues. xfsprogs-2.8.6 (07 July 2006) - Fixed xfs_repair handling of duplicate names in a directory. xfsprogs-2.8.5 (05 July 2006) - Update translation Makefile to work better with the Ubuntu translation system. Thanks to feedback from Martin Pitt. - Fix annoying "ignores datarootdir" warning from configure. - Fix issues with makedepend build infrastructure. - Add prefetch code for improved xfs_repair run times. xfsprogs-2.8.4 (23 June 2006) - Improve Debian udeb package handling, thanks to Frans Pop. - Fix a situation where xfs_growfs can fail to match a block device to a filesystem correctly; thanks to Bastian Kleineidam. - Minor corrections to the xfs_growfs man page. xfsprogs-2.8.3 (21 June 2006) - Fix a possible segv in xfs_growfs; thanks to Bastian Kleineidam. xfsprogs-2.8.2 (17 June 2006) - More updates to repair/libxfs for improving performance - Incorporate librt into the build process for lio_listio - Minor xfs_logprint tweaks and fixes. - Small updates to xfs_io manual page. - Several fixes from earler 2.8 releases with respect to inode/buffer cache refcounting. xfsprogs-2.8.1 (29 May 2006) - Fix endianness issues on FreeBSD. xfsprogs-2.8.0 (18 May 2006) - Initial pass at user space caching, ultimately provides a starting point for a faster, parallel version of repair. - Fix several inode/buffer reference counting issues. - Fix compiler warnings, and builds on certain glibc versions having issues with the device major() macro. - Added code to xfs_db and xfs_admin to allow conversion from version 1 to version 2 logs. xfsprogs-2.7.18 (16 May 2006) - Fixed a case where xfs_repair was reporting a valid used block as a duplicate during phase 4. - Fixed a case where xfs_repair could incorrectly flag extent b+tree nodes as corrupt. - Portability changes, get xfs_repair compiling on IRIX. - Parent pointer updates in xfs_io checker command. - Allow LDFLAGS to be overridden, for Gentoo punters. xfsprogs-2.7.17 (05 April 2006) - Fix libxfs access(2) check on /proc/mounts, which was causing issues when xfs_check/xfs_repair run on readonly root filesystem mounts. - Fix Debian packaging for libc-dev build dependency. - Fix up auto lib64 install detection for x86_64 platforms. xfsprogs-2.7.16 (22 March 2006) - Fix freespace accounting in xfs_quota(8) df command. - Fix a typo on the xfs_quota(8) man page. - Make -O2 (cc optimisation level) the default. xfsprogs-2.7.15 (03 March 2006) - Fix the way external log/realtime devices were handled in userspace with older kernels (subtely different in procfs) - Fix a corruption problem in xfs_copy(8) when attempting to zero the (old) log, a section was sometimes missed (depends on log and I/O buffer (mis)alignment). xfsprogs-2.7.14 (15 February 2006) - Debian packaging updates (debmake out, debhelper in). - Fix a header to work with additional compiler variants. xfsprogs-2.7.13 (08 February 2006) - Convert fsck into a shell script and make it provide a hint to run repair/check (in non-auto fsck modes). Thanks to Marian Jancar for this. - Fix compilation botch on non-Linux platforms (duplicate type definitions). xfsprogs-2.7.12 (31 January 2006) - Added initial Polish translation. Thanks to Jakub Bogusz for this. - Fixed rpm specfile with respect to INSTALL_{USER,GROUP}. xfsprogs-2.7.11 (16 January 2006) - Fix a problem with the generated source tarballs and a missing parent.h header file. xfsprogs-2.7.10 (16 December 2005) - Make xfs_db keep trying when root inode can't be read. - Make xfs_db check AGF BNO and CNT btree consistency. - Tweak a couple of libxfs headers so they can be used by C++ programs (removes nested struct declarations, which are used outside the scope they're declared in). - Fix a rounding issue in xfs_quota time reporting, making it more consistent with the standard quota utilities. - Fix dopey libxfs message "Unmount and run xfs_repair.", especially annoying when printed by xfs_repair itself. - Fix a dir2 xfs_repair bug, misdiagnosing a valid dir as corrupt. Thanks to Masanori Tsuda. xfsprogs-2.7.9 (08 December 2005) - Fix thinko in libxcmd cvtnum routine - Fix EFI/EFD printing in xfs_logprint xfsprogs-2.7.8 (05 December 2005) - Extend xfs_io to do aligned direct IO automatically - Report direct IO parameters (dioinfo) in xfs_io - Make xfs_mkfile a shell script wrapper around xfs_io xfsprogs-2.7.7 (16 November 2005) - Fix some gcc compiler warnings on 64 bit platforms. - Remove last reference to a (kernel) header. - Updated aclocal.m4 - Fix a bug in xfs_io lsproj/chproj recursive modes. - Add xfs_io recursive modes for the extsize command. - Add xfs_db version command modes for attr1 and attr2. xfsprogs-2.7.6 (31 October 2005) - Add support for the inode extent size hint for the regular data device (previously was realtime only), and allow the optional inheritance of this property. - Add support for additional read/write patterns in xfs_io (reverse and random, in addition to sequential forwards). - Add some mkfs debugging options to aid testing inheritance of realtime, project ID, and extsize inode attributes. - Add mkfs option for forcing use of ATTR2, and make growfs report its use. - Fix use of cursor in attr_list_by_handle() libhandle code. - Fix several compiler warnings when building on IRIX. xfsprogs-2.7.5 (26 October 2005) - Fix an endian bug in xfs_db "frag" command. - Fix some errors on the xfs_quota(8) man page. xfsprogs-2.7.4 (08 October 2005) - Fix read and write calls in xfs_io to allow buffers larger than 4GiB on 64 bit platforms. - FreeBSD build tweaks from Craig Rodrigues. - Fixed a few minor compiler warnings. xfsprogs-2.7.3 (29 September 2005) - Fix xfs_repair handling of the morebits bit. - Merge back several kernel changes related to attr2. - Extended xfs_db expert mode commands - Clean up some fsxattr uses to reduce number of syscalls, now that IRIX also supports project identifiers via this interface. xfsprogs-2.7.2 (28 September 2005) - Fix up xfs_repair segmentation fault due to wrong allocation size. xfsprogs-2.7.1 (20 September 2005) - Fix up reporting of devices in xfs_growfs - now uses /proc/mounts in preference to /etc/mtab. - Fix a strtok-related bug in the extraction of device names, also only affecting xfs_growfs. xfsprogs-2.7.0 (16 September 2005) - Support for updated extended attributes format (attr2) - Make xfs_quota tool issue a quota sync in all the needed places, before reporting, to counter affects of delayed allocation. - Quota-related ID signedness issue fixes. - Expert mode xfs_db commands to set/remove attributes. xfsprogs-2.6.37 (11 August 2005) - Fix FreeBSD builds (getmntinfo), thanks to Craig Rodrigues. xfsprogs-2.6.36 (28 July 2005) - Fix mkfs stripe unit alignment checks for external logs - Fix running xfs_db on non-XFS devices (was segfaulting) - Fix a 32 bit wrap in xfs_repair searching for secondary superblocks. xfsprogs-2.6.35 (01 July 2005) - Add back fd_to_handle() to libhandle. - Add handle call mappings to xfsctl() for IRIX. xfsprogs-2.6.34 (20 June 2005) - Switch to the fsxattr xfsctl for getting/setting project identifiers on inodes, remove the short-lived specialised ioctls for doing this. - Make the "blocktrash" xfs_db command available in expert- mode only. xfsprogs-2.6.33 (13 June 2005) - Another libhandle fix on 64bit, Big Endian systems. xfsprogs-2.6.32 (08 June 2005) - Minor endian cleanups in some tools. - Fix a couple of xfs_quota double-reporting issues when issuing commands via the -c (command line) 0option. xfsprogs-2.6.31 (06 June 2005) - Fix previous MD driver-specific change to correctly handle (i.e. not "stripe align") linear arrays. - Add MD RAID level 4, 6, and 10 support. - Make mkfs.xfs automatically adjiust the geometry to use a sector size that matches the block size when MD RAID level 4/5/6 are in use. - Couple of minor man page fixups, including patch botch on initial revision of xfs_quota(8). xfsprogs-2.6.30 (03 June 2005) - Add xfs_quota(8) command which knows how to do all things quota related, and can also do the XFS specific extensions like project quota, realtime device quota, etc. - Created a library of common code (libxcmd.a) shared by xfs_growfs, xfs_io and xfs_quota. - Fix use of regular files for realtime subvolumes (debugging only, really). - Fix bug in xfs_io command line option handling when commands where specified for multiple files at once. - Allow xfs_io to specify O_NONBLOCK for regular file IO. - Fix MD driver-specific code to not attempt stripe alignment for volumes that are not stripes (e.g. concat/mirror). xfsprogs-2.6.29 (19 April 2005) - Fix mkfs.xfs -dfile. - Fix libhandle on 64bit, Big Endian systems. xfsprogs-2.6.28 (30 March 2005) - Fix compiler warning in repair/dir.c size checks. - Fix more compilation problem with version 4 of gcc (thanks to Andreas Jochens). - Make xfs_db and xfs_repair cope with filesystems that have project quota enabled. xfsprogs-2.6.27 (23 March 2005) - Fix default mkfs allocation group size calculations for filesystem sizes in the range 32 - 64 terabytes. - Add noalign mkfs suboptions for -d/-r to disable the sunit/swidth auto-alignment (based on logical volume geometry, extracted from the driver). xfsprogs-2.6.26 (08 March 2005) - Fix compilation problem with version 4 of gcc (thanks to Andreas Jochens). - Added a streamlined for programs wanting to make use of the XFS-specific kernel interfaces (to address complaints that was "heavy"). - Add imap as an expert command in xfs_io, making it more easily accessible to those who need it. - Extended statistics reporting for xfs_io command. - Fixed readline support for current distributions. - Add an --enable-termcap=[yes/no] configure option, and changed --enable-readline=[yes/no] to not force linking with libtermcap. Builds on some platforms may need to use both options, but most distributions do not require --enable-termcap when linking against libreadline. - Minor man page updates. xfsprogs-2.6.25 (08 October 2004) - Fix build with really old glibc versions. xfsprogs-2.6.24 (29 September 2004) - Allow 'e' suffix in size arguments to mkfs. - Update mkfs man page description of maximum allocation group size. - Update mkfs and xfs_db man pages to use consistent, standard notations. - Sync up user/kernel source in libxfs and headers. xfsprogs-2.6.23 (17 September 2004) - Fix xfs_io pread/pwrite -b option, when used more than once we would use the largest of the previous values, instead of the (possibly smaller) value specified. - Add recursive modes to lsattr/chattr xfs_io commands. - Make xfs_io run any given command line commands (-c) on all files specified, not just the first. xfsprogs-2.6.22 (10 September 2004) - Update xfs_io to get a clean compile on IRIX with the MIPSPro compilers. - Add documentation about additional XFS inode flags. - Add xfs_io write options to include fsync/fdatasync in the timing results it displays. - Add xfs_fsop_counts output to the xfs_io statfs data, which also shows free realtime space, etc. - Add knowledge of additional inode flags for nosymlinks and project ID inheritance. xfsprogs-2.6.21 (09 August 2004) - Support realtime bit inheritance on directories. - Fix xfs_io build with unusual (old) glibc versions. - Fix tools to not issue the BLKFLSBUF ioctl to ramdisk devices. Thanks to Bo Yang for this fix. xfsprogs-2.6.20 (28 July 2004) - Fix a segfault on xfs_io open error path for non-XFS files. Thanks to Steinar H. Gunderson for this fix. xfsprogs-2.6.19 (16 July 2004) - Fix two byte count size wraps in xfs_copy. - Minor man page fixes from Eric Raymond. xfsprogs-2.6.18 (23 June 2004) - Fix libhandle from possibly returning an invalid handle length on systems where size_t is 64 bits. - Minor autoconf fixups to get rpm test working on all platforms again. - Minor man page updates fixing minus/hyphen usage. xfsprogs-2.6.17 (23 June 2004) - Fix use of isset macro, getting realtime devices to function correctly in xfs_db and xfs_repair. - Fix initialisation of realtime devices in libxfs. xfsprogs-2.6.16 (17 June 2004) - Add sendfile command into xfs_io(8) to exercise that functionality. - Remove maxtrres program that was used in the build to generate a header for mkfs' consumption. - This allows cross-compiles to be greatly simplified. - Portability tweaks for building on other platforms. - Fix obscure bug in log size lower boundary checks for auto-sized logs when stripe alignment is in effect; the enforced lower bound could have been set too low. xfsprogs-2.6.15 (09 June 2004) - Make xfs_check test for a dirty log before proceeding to check the filesystem. - Fix couple of minor bugs in xfs_io (readonly handling on writes, off-by-one error in open file error reporting). xfsprogs-2.6.14 (13 May 2004) - Allow logprint to copy a log to a file (-C) and to dump a log from beginning to end showing ondisk log record (-d). - Fix logprint handling of -f option - shouldn't be doing the UUID check in that case, since we don't have the SB. - Remove MD device superblock "clean" check, following Neil Brown's advice. - Small Debian packaging tweak to say xfsprogs has an fsck. xfsprogs-2.6.13 (03 May 2004) - Zero out more at beginning and end of device at mkfs time (get all old MD superblocks at the end, for mount by label). xfsprogs-2.6.12 (30 April 2004) - Extract stripe unit/width from device mapper devices (added libdisk infrastructure, used by mkfs.xfs). - Fix rounding in xfs_io(8) bytes read/written output. - Sync up user/kernel source in libxfs and headers. - Fix compiler warnings on 64 bit platforms. - Update i18n message catalog. xfsprogs-2.6.11 (15 April 2004) - Fix file descriptor leak in path_to_fshandle. A file was being opened but never closed, regardless of whether that descriptor was being cached. Now close the file on error or if it is not being cached. - Fix xfs_repair handling of a corrupt v2 directory with multiple entries having the same name. xfsprogs-2.6.10 (05 April 2004) - Fix botch in recent addition of new superblock field (features2) which could result in filesystems with v2 logs being created with invalid superblock fields. Thanks to Chris Pascoe for this fix. - Fix error when forcing a too-large v2 log stripe size back to 32K. Thanks to Chris Pascoe for this fix too. - Fix xfs_copy -d option so that it really does create a duplicate filesystem (the log is duplicated too now in that case, whereas previously a fresh log was created). xfsprogs-2.6.9 (26 March 2004) - Update HFILES in xfsprogs/io/Makefile to package io/io.h xfsprogs-2.6.8 (25 March 2004) - Fix xfs_db when dumping v2 dirs larger than the fsb size. - Several xfs_io additions - support for memory mapped areas, multiple open files, expert mode (freeze, shutdown, error injection, etc), fadvise (Linux-specific), allow user to specify a create mode to open(2). - Fix xfs_bmap verbose mode stripe alignment information. - Fix typo on xfs(5) man page. xfsprogs-2.6.7 (19 March 2004) - Fix up UUID library checks again, previous fix didn't work for older versions of autconf. - Allow for future extensions to the XFS ondisk structure by reserving an extra 32 bits in the superblock for feature bits (update xfs_db to dump them). - Fix xfs_repair handling of version 2 directories with a hole at the start. - Fix an endian bug in xfs_copy, when operating on allocation groups with multi-level freespace btrees. - Ensure xfs_repair "dangerous" mode does not attempt to set the device blocksize, this generates an error when target filesystem is mounted readonly. xfsprogs-2.6.6 (03 March 2004) - mkfs now opens the devices it's operating on with the O_EXCL flag set, which is used by the Linux 2.6 block layer to ensure concurrent access does not happen. - Allow xfs_io to operate on files from other filesystems, with the XFS-specific commands unavailable in this mode. - Fix configure scripts to also search for a UUID library in /usr/lib64 which is its home on AMD64/x86_64. xfsprogs-2.6.5 (20 February 2004) - Fix up mkfs to ensure that the log size is a multiple of the v2 log stripe size even if the log happens to be aligned on a log stripe boundary (always check it). xfsprogs-2.6.4 (17 February 2004) - Fix a few more libxfs/repair leaks. - Fix up some libhandle routines, add the open_by_fshandle routine required by recent versions of xfsdump. xfsprogs-2.6.3 (19 January 2004) - Merge Steve Langasek's work on the Debian installer support for xfsprogs. - Add knowledge to xfs_db about the security namespace in its extended attributes commands. - Sync up user/kernel source in libxfs and headers. - Fix a couple of compilation warnings. - Workaround for some versions of autoconf mishandling the AC_CHECK_SIZEOF macro. - Fix a memory leak in libxfs, most noticable in xfs_repair. xfsprogs-2.6.2 (17 December 2003) - Fix dev_t sizing issues in user tools - glibc uses a 64 bit number and XFS has a 32 device bit number, confusion reigns. Not much manipulates device numbers in the XFS user tools though, hence hasn't really been seen before. Thanks to Christoph for the patch. xfsprogs-2.6.1 (27 November 2003) - Human-friendly xfs_io read/write bsize specifications. - Dump throughput and IOPs values after xfs_io reads/writes. - Sync up user/kernel source in libxfs, libxlog and headers. xfsprogs-2.6.0 (28 October 2003) - Change to mkfs strategy for allocation group count and size default. Scales significantly better for large filesystems. xfsprogs-2.5.11 (10 October 2003) - Incorporate Jan Derfinaks change to the Linux block ioctls used in libxfs, allowing this code to compile cleanly with include files from Linux 2.6.0-test5 onward. xfsprogs-2.5.10 (30 September 2003) - Fix up xfs_logprint to handle version 2 logs for its operation output (previously core dumped on it). xfsprogs-2.5.9 (19 September 2003) - Sync up user/kernel source in libxfs, libxlog and headers. - Add new inode flags into xfs_db too. xfsprogs-2.5.8 (12 September 2003) - Add missing options to xfs_db frag command one-line summary. - Add xfs_io commands for setting and clearing new inode flags for immutable/append-only/sync/no-atime/no-dump. - Dump some other statfs fields in the xfs_io statfs commands. - Remove "test" mode from xfs_repair, only useful in xfs_check. - Fix problem in xfs_logprint where it was trying to continue in the presence of a corrupt log when it shouldn't have. - Fix an incorrect assertion in xfs_logprint in regards to the validity of the log start block. - Fix xfs_growfs (and hence xfs_info) to allow it to be given either a mount point or a device in the mount table - it'll figure it out and should do the right thing either way now. xfsprogs-2.5.7 (29 August 2003) - Sync up user/kernel source in libxfs and headers. - Make xfs_copy a tad more portable, although work remains. - Add a "test" mode to xfs_repair and xfs_check which allows for sparse (and hence extremely large) filesystem testing. xfsprogs-2.5.6 (19 August 2003) - Fix a mkfs problem where it could exit inappropriately when a large data volume stripe unit was either specified on the command line or via querying the underlying volume manager. xfsprogs-2.5.5 (07 August 2003) - Update xfs_io command to allow reading from non-XFS files. - Sync up user/kernel source in libxfs, libxlog and headers. - Update xfs_db and xfs_logprint commands to print new inode flush iteration field. xfsprogs-2.5.4 (23 July 2003) - Update xfs_io bmap command to report unwritten extent flag if it is set on an extent (in verbose mode only). - Introducing xfs_copy. - Fix shell quoting problem in xfs_bmap script. xfsprogs-2.5.3 (07 July 2003) - Update xfs_io commands which take user input in terms of byte counts to now also allow unit prefixes like mkfs.xfs. - Tweak build to avoid unnecessary rebuilds of international language files (if present), suggested by Steve Langasek. - Fix usage message in mkfs.xfs, it was out of date. - Fix some filesystem type detection code, in particular the bfs probe code was broken for 64 bit machines (found by QA test 032) and the hfs code was broken too (originally found by Ethan Benson). We now also detect hfs+ filesystems. xfsprogs-2.5.2 (25 June 2003) - Fix xvm stripe detection in libdisk - pass correctly sized structures to xvm ioctls. - Add pthread library checks into configure and build scripts for work-in-progress on xfs_repair and xfs_copy. - Fix missing initialisation of stripe unit/width alignment information during libxfs_mount. - Fix botched repair typecast for multi-terabyte filesystems. xfsprogs-2.5.1 (23 June 2003) - Fix libdisk device driver (volume managers) detection code used by mkfs, so that drivers with multiple majors are not incorrectly processed. xfsprogs-2.5.0 (18 June 2003) - Fix libdisk (and hence mkfs) code which warns on MD devices with the clean flag not set, apparently this is not so wise. - Fix libxfs_device_zero to work with smaller-than-requested write return values. - Fix error in xfs_io pwrite code with large request sizes. - Fix rounding-down-input problems in several xfs_io commands. - Changed mkfs.xfs default log size scaling algorithm slightly, to create larger logs at smaller filesystem sizes by default (thanks to Andi Kleen for the patch). - Enable support for sector sizes larger than 512 bytes. xfsprogs-2.4.12 (02 June 2003) - Fix xfs_logprint handling of any version 2 log device. - Remove calls to exit in libhandle, propogate errors to caller, and bumped libhandle version from 1.0.1 to 1.0.2. xfsprogs-2.4.11 (30 May 2003) - Extract device sector size at mkfs time and issue warnings if the requested filesystem sector size is too small. - Sync up user/kernel source in libxfs, libxlog and headers. - Skip realtime initialisation in libxfs mount path if the caller is xfs_db, otherwise we get nonsense warnings. - Update xfs_io with a couple of additional commands. - Fix xfs_logprint handling of corrupt v2 log devices. xfsprogs-2.4.10 (12 May 2003) - Fix a bug in mkfs - creating version 2 logs, an incorrect stripe unit value was being passed to libxfs_clear_log. All recent versions of xfs_repair will fix this, however, because xfs_repair uses the correct stripe unit value. - Fix a bug in xfs_logprint, when dumping a corrupt log. - FreeBSD updates from Alexander Kabaev. - Large sector size updates for mkfs (disabled at the moment). - Large sector size fixes for xfs_repair. - Sync up with aeb's mount source for filesystem detection. xfsprogs-2.4.9 (03 May 2003) - Allow xfs_repair to run on read-only filesystems. xfsprogs-2.4.8 (26 April 2003) - Rework configure.in to make use of shared macros. - Fix up #include lines to allow compilation of sources with installed headers rather than local headers. - Fix botches in xfs_bmap shell script which prevented any arguments being passed on to xfs_io (from Jan Derfinak). xfsprogs-2.4.7 (22 April 2003) - Clarify XFS system call interfaces, fix up documentation. xfsprogs-2.4.6 (11 April 2003) - Fix a bug in detection of "clean" and "error" states with MD devices. - Fix configure tests that used AC_PATH_PROG incorrectly. - Add support for libedit, if libreadline is unavailable. - Fix the libxfs build on big endian platforms. - Sync up user/kernel source in libxfs and headers. xfsprogs-2.4.5 (03 April 2003) - Sync up xfs_inode.c in libxfs. - Implement get_unaligned/put_unaligned in libxfs. xfsprogs-2.4.4 (30 March 2003) - Correct display of imaxpct in mkfs.xfs output. - Portability changes; including some code to support use of several tools on Mac OS X (for Russell), ditto for FreeBSD (from Russell); also did a simplistic backport to IRIX (for me), so that I can run purify on some of the tools. - See doc/INSTALL for more details on this. - Sync up user/kernel source in libxfs and headers. - Fix up some warnings when compiling libxfs on big endian platforms. - Fix a configure.in botch which resulted in libreadline always being used even when it was not asked for. - Fixed the configure.in script so that if gettext disabled, we don't check for the gettext tools (and no longer fails if they were not found). - Added the ability to specify a different user and/or group to install as (previously, and still by default, root/root were always used here). xfsprogs-2.4.3 (27 March 2003) - Cleanups to the build process, in particular the automatic rpm package generation Makefile and spec file template. - Makepkgs script can now propagate failures back from make. - Minor configure.in update to deal with readline libraries which have not been linked correctly. xfsprogs-2.4.2 (25 March 2003) - Added the xfs_io(8) command, an xfs_db(8) alike command for testing and debugging the XFS file IO path. - Added an optional dependency on the GNU readline library which is "off" by default and enabled with the configure option --enable-readline=yes; it affects the interactive tools only (xfs_db and now xfs_io). - Implemented xfs_bmap(8) as a shell script wrapper. - Documented the mkfs.xfs -f, -llogdev and -rrtdev options. - Corrected size check for realtime summary inode (not the same as the realtime bitmap inode) in xfs_repair. xfsprogs-2.4.1 (18 March 2003) - Fix error reporting when zeroing parts of the realtime device in phase6 of xfs_repair. - Add a mkfs.xfs check for Mac partitions before writing to the device. - Thanks to Ethan Benson for this. - Minor fix to the xfs_bmap(8) man page. - Sync up user/kernel source in libxfs and headers. xfsprogs-2.4.0 (06 March 2003) - Enable unwritten extents by default in mkfs.xfs. - Add a command to xfs_db to enable unwritten extents. - Add an option to xfs_admin to use the above command. - Add command to xfs_db to print out the currently enabled feature bits and version number. - Make xfs_db slightly more robust in the presense of bad ondisk data. - Rationalise some xfs_db superblock-related code and the uuid command now checks for a dirty log before zeroing. - Add stripe alignment information to xfs_bmap. - Sync up user/kernel source in libxfs and headers. - Update man pages, fix a typo in the xfs_admin man page relating to the UUID options. xfsprogs-2.3.11 (18 February 2003) - Missed a build dependency for the Debian build process. xfsprogs-2.3.10 (17 February 2003) - Fix a divide-by-zero error in mkfs with certain stripe unit and/or width options specified. - Sync up user/kernel source in libxfs and headers. xfsprogs-2.3.9 (31 December 2002) - Additional xfs_repair check in v2 directory handling for blks with no data entries (merged from IRIX), includes several handy comments sprinkled throughout this v2 dir code. - Fix an endian bug in the same area of code (v2 dirs, phase 6, longform_dir2_rebuild_setup) - xfs_repair has additional checks for bad sector values now. - xfs_repair I18N changes. - Fix detection of readonly mounts, slightly botched in 2.3.8. - Fix references to removed ioctl commands on xfs(5) man page. xfsprogs-2.3.8 (18 December 2002) - Initial support for I18N (still more to do here). - Initial changes for filesystems with greater than 512 byte sector sizes (still plenty more to do here too). - Tidy up libxfs functions which take a "flags" argument. - Sync up user/kernel source in lib{xfs,xlog} and headers. - Fixed incorrect use of XFS_FSB_TO_DADDR macro in xfs_db's faddr.c::fa_dirblock routine - now use XFS_FSB_TO_BB here, as set_cur() takes basic blocks as its third parameter. - Fixed obscure issue in mkfs where only the first AG would get its AGFL freelist "fixed" - not clear this caused any issues in practice (on Linux it's always been this way, we now match up with IRIX though). - Made xfs_growfs filesystem geometry output match up with that displayed by mkfs.xfs (xfs_growfs was missing a comma before the log version field). - Fixed an issue in xfs_repair where data past the end of the valid superblock fields was sometimes not cleared, when it really should have been (due to a libxfs problem). - Shell scripts (xfs_info, xfs_check, etc) now also report the xfsprogs version number via -V, like other commands. xfsprogs-2.3.7 (14 November 2002) - Fix an endian bug in xfs_db freesp command when descending into multi-level agf cnt/bno btrees. xfsprogs-2.3.6 (31 October 2002) - Sync up user/kernel source in lib{xfs,xlog} and headers. - Fix several warnings from newer (3.2) versions of gcc. - Minor header file shuffling. xfsprogs-2.3.5 (10 October 2002) - Sync up user/kernel source in lib{xfs,xlog} and headers. - Fix mkfs (libxfs) bug when using BLKFLSBUF ioctl - we passed in the device number instead of a file descriptor (and EBADF was the end result, which we ignored). - Thanks to Anton Blanchard for fixing this. xfsprogs-2.3.4 (04 October 2002) - Fix size calculation bug in xfs_repair's memory allocation, reduces memory usage by a factor of 4. xfsprogs-2.3.3 (16 September 2002) - Fix mkfs bug when optimizing AG size on striped devices, ASSERT(agcount != 0) tripped on single-ag filesystems. xfsprogs-2.3.2 (10 September 2002) - Use pread/pwrite instead of lseek + read/write. xfsprogs-2.3.1 (03 September 2002) - Allow xfs_db to accept negative numbers when writing values. xfsprogs-2.3.0 (03 September 2002) - Several changes to geometry ioctl callers which will make the tools useable on older kernel versions too. - Mainly affects xfs_bmap and xfs_growfs. - Do some additional cleanup after autoconf has run. xfsprogs-2.2.3 (28 August 2002) - Update libdisk for a few other filesystems. - Fix call to lvdisplay on LVM volumes so that lvdisplay always gets the full, real path to the volume, as required. xfsprogs-2.2.2 (19 August 2002) - Fix endian bug in xfs_db, was not flipping 16-bit numbers. - Make xfs_repair recognize a NULLFSINO and print that in addition to "18446744073709551615" for easy recognition. - Fix format string that xfs_repair uses when fixing inodes, so that the new inode numbers are printed correctly. xfsprogs-2.2.1 (09 August 2002) - Fix buglet in libdisk get_driver_block_major() routine which would result in incorrect majors being returned for not-found drivers. - Fix problem in install process with newer autoconf versions. xfsprogs-2.2.0 (08 August 2002) - mkfs.xfs defaults to a blocksize of 4096 bytes, and no longer uses getpagesize(2) to dynamically configure the default size. - Add EVMS stripe unit/width auto-detection support in mkfs.xfs (patch from Luciano Chavez). - Sync user/kernel headers (arch.h incorporated into xfs_arch.h, and several other minor changes). xfsprogs-2.1.2 (17 July 2002) - Fix up log stripe unit specification options, and update man page. Also fix suffix handling for data su/sw options (disallow unit suffixes on -d sunit,swidth,sw and -l sunit). Add "s" (512-byte sectors) as valid suffix. - Automatically select v2 logs if a log stripe unit is specified. xfsprogs-2.1.1 (04 July 2002) - Build infrastructure updates so that configure options can be used to specify paths rather than semi-hard-coded path names controlled by the ROOT/ROOT_PREFIX environment variables; eg. now allows /lib64 and /lib32 xfsprogs-2.1.0 (14 June 2002) - Support for XFS version 2 log format. - Fix for xfs_repair mangling i8count for dir2_sf directories - Minor mkfs.xfs man page update for blocksize limits on Linux - xfs_cred.h split into xfs_acl.h, xfs_cap.h and xfs_mac.h - Fix typo in mkfs realtime summary inode alloc failure message xfsprogs-2.0.6 (30 May 2002) - Fix error returns from log recovery (affects xfs_repair). - Fix the way mkfs.xfs round downs the device when the last AG is smaller than the minimum AG size. - Fix bug in xfs_repair da_write() routine, which affects filesystems where the data blocksize != naming blocksize (see xfs_info output). - Fix a use-after-free bug in xfs_repair code for checking version 1 btree-format directories. - Add checks of the ACL permissions field into xfs_repair. xfsprogs-2.0.5 (02 May 2002) - Size AGs so that they do not always start on the same part of a striped disk - Fix an off-by-one error on rounding down an AG that is too small to be an AG - Don't auto-grow the log to be larger than an AG - Change the error philosophy for -d su=,sw= away from forcing the XFS stripe size to match the volume manager stripe size and instead accept, with a warning, the stripe unit & width supplied on the commandline. - Update xfs_growfs man page - Don't build libxlog.a with DEBUG enabled - xfs_db fixes from ASANO Masahiro at NEC xfsprogs-2.0.4 (17 April 2002) - Minor update sync'ing with kernel changes (less endian swabbing in libxfs code) xfsprogs-2.0.3 (13 April 2002) - Important build system update, was causing libxfs to be built incorrectly, which can cause xfs_repair to fail by tripping asserts in additional libxfs debug code. xfsprogs-2.0.2 (04 April 2002) - Bumped version of libhandle to libhandle.so.1.0.1 This changes open_by_handle() and friends so that O_LARGEFILE is added to the open flags. This allows xfsdump to dump files greater than 2^31-1 bytes instead of not dumping the large files and giving warning messages. xfsprogs-2.0.1 (12 March 2002) - Fall back to BLKGETSIZE if BLKGETSIZE64 fails - Sync user/kernel headers and shared code xfsprogs-2.0.0 (26 February 2002) - Major release to coincide with switch to new extended attributes system call interfaces - bumped version of libhandle, added new symbols to use the reworked extended attributes handle ioctl interface - xfs_repair in no-modify mode opens the filesystem device read-only now (fix from Chris Pascoe) - sync up with recent (minor) changes to shared kernel code - switch to using the BLKGETSIZE64 ioctl in libxfs, instead of the (previously busted) BLKGETSIZE ioctl xfsprogs-1.3.19 (15 February 2002) - fix xfs_repair option parsing for external logs - add xfs_repair option parsing for realtime device - fix xfs_repair version (-V) option - should not require an argument - add -V option to usage string - document verbose (-v) and -r options in manpage xfsprogs-1.3.18 (17 January 2002) - fix mkfs.xfs buglet in overwriting signatures when run on a regular file xfsprogs-1.3.17 (14 January 2002) - mkfs.xfs overwrites pre-existing filesystem, swap, or md driver signatures. - xfs_repair fix to prevent double insertion into the uncertain_inode AVL trees ("avl_insert: duplicate range") - xfs_repair fix if the log is corrupted and we can't find the head, don't exit - just proceed on with zeroing it - use snprintf instead of sprintf throughout xfsprogs-1.3.16 (17 December 2001) - added text dump type to xfs_db (mkp) - removed use of a temporary file in xfs_db when processing commands on the command line - allows xfs_check to be run on read-only root filesystems xfsprogs-1.3.15 (12 December 2001) - reenable the use of the BLKBSZSET ioctl, it's baaack - sync recent XFS kernel source changes back into libxfs xfsprogs-1.3.14 (05 December 2001) - fix minor debian package version numbering issue - add documentation for xfs_db(8) label/uuid commands - automatic inode sizing code in mkfs.xfs has been removed (restricting inodes to 32 bits) - Steve's recent kernel changes mean this is no longer an issue - fix bug in mkfs.xfs size cross-check for realtime device xfsprogs-1.3.13 (25 October 2001) - fix bug in mkfs for 1Tbyte + filesystems - sync with recent kernel changes - this does not affect userspace (libxfs), all affected code is removed by cpp. xfsprogs-1.3.12 (17 October 2001) - implement the -f (file) option to xfs_logprint - rework the xlog code into libxlog for code sharing - xfs_repair now detects a dirty log and, without -L, will no longer blindly zero it (which prevents any recovery) xfsprogs-1.3.11 (17 October 2001) - tidy up some (benign) compiler warnings from libxfs - fixed 64-bit pointer alignment issues in xfs_check - fixed 64-bit pointer alignment issues in xfs_repair - verified these on IA64, also reported to fix sparc issues xfsprogs-1.3.10 (12 October 2001) - sync with XFS kernel header changes for EAs by-handle - ported xfs_imap command for dumping the inode map xfsprogs-1.3.9 (03 October 2001) - fix xfs_repair bug in handling a corrupt root directory inode with multiple "lost+found" entries - fix xfs_logprint bug in scanning for log head and tail - ensure xfs_bmap doesn't issue XFS ioctls to non-XFS files - numerous man page updates xfsprogs-1.3.8 (19 September 2001) - rewrote the LVM support used by mkfs.xfs to call external lvdisplay program to get volume geometry (mkp@mkp.net) - fix bug in LVM driver wrapper where it would not have been used at all, ever (since 1.3.0), due to idiot programmer error (*blush*) -- also thanks to mkp for the bug fix xfsprogs-1.3.7 (10 September 2001) - enable preallocation in xfs_mkfile [missed during port?] - fix xfs_db core dump when reporting freespace - allow libuuid to be linked dynamically if desired (based on a patch from Colin Walters , helps the folk working on the Debian installer for XFS) - licensing change for "libhandle" (was GPL, now LGPL-2.1) and some related header files xfsprogs-1.3.6 (31 August 2001) - make mkfs.xfs aware of geometries that might cause inode numbers to exceed 32 significant bits. - make xfs_growfs warn if new filesystem will have inode numbers that exceed 32 significant bits. - fix logprint bug in reporting extended attributes (thanks to Tang Lingbo for fixing this) - fix mkfs.xfs core dump when attemping to run on devices which are too small to hold a valid XFS filesystem xfsprogs-1.3.5 (13 August 2001) - fix bug in xfs_db bit handling on big endian platforms - fix mkfs bug related to too-small final allocation group - fix signedness bug in DMAPI ioctl structure definition xfsprogs-1.3.4 (04 August 2001) - fix endian bug in xfs_db "frag" command - small configure script changes to allow cross compilation - several man pages updated to document external log usage - install another shared library symlink for ld to find - switched on -fno-strict-aliasing for library object builds - fix several minor compiler warnings when building on IA64 xfsprogs-1.3.3 (27 July 2001) - fixes for (hopefully) the last few nits in libtool usage xfsprogs-1.3.2 (23 July 2001) - install static libs and libtool archives into /usr/lib - shared libraries are unchanged, however xfsprogs-1.3.1 (15 July 2001) - updated xfs_types.h file from the kernel changes needed for an xfsdump fix. - tidy up various aspects of the libtool rework - XVM stripe unit/width extraction - fix an endian bug in xfs_db "write" command - fix a build problem with liblvm.a installed - fix bug in xfs_growfs mount option parsing with external log - BLKSZSET ioctl now conditional via the Makefile (off by default) - rework some of the Debian packaging rules - fix sign of BLKGETSIZE ioctl argument in libxfs - updated xfs_fs.h with DMAPI setdm details for dump/restore xfsprogs-1.3.0 (11 July 2001) - reworked Makefiles to use libtool - new libdisk to allow sharing of generic mount/disk code and - also abstracts individual driver support (LVM, MD, XVM..) - partition table detection so mkfs.xfs doesn't blindly overwrite - small xfs_repair bug fix from Steve xfsprogs-1.2.8 (02 July 2001) - fixed a bug in libxfs /etc/mtab read-only mount detection - first try procfs, fall back to /etc/mtab, for read-only mounts - sync with recent mount code changes for reiserfs and ext3 probes - fix logprint build problem under gcc 3.0 xfsprogs-1.2.7 (22 May 2001) - new xfs_freeze(8) command - volume manager snapshot helper xfsprogs-1.2.6 (15 May 2001) - merge support for -d agsize=/su=/sw= (AG, stripe unit/width size) - merge support for dynamic configuration of default log size - document these and fix a couple of man page typos too xfsprogs-1.2.5 (07 May 2001) - fix missing Makefile include entries for LVM headers - configure script default man path now /usr/share/man - add experimental xfs_rtcp (realtime copy) command - powerpc build failure fixups - thanks to Robert Ramiega - cleanup arch-specific code, esp. the byteswab routines - as a result, move to -O1 as default for extern inlines xfsprogs-1.2.4 (01 May 2001) - added -L option to mkfs.xfs (filesystem label) xfsprogs-1.2.3 (27 April 2001) - add dquot and quotaoff log item support into xfs_logprint - fix logprint core dump reporting AGI in "continue"'d transactions xfsprogs-1.2.2 (09 April 2001) - fix problem in xfs_db (check) group quota logic - fixes to warnings from recent gcc and/or 64-bit builds xfsprogs-1.2.1 (04 April 2001) - sync up with recent changes to XFS kernel headers xfsprogs-1.2.0 (01 April 2001) - support for group quota added - some headers updated, in particular - now in late stages of beta xfsprogs-1.1.9 (26 March 2001) - added automagic stripe unit/stripe width extraction for MD devices xfsprogs-1.1.8 (23 March 2001) - mkfs heuristics to make a qualified guess of internal logsize xfsprogs-1.1.7 (20 March 2001) - upgraded LVM to 0.9beta6 - minor rpm spec file changes xfsprogs-1.1.6 (20 March 2001) - fix sparc build failure - fcntl.h missing O_DIRECT - added README.quota describing use of quota with XFS xfsprogs-1.1.5 (12 March 2001) - upgraded LVM support to 0.9beta2 (IOP 10) xfsprogs-1.1.4 (10 March 2001) - kernel now supports O_DIRECT - re-enable its use in xfs_mkfile - BLKSETSIZE ioctl replaced by BLKBSZSET ioctl in libxfs - libxfs_init extended so only mkfs and xfs_repair use BLKBSZSET - NOTE: this version requires an XFS kernel from March 9 or later xfsprogs-1.1.3 (02 March 2001) - minor Makefile-related cleanups xfsprogs-1.1.2 (10 February 2001) - added libhandle routines to simplify dump/restore EA support xfsprogs-1.1.1 (30 January 2001) - minor rpm and deb packaging work xfsprogs-1.1.0 (15 January 2001) - rework xfs-cmds package into base, devel and dump packages - completed Debian packaging - late beta code xfs-cmds-1.0.7 (02 January 2001) - added mkfs support for extracting LVM stripe unit/width - libattr (*experimental* extended attributes interface) added - removed xfs_fstab.5 man page (merged into mount.8) - install xfs_repair into /sbin, not /usr/sbin xfs-cmds-1.0.6 (04 October 2000) - reworked external log format to be IRIX compatible - mkfs, repair, db, logprint now work with new format - xfs_admin added for setting filesystem label xfs-cmds-1.0.5 (18 September 2000) - minor bug fixes - first beta release xfs-cmds-1.0.4 (18 August 2000) - minor bug fixes - xfs_growfs added - xfs_info added - late alpha code xfs-cmds-1.0.3 (16 August 2000) - numerous bug fixes - xfsdump and xfsrestore added - xfsstats added - fsck.xfs (symlink to /bin/true) added - demise of sim library complete, mkfs and repair reworked - no longer need to have an XFS kernel handy for building xfs-cmds - xfs_copy compiles on Linux - dump/restore README added - late alpha code xfs-cmds-1.0.2 (27 July 2000) - numerous bug fixes - xfs_attr (extended attributes) command added - fsr_xfs added (ported by jones@tacc.utexas.edu) - LVM+XFS README added - early alpha code xfs-cmds-1.0.1 (5 July 2000) - numerous bug fixes - reworked build environment - begun work on user/kernel separation - early alpha code xfs-cmds-1.0.0 (16 June 2000) - initial release for USENIX CDs - early alpha code xfsprogs-4.9.0+nmu1ubuntu2/doc/COPYING0000644000000000000000000017311613063067170014302 0ustar The library named "libhandle" and some specific header files (including ) are licensed under the GNU Lesser General Public License. All other components are licensed under the GNU General Public License. ---------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ---------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ---------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ---------------------------------------------------------------------- xfsprogs-4.9.0+nmu1ubuntu2/doc/CREDITS0000644000000000000000000000376013063067170014264 0ustar This is a credits-file of people that have contributed to the Linux/XFS project. It is sorted by name and formatted to allow easy grepping and beautification by scripts (i.e. it follows the same format Linus has used in the kernel). The fields are: name (N), email (E), web-address (W), PGP key ID and fingerprint (P), description (D), and snail-mail address (S). ---------- N: Jens Axboe E: axboe@suse.de D: Block/elevator/kiobuf hacking, IDE kiobuf support S: Peter Bangs Vej 258, 2TH S: 2500 Valby S: Denmark N: Ethan Benson E: erbenson@alaska.net D: Additional inode flags (immutable, append-only, etc) S: P.O. Box 770525 S: Eagle River, AK 99577 S: Alaska N: Nicolas Boullis E: nboullis@debian.org D: fix XFS recovery on 64-bit big-endian architectures N: Danny Cox E: danscox@mindspring.com D: ACL port to Linux N: Thomas Graichen E: tgr@spoiled.org D: Original XFS FAQ maintainer D: PowerPC and Alpha porting S: Berlin, Germany N: Juergen Hasch E: hasch@t-online.de D: libacl fixes S: Meisenstr. 23, 73066 Uhingen, Germany N: Bill Jones E: jones@hpc.utexas.edu D: fsr port to Linux S: Austin, Texas, USA N: Jan Kara E: jack@atrey.karlin.mff.cuni.cz E: jack@suse.cz D: Quota 3.01 user tools, allowing different forms of quota to coexist D: Merging XFS support into quota user tools W: http://atrey.karlin.mff.cuni.cz/~jack/ S: Krosenska' 543 S: 181 00 Praha 8 S: Czech Republic N: Andi Kleen E: ak@muc.de D: Most recently, fine-tuning default mkfs/mount logsize/logbufs values S: Schwalbenstr. 96 S: 85551 Ottobrunn S: Germany N: Seth Mos E: seth@arosa.nl D: XFS FAQ ( http://oss.sgi.com/projects/xfs/faq.html ) maintainer W: http://iserv.nl/ S: Den Helder, The Netherlands N: Bart Samwel E: bart@samwel.tk W: http://www.xs4all.nl/~bsamwel/laptop_mode/ D: Laptop mode for XFS N: Robert Stickel E: previously: rstickel@connex.com D: libacl port to Linux N: John Trostel E: john.trostel@gtri.gatech.edu D: libacl extensions for Linux S: GTRI/EOEML, Georgia Institute of Technology, Atlanta, GA 30332, USA xfsprogs-4.9.0+nmu1ubuntu2/doc/INSTALL0000644000000000000000000001122013063067170014263 0ustar This document describes how to configure and build the open source XFS commands and utilites ("xfsprogs") from source, and how to install and run them. See the README file in the top level directory for details about how to contribute to the XFS project. Linux Instructions ================== 0. If you have the binary rpm, simply install it and skip to step 2 (below). The rpm command to do this is: # rpm -Uvh xfsprogs-*.rpm [and optionally, for the development libraries and headers] # rpm -Uvh xfsprogs-devel-*.rpm The Debian command to do this is: # apt-get install xfsprogs [and optionally, for the development libraries and headers] # apt-get install xfslibs-dev 1. Configure, build and install the package The xfsprogs package uses autoconf/configure and expects a GNU build environment (your platform must at least have both autoconf and gmake). You will also need to have installed either the e2fsprogs-devel package (on an RPM based system) or the uuid-dev package (on a Debian system) as some of the commands make use of the UUID library provided by these. To build the package and install it manually, use the following steps: # make # su root # make install [and optionally, for the development libraries and headers] # make install-dev Note that there are so many "install" variants out there that we wrote our own script (see "install-sh" in the top level directory). If you wish to turn off debugging asserts in the command build and turn on the optimizer then set the shell environment variables: OPTIMIZER=-O1 DEBUG=-DNDEBUG before running make or Makepkgs. Mac OS X Instructions ===================== 0. Note: since there is no XFS implementation on Mac OS X, you are severely limited in what you can do. mkfs.xfs(8), xfs_db(8) and xfs_repair(8) are the only functional tools on this platform, as they do not interact with the XFS kernel code at all. Still, it can be useful to have access to these utilities from Mac OS X in a dual boot configuration, for example. However, keep on mind that mkfs.xfs on Mac OS X has disabled device access, although you can create a filesystem in a file. Also note that existing filesystem detection is disabled. 1. Configure, build and install the package The xfsprogs package uses autoconf/configure and expects a GNU build environment (your platform must at least have both autoconf, make, and glibtool). You will also need to have built and installed the UUID library which is provided by the e2fsprogs source package. (Or use Homebrew, Macports or any other 3rd party package manager.) Building libuuid: [download; unzip/untar e2fsprogs; cd e2fsprogs] $ ./configure --prefix=/usr --mandir=/usr/share/man $ make lib/ext2fs/ext2_types.h $ cd lib/uuid $ make $ su root # make install [verify that you now have a /usr/lib/libuuid.a] Building xfsprogs: [firstly set these environment variables to these values] TAR=/usr/bin/gnutar LIBTOOL=/usr/bin/glibtool INSTALL_GROUP=wheel LOCAL_CONFIGURE_OPTIONS="\ --enable-gettext=no\ --enable-blkid=no\ --enable-librt=no\ " $ make $ su root # make install [and optionally, for the development libraries and headers] # make install-dev IRIX Instructions ================= 0. Note: building this package on IRIX is mainly useful for the XFS developers who want to run purify on some of the tools. Most tools are not functional due to incomplete support for the syssgi and fcntl interfaces that XFS provides and which these tools make extensive use of. 1. Configure, build and install the package The xfsprogs package uses autoconf/configure and expects a GNU build environment which can be obtained by installing a number of freeware packages (gcc, autoconf, libtool, gmake). Even though IRIX provides a set of UUID functions via libc, you still need to have built and installed the UUID library which is provided by the e2fsprogs source package. This is because some difficult to resolve differences exist between the UUID functions and data types, which makes co-existence of these more trouble than its worth at the moment. Follow the instructions above for building and installing libuuid. Building xfsprogs: [firstly set these environment variables to these values] INSTALL_GROUP=sys CC=/usr/freeware/bin/gcc TAR=/usr/freeware/bin/tar MAKE=/usr/freeware/bin/gmake LIBTOOL=/usr/freeware/bin/libtool MSGFMT=/usr/freeware/bin/msgfmt MSGMERGE=/usr/freeware/bin/msgmerge XGETTEXT=/usr/freeware/bin/xgettext $ make $ su root # make install [and optionally, for the development libraries and headers] # make install-dev xfsprogs-4.9.0+nmu1ubuntu2/doc/Makefile0000644000000000000000000000110513063067170014673 0ustar # # Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LSRCFILES = INSTALL CHANGES COPYING CREDITS sparse.txt LDIRT = *.gz default: CHANGES.gz include $(BUILDRULES) CHANGES.gz: @echo " [ZIP] $@" $(Q)$(ZIP) --best -c < CHANGES > $@ install: default $(INSTALL) -m 755 -d $(PKG_DOC_DIR) $(INSTALL) -m 644 CHANGES.gz CREDITS $(PKG_DOC_DIR) ifeq ($(PKG_DISTRIBUTION), debian) $(INSTALL) -S CHANGES.gz $(PKG_DOC_DIR)/changelog.gz else $(INSTALL) -m 644 COPYING $(PKG_DOC_DIR) endif install-dev: xfsprogs-4.9.0+nmu1ubuntu2/doc/sparse.txt0000644000000000000000000000210313063067170015270 0ustar This document describes how to use the sparse source code checking tool to check the source code of the open source XFS commands and utilites ("xfsprogs"). First you need to install sparse, either from your distribution or from source as provided at http://www.kernel.org/pub/software/devel/sparse/. To simply build the xfsprogs source code while checking the source using sparse just set the compiler to cgcc, which is a wrapper that calls both sparse and gcc using: CC=cgcc ./configure Now that default warnings from sparse are a little bit verbose checking for various not that important things and also complaining about the glibc system headers. It does however not check for bitwise annotation which are very important for xfsprogs to verify the endianess handling of the on-disk structures is correct. To get a more reasonable set of warnings build xfsprogs using: LCFLAGS="-Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl" make You are of course free to experiment with the warnings flags documented in the sparse manpage to check xfsprogs for other issues. xfsprogs-4.9.0+nmu1ubuntu2/estimate/0000755000000000000000000000000013063067174014310 5ustar xfsprogs-4.9.0+nmu1ubuntu2/estimate/Makefile0000644000000000000000000000055113063067172015747 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_estimate CFILES = xfs_estimate.c default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/estimate/xfs_estimate.c0000644000000000000000000001473713063067172017161 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Estimate space of an XFS filesystem * * XXX: assumes dirv1 format. */ #include "libxfs.h" #include #include unsigned long long cvtnum(char *s) { unsigned long long i; char *sp; i = strtoll(s, &sp, 0); if (i == 0 && sp == s) return 0LL; if (*sp == '\0') return i; if (*sp =='k' && sp[1] == '\0') return 1024LL * i; if (*sp =='m' && sp[1] == '\0') return 1024LL * 1024LL * i; if (*sp =='g' && sp[1] == '\0') return 1024LL * 1024LL * 1024LL * i; return 0LL; } int ffn(const char *, const struct stat *, int, struct FTW *); #define BLOCKSIZE 4096 #define INODESIZE 256 #define PERDIRENTRY \ (sizeof(xfs_dir2_leaf_entry_t) + sizeof(xfs_dir2_data_entry_t)) #define LOGSIZE 1000 #define FBLOCKS(n) ((n)/blocksize) #define RFBYTES(n) ((n) - (FBLOCKS(n) * blocksize)) unsigned long long dirsize=0; /* bytes */ unsigned long long logsize=LOGSIZE*BLOCKSIZE; /* bytes */ unsigned long long fullblocks=0; /* FS blocks */ unsigned long long isize=0; /* inodes bytes */ unsigned long long blocksize=BLOCKSIZE; unsigned long long nslinks=0; /* number of symbolic links */ unsigned long long nfiles=0; /* number of regular files */ unsigned long long ndirs=0; /* number of directories */ unsigned long long nspecial=0; /* number of special files */ unsigned long long verbose=0; /* verbose mode TRUE/FALSE */ int __debug = 0; int ilog = 0; int elog = 0; void usage(char *progname) { fprintf(stderr, _("Usage: %s [opts] directory [directory ...]\n" "\t-b blocksize (fundamental filesystem blocksize)\n" "\t-i logsize (internal log size)\n" "\t-e logsize (external log size)\n" "\t-v prints more verbose messages\n" "\t-V prints version and exits\n" "\t-h prints this usage message\n\n" "Note:\tblocksize may have 'k' appended to indicate x1024\n" "\tlogsize may also have 'm' appended to indicate (1024 x 1024)\n"), basename(progname)); exit(1); } int main(int argc, char **argv) { unsigned long long est; extern int optind; extern char *optarg; char dname[40]; int c; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((c = getopt (argc, argv, "b:hdve:i:V")) != EOF) { switch (c) { case 'b': blocksize=cvtnum(optarg); if (blocksize <= 0LL) { fprintf(stderr, _("blocksize %llu too small\n"), blocksize); usage(argv[0]); } else if (blocksize > 64LL * 1024LL) { fprintf(stderr, _("blocksize %llu too large\n"), blocksize); usage(argv[0]); } break; case 'i': if (elog) { fprintf(stderr, _("already have external log " "noted, can't have both\n")); usage(argv[0]); } logsize=cvtnum(optarg); ilog++; break; case 'e': if (ilog) { fprintf(stderr, _("already have internal log " "noted, can't have both\n")); usage(argv[0]); } logsize=cvtnum(optarg); elog++; break; case 'v': verbose = 1; break; case 'd': __debug++; break; case 'V': printf(_("%s version %s\n"), basename(argv[0]), VERSION); exit(0); default: case 'h': usage(argv[0]); } } if (optind == argc) usage(argv[0]); if (!elog && !ilog) { ilog=1; logsize=LOGSIZE * blocksize; } if (verbose) printf(_("directory bsize blocks megabytes logsize\n")); for ( ; optind < argc; optind++) { dirsize=0LL; /* bytes */ fullblocks=0LL; /* FS blocks */ isize=0LL; /* inodes bytes */ nslinks=0LL; /* number of symbolic links */ nfiles=0LL; /* number of regular files */ ndirs=0LL; /* number of directories */ nspecial=0LL; /* number of special files */ nftw(argv[optind], ffn, 40, FTW_PHYS | FTW_MOUNT); if (__debug) { printf(_("dirsize=%llu\n"), dirsize); printf(_("fullblocks=%llu\n"), fullblocks); printf(_("isize=%llu\n"), isize); printf(_("%llu regular files\n"), nfiles); printf(_("%llu symbolic links\n"), nslinks); printf(_("%llu directories\n"), ndirs); printf(_("%llu special files\n"), nspecial); } est = FBLOCKS(isize) + 8 /* blocks for inodes */ + FBLOCKS(dirsize) + 1 /* blocks for directories */ + fullblocks /* blocks for file contents */ + (8 * 16) /* fudge for overhead blks (per ag) */ + FBLOCKS(isize / INODESIZE); /* 1 byte/inode for map */ if (ilog) est += (logsize / blocksize); if (!verbose) { printf(_("%s will take about %.1f megabytes\n"), argv[optind], (double)est*(double)blocksize/(1024.0*1024.0)); } else { /* avoid running over 39 characters in field */ strncpy(dname, argv[optind], 40); dname[39] = '\0'; printf(_("%-39s %5llu %8llu %10.1fMB %10llu\n"), dname, blocksize, est, (double)est*(double)blocksize/(1024.0*1024.0), logsize); } if (!verbose && elog) { printf(_("\twith the external log using %llu blocks "), logsize/blocksize); printf(_("or about %.1f megabytes\n"), (double)logsize/(1024.0*1024.0)); } } return 0; } int ffn(const char *path, const struct stat *stb, int flags, struct FTW *f) { /* cases are in most-encountered to least-encountered order */ dirsize+=PERDIRENTRY+strlen(path); isize+=INODESIZE; switch (S_IFMT & stb->st_mode) { case S_IFREG: /* regular files */ fullblocks+=FBLOCKS(stb->st_blocks * 512 + blocksize-1); if (stb->st_blocks * 512 < stb->st_size) fullblocks++; /* add one bmap block here */ nfiles++; break; case S_IFLNK: /* symbolic links */ if (stb->st_size >= (INODESIZE - (sizeof(xfs_dinode_t)+4))) fullblocks+=FBLOCKS(stb->st_size + blocksize-1); nslinks++; break; case S_IFDIR: /* directories */ dirsize+=blocksize; /* fudge upwards */ if (stb->st_size >= blocksize) dirsize+=blocksize; ndirs++; break; case S_IFIFO: /* named pipes */ case S_IFCHR: /* Character Special device */ case S_IFBLK: /* Block Special device */ case S_IFSOCK: /* socket */ nspecial++; break; } return 0; } xfsprogs-4.9.0+nmu1ubuntu2/fs/0000755000000000000000000000000013063067174013105 5ustar xfsprogs-4.9.0+nmu1ubuntu2/fs/xfs/0000755000000000000000000000000013063067174013705 5ustar xfsprogs-4.9.0+nmu1ubuntu2/fs/xfs/xfs_rmap_item.c0000644000000000000000000000000013033541503016662 0ustar xfsprogs-4.9.0+nmu1ubuntu2/fs/xfs/xfs_rmap_item.h0000644000000000000000000000000013033541503016667 0ustar xfsprogs-4.9.0+nmu1ubuntu2/fsck/0000755000000000000000000000000013063067174013423 5ustar xfsprogs-4.9.0+nmu1ubuntu2/fsck/Makefile0000644000000000000000000000050513063067170015057 0ustar # # Copyright (c) 2006 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LSRCFILES = xfs_fsck.sh default: $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(INSTALL) -m 755 xfs_fsck.sh $(PKG_ROOT_SBIN_DIR)/fsck.xfs install-dev: xfsprogs-4.9.0+nmu1ubuntu2/fsck/xfs_fsck.sh0000755000000000000000000000066113063067170015567 0ustar #!/bin/sh -f # # Copyright (c) 2006 Silicon Graphics, Inc. All Rights Reserved. # AUTO=false while getopts ":aApy" c do case $c in a|A|p|y) AUTO=true;; esac done eval DEV=\${$#} if [ ! -e $DEV ]; then echo "$0: $DEV does not exist" exit 8 fi if $AUTO; then echo "$0: XFS file system." else echo "If you wish to check the consistency of an XFS filesystem or" echo "repair a damaged filesystem, see xfs_repair(8)." fi exit 0 xfsprogs-4.9.0+nmu1ubuntu2/fsr/0000755000000000000000000000000013136024635013263 5ustar xfsprogs-4.9.0+nmu1ubuntu2/fsr/Makefile0000644000000000000000000000077013063067172014731 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_fsr CFILES = xfs_fsr.c LLDLIBS = $(LIBHANDLE) ifeq ($(HAVE_GETMNTENT),yes) LCFLAGS += -DHAVE_GETMNTENT endif ifeq ($(HAVE_GETMNTINFO),yes) LCFLAGS += -DHAVE_GETMNTINFO endif default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/fsr/xfs_fsr.c0000644000000000000000000012475013136024635015112 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "xfs.h" #include "xfs_types.h" #include "jdm.h" #include "xfs_bmap_btree.h" #include "xfs_attr_sf.h" #include #include #include #include #include #include #include #include #include #define _PATH_FSRLAST "/var/tmp/.fsrlast_xfs" #define _PATH_PROC_MOUNTS "/proc/mounts" char *progname; int vflag; int gflag; static int Mflag; /* static int nflag; */ int dflag = 0; /* static int sflag; */ int argv_blksz_dio; extern int max_ext_size; static int npasses = 10; static int startpass = 0; struct getbmap *outmap = NULL; int outmap_size = 0; int RealUid; int tmp_agi; static __int64_t minimumfree = 2048; #define MNTTYPE_XFS "xfs" #define SMBUFSZ 1024 #define ROOT 0 #define NULLFD -1 #define GRABSZ 64 #define TARGETRANGE 10 #define V_NONE 0 #define V_OVERVIEW 1 #define V_ALL 2 #define BUFFER_SIZE (1<<16) #define BUFFER_MAX (1<<24) static time_t howlong = 7200; /* default seconds of reorganizing */ static char *leftofffile = _PATH_FSRLAST; /* where we left off last */ static time_t endtime; static time_t starttime; static xfs_ino_t leftoffino = 0; static int pagesize; void usage(int ret); static int fsrfile(char *fname, xfs_ino_t ino); static int fsrfile_common( char *fname, char *tname, char *mnt, int fd, xfs_bstat_t *statp); static int packfile(char *fname, char *tname, int fd, xfs_bstat_t *statp, struct fsxattr *fsxp); static void fsrdir(char *dirname); static int fsrfs(char *mntdir, xfs_ino_t ino, int targetrange); static void initallfs(char *mtab); static void fsrallfs(char *mtab, int howlong, char *leftofffile); static void fsrall_cleanup(int timeout); static int getnextents(int); int xfsrtextsize(int fd); int xfs_getrt(int fd, struct statvfs *sfbp); char * gettmpname(char *fname); char * getparent(char *fname); int fsrprintf(const char *fmt, ...); int read_fd_bmap(int, xfs_bstat_t *, int *); int cmp(const void *, const void *); static void tmp_init(char *mnt); static char * tmp_next(char *mnt); static void tmp_close(char *mnt); int xfs_getgeom(int , xfs_fsop_geom_v1_t * ); xfs_fsop_geom_v1_t fsgeom; /* geometry of active mounted system */ #define NMOUNT 64 static int numfs; typedef struct fsdesc { char *dev; char *mnt; int npass; } fsdesc_t; fsdesc_t *fs, *fsbase, *fsend; int fsbufsize = 10; /* A starting value */ int nfrags = 0; /* Debug option: Coerse into specific number * of extents */ int openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT; int xfs_fsgeometry(int fd, xfs_fsop_geom_v1_t *geom) { return ioctl(fd, XFS_IOC_FSGEOMETRY_V1, geom); } int xfs_bulkstat_single(int fd, xfs_ino_t *lastip, xfs_bstat_t *ubuffer) { xfs_fsop_bulkreq_t bulkreq; bulkreq.lastip = (__u64 *)lastip; bulkreq.icount = 1; bulkreq.ubuffer = ubuffer; bulkreq.ocount = NULL; return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq); } int xfs_bulkstat(int fd, xfs_ino_t *lastip, int icount, xfs_bstat_t *ubuffer, __s32 *ocount) { xfs_fsop_bulkreq_t bulkreq; bulkreq.lastip = (__u64 *)lastip; bulkreq.icount = icount; bulkreq.ubuffer = ubuffer; bulkreq.ocount = ocount; return ioctl(fd, XFS_IOC_FSBULKSTAT, &bulkreq); } int xfs_swapext(int fd, xfs_swapext_t *sx) { return ioctl(fd, XFS_IOC_SWAPEXT, sx); } int xfs_fscounts(int fd, xfs_fsop_counts_t *counts) { return ioctl(fd, XFS_IOC_FSCOUNTS, counts); } void aborter(int unused) { fsrall_cleanup(1); exit(1); } /* * Check if the argument is either the device name or mountpoint of an XFS * filesystem. Note that we do not care about bind mounted regular files * here - the code that handles defragmentation of invidual files takes care * of that. */ static char * find_mountpoint_check(struct stat *sb, struct mntent *t) { struct stat ms; if (S_ISDIR(sb->st_mode)) { /* mount point */ if (stat(t->mnt_dir, &ms) < 0) return NULL; if (sb->st_ino != ms.st_ino) return NULL; if (sb->st_dev != ms.st_dev) return NULL; if (strcmp(t->mnt_type, MNTTYPE_XFS) != 0) return NULL; } else { /* device */ if (stat(t->mnt_fsname, &ms) < 0) return NULL; if (sb->st_rdev != ms.st_rdev) return NULL; if (strcmp(t->mnt_type, MNTTYPE_XFS) != 0) return NULL; /* * Make sure the mountpoint given by mtab is accessible * before using it. */ if (stat(t->mnt_dir, &ms) < 0) return NULL; } return t->mnt_dir; } static char * find_mountpoint(char *mtab, char *argname, struct stat *sb) { struct mntent_cursor cursor; struct mntent *t = NULL; char *mntp = NULL; if (platform_mntent_open(&cursor, mtab) != 0){ fprintf(stderr, "Error: can't get mntent entries.\n"); exit(1); } while ((t = platform_mntent_next(&cursor)) != NULL) { mntp = find_mountpoint_check(sb, t); if (mntp == NULL) continue; break; } platform_mntent_close(&cursor); return mntp; } int main(int argc, char **argv) { struct stat sb; char *argname; int c; char *mntp; char *mtab = NULL; setlinebuf(stdout); progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); gflag = ! isatty(0); while ((c = getopt(argc, argv, "C:p:e:MgsdnvTt:f:m:b:N:FV")) != -1) { switch (c) { case 'M': Mflag = 1; break; case 'g': gflag = 1; break; case 'n': /* nflag = 1; */ break; case 'v': ++vflag; break; case 'd': dflag = 1; break; case 's': /* frag stats only */ /* sflag = 1; */ fprintf(stderr, _("%s: Stats not yet supported for XFS\n"), progname); usage(1); break; case 't': howlong = atoi(optarg); break; case 'f': leftofffile = optarg; break; case 'm': mtab = optarg; break; case 'b': argv_blksz_dio = atoi(optarg); break; case 'p': npasses = atoi(optarg); break; case 'C': /* Testing opt: coerses frag count in result */ if (getenv("FSRXFSTEST") != NULL) { nfrags = atoi(optarg); openopts |= O_SYNC; } break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); default: usage(1); } } /* * If the user did not specify an explicit mount table, try to use * /proc/mounts if it is available, else /etc/mtab. We prefer * /proc/mounts because it is kernel controlled, while /etc/mtab * may contain garbage that userspace tools like pam_mounts wrote * into it. */ if (!mtab) { if (access(_PATH_PROC_MOUNTS, R_OK) == 0) mtab = _PATH_PROC_MOUNTS; else mtab = _PATH_MOUNTED; } if (vflag) setbuf(stdout, NULL); starttime = time(0); /* Save the caller's real uid */ RealUid = getuid(); pagesize = getpagesize(); if (optind < argc) { for (; optind < argc; optind++) { argname = argv[optind]; if (lstat(argname, &sb) < 0) { fprintf(stderr, _("%s: could not stat: %s: %s\n"), progname, argname, strerror(errno)); continue; } if (S_ISLNK(sb.st_mode)) { struct stat sb2; if (stat(argname, &sb2) == 0 && (S_ISBLK(sb2.st_mode) || S_ISCHR(sb2.st_mode))) sb = sb2; } mntp = find_mountpoint(mtab, argname, &sb); if (mntp != NULL) { fsrfs(mntp, 0, 100); } else if (S_ISCHR(sb.st_mode)) { fprintf(stderr, _( "%s: char special not supported: %s\n"), progname, argname); exit(1); } else if (S_ISDIR(sb.st_mode) || S_ISREG(sb.st_mode)) { if (!platform_test_xfs_path(argname)) { fprintf(stderr, _( "%s: cannot defragment: %s: Not XFS\n"), progname, argname); continue; } if (S_ISDIR(sb.st_mode)) fsrdir(argname); else fsrfile(argname, sb.st_ino); } else { printf( _("%s: not fsys dev, dir, or reg file, ignoring\n"), argname); } } } else { initallfs(mtab); fsrallfs(mtab, howlong, leftofffile); } return 0; } void usage(int ret) { fprintf(stderr, _( "Usage: %s [-d] [-v] [-g] [-t time] [-p passes] [-f leftf] [-m mtab]\n" " %s [-d] [-v] [-g] xfsdev | dir | file ...\n" " %s -V\n\n" "Options:\n" " -g Print to syslog (default if stdout not a tty).\n" " -t time How long to run in seconds.\n" " -p passes Number of passes before terminating global re-org.\n" " -f leftoff Use this instead of %s.\n" " -m mtab Use something other than /etc/mtab.\n" " -d Debug, print even more.\n" " -v Verbose, more -v's more verbose.\n" " -V Print version number and exit.\n" ), progname, progname, progname, _PATH_FSRLAST); exit(ret); } /* * initallfs -- read the mount table and set up an internal form */ static void initallfs(char *mtab) { struct mntent_cursor cursor; struct mntent *mnt= NULL; int mi; char *cp; struct stat sb; /* malloc a number of descriptors, increased later if needed */ if (!(fsbase = (fsdesc_t *)malloc(fsbufsize * sizeof(fsdesc_t)))) { fsrprintf(_("out of memory: %s\n"), strerror(errno)); exit(1); } fsend = (fsbase + fsbufsize - 1); /* find all rw xfs file systems */ mi = 0; fs = fsbase; if (platform_mntent_open(&cursor, mtab) != 0){ fprintf(stderr, "Error: can't get mntent entries.\n"); exit(1); } while ((mnt = platform_mntent_next(&cursor)) != NULL) { int rw = 0; if (strcmp(mnt->mnt_type, MNTTYPE_XFS ) != 0 || stat(mnt->mnt_fsname, &sb) == -1 || !S_ISBLK(sb.st_mode)) continue; cp = strtok(mnt->mnt_opts,","); do { if (strcmp("rw", cp) == 0) rw++; } while ((cp = strtok(NULL, ",")) != NULL); if (rw == 0) { if (dflag) fsrprintf(_("Skipping %s: not mounted rw\n"), mnt->mnt_fsname); continue; } if (mi == fsbufsize) { fsbufsize += NMOUNT; if ((fsbase = (fsdesc_t *)realloc((char *)fsbase, fsbufsize * sizeof(fsdesc_t))) == NULL) { fsrprintf(_("out of memory: %s\n"), strerror(errno)); exit(1); } if (!fsbase) { fsrprintf(_("out of memory on realloc: %s\n"), strerror(errno)); exit(1); } fs = (fsbase + mi); /* Needed ? */ } fs->dev = strdup(mnt->mnt_fsname); fs->mnt = strdup(mnt->mnt_dir); if (fs->dev == NULL) { fsrprintf(_("strdup(%s) failed\n"), mnt->mnt_fsname); exit(1); } if (fs->mnt == NULL) { fsrprintf(_("strdup(%s) failed\n"), mnt->mnt_dir); exit(1); } mi++; fs++; } platform_mntent_close(&cursor); numfs = mi; fsend = (fsbase + numfs); if (numfs == 0) { fsrprintf(_("no rw xfs file systems in mtab: %s\n"), mtab); exit(0); } if (vflag || dflag) { fsrprintf(_("Found %d mounted, writable, XFS filesystems\n"), numfs); if (dflag) for (fs = fsbase; fs < fsend; fs++) fsrprintf("\t%-30.30s%-30.30s\n", fs->dev, fs->mnt); } } static void fsrallfs(char *mtab, int howlong, char *leftofffile) { int fd; int error; int found = 0; char *fsname; char buf[SMBUFSZ]; int mdonly = Mflag; char *ptr; xfs_ino_t startino = 0; fsdesc_t *fsp; struct stat sb, sb2; fsrprintf("xfs_fsr -m %s -t %d -f %s ...\n", mtab, howlong, leftofffile); endtime = starttime + howlong; fs = fsbase; /* where'd we leave off last time? */ if (lstat(leftofffile, &sb) == 0) { if ( (fd = open(leftofffile, O_RDONLY)) == -1 ) { fsrprintf(_("%s: open failed\n"), leftofffile); } else if ( fstat(fd, &sb2) == 0) { /* * Verify that lstat & fstat point to the * same regular file (no links/no quick spoofs) */ if ( (sb.st_dev != sb2.st_dev) || (sb.st_ino != sb2.st_ino) || ((sb.st_mode & S_IFMT) != S_IFREG) || ((sb2.st_mode & S_IFMT) != S_IFREG) || (sb2.st_uid != ROOT) || (sb2.st_nlink != 1) ) { fsrprintf(_("Can't use %s: mode=0%o own=%d" " nlink=%d\n"), leftofffile, sb.st_mode, sb.st_uid, sb.st_nlink); close(fd); fd = NULLFD; } } else { close(fd); fd = NULLFD; } } else { fd = NULLFD; } if (fd != NULLFD) { if (read(fd, buf, SMBUFSZ) == -1) { fs = fsbase; fsrprintf(_("could not read %s, starting with %s\n"), leftofffile, *fs->dev); } else { /* Ensure the buffer we read is null terminated */ buf[SMBUFSZ-1] = '\0'; for (fs = fsbase; fs < fsend; fs++) { fsname = fs->dev; if ((strncmp(buf,fsname,strlen(fsname)) == 0) && buf[strlen(fsname)] == ' ') { found = 1; break; } } if (! found) fs = fsbase; ptr = strchr(buf, ' '); if (ptr) { startpass = atoi(++ptr); ptr = strchr(ptr, ' '); if (ptr) { startino = strtoull(++ptr, NULL, 10); } } if (startpass < 0) startpass = 0; /* Init pass counts */ for (fsp = fsbase; fsp < fs; fsp++) { fsp->npass = startpass + 1; } for (fsp = fs; fsp <= fsend; fsp++) { fsp->npass = startpass; } } close(fd); } if (vflag) { fsrprintf(_("START: pass=%d ino=%llu %s %s\n"), fs->npass, (unsigned long long)startino, fs->dev, fs->mnt); } signal(SIGABRT, aborter); signal(SIGHUP, aborter); signal(SIGINT, aborter); signal(SIGQUIT, aborter); signal(SIGTERM, aborter); /* reorg for 'howlong' -- checked in 'fsrfs' */ while (endtime > time(0)) { pid_t pid; if (fs == fsend) fs = fsbase; if (fs->npass == npasses) { fsrprintf(_("Completed all %d passes\n"), npasses); break; } if (npasses > 1 && !fs->npass) Mflag = 1; else Mflag = mdonly; pid = fork(); switch(pid) { case -1: fsrprintf(_("couldn't fork sub process:")); exit(1); break; case 0: error = fsrfs(fs->mnt, startino, TARGETRANGE); exit (error); break; default: wait(&error); if (WIFEXITED(error) && WEXITSTATUS(error) == 1) { /* child timed out & did fsrall_cleanup */ exit(0); } break; } startino = 0; /* reset after the first time through */ fs->npass++; fs++; } fsrall_cleanup(endtime <= time(0)); } /* * fsrall_cleanup -- close files, print next starting location, etc. */ static void fsrall_cleanup(int timeout) { int fd; int ret; char buf[SMBUFSZ]; unlink(leftofffile); if (timeout) { fsrprintf(_("%s startpass %d, endpass %d, time %d seconds\n"), progname, startpass, fs->npass, time(0) - endtime + howlong); /* record where we left off */ fd = open(leftofffile, O_WRONLY|O_CREAT|O_EXCL, 0644); if (fd == -1) { fsrprintf(_("open(%s) failed: %s\n"), leftofffile, strerror(errno)); } else { ret = sprintf(buf, "%s %d %llu\n", fs->dev, fs->npass, (unsigned long long)leftoffino); if (write(fd, buf, ret) < strlen(buf)) fsrprintf(_("write(%s) failed: %s\n"), leftofffile, strerror(errno)); close(fd); } } } /* * fsrfs -- reorganize a file system */ static int fsrfs(char *mntdir, xfs_ino_t startino, int targetrange) { int fsfd, fd; int count = 0; int ret; __s32 buflenout; xfs_bstat_t buf[GRABSZ]; char fname[64]; char *tname; jdm_fshandle_t *fshandlep; xfs_ino_t lastino = startino; fsrprintf(_("%s start inode=%llu\n"), mntdir, (unsigned long long)startino); fshandlep = jdm_getfshandle( mntdir ); if ( ! fshandlep ) { fsrprintf(_("unable to get handle: %s: %s\n"), mntdir, strerror( errno )); return -1; } if ((fsfd = open(mntdir, O_RDONLY)) < 0) { fsrprintf(_("unable to open: %s: %s\n"), mntdir, strerror( errno )); free(fshandlep); return -1; } if (xfs_getgeom(fsfd, &fsgeom) < 0 ) { fsrprintf(_("Skipping %s: could not get XFS geometry\n"), mntdir); close(fsfd); free(fshandlep); return -1; } tmp_init(mntdir); while ((ret = xfs_bulkstat(fsfd, &lastino, GRABSZ, &buf[0], &buflenout)) == 0) { xfs_bstat_t *p; xfs_bstat_t *endp; if (buflenout == 0) goto out0; /* Each loop through, defrag targetrange percent of the files */ count = (buflenout * targetrange) / 100; qsort((char *)buf, buflenout, sizeof(struct xfs_bstat), cmp); for (p = buf, endp = (buf + buflenout); p < endp ; p++) { /* Do some obvious checks now */ if (((p->bs_mode & S_IFMT) != S_IFREG) || (p->bs_extents < 2)) continue; fd = jdm_open(fshandlep, p, O_RDWR|O_DIRECT); if (fd < 0) { /* This probably means the file was * removed while in progress of handling * it. Just quietly ignore this file. */ if (dflag) fsrprintf(_("could not open: " "inode %llu\n"), p->bs_ino); continue; } /* Don't know the pathname, so make up something */ sprintf(fname, "ino=%lld", (long long)p->bs_ino); /* Get a tmp file name */ tname = tmp_next(mntdir); ret = fsrfile_common(fname, tname, mntdir, fd, p); leftoffino = p->bs_ino; close(fd); if (ret == 0) { if (--count <= 0) break; } } if (endtime && endtime < time(0)) { tmp_close(mntdir); close(fsfd); fsrall_cleanup(1); exit(1); } } if (ret < 0) fsrprintf(_("%s: xfs_bulkstat: %s\n"), progname, strerror(errno)); out0: tmp_close(mntdir); close(fsfd); free(fshandlep); return 0; } /* * To compare bstat structs for qsort. */ int cmp(const void *s1, const void *s2) { return( ((xfs_bstat_t *)s2)->bs_extents - ((xfs_bstat_t *)s1)->bs_extents); } /* * reorganize by directory hierarchy. * Stay in dev (a restriction based on structure of this program -- either * call efs_{n,u}mount() around each file, something smarter or this) */ static void fsrdir(char *dirname) { fsrprintf(_("%s: Directory defragmentation not supported\n"), dirname); } /* * Sets up the defragmentation of a file based on the * filepath. It collects the bstat information, does * an open on the file and passes this all to fsrfile_common. */ static int fsrfile(char *fname, xfs_ino_t ino) { xfs_bstat_t statbuf; jdm_fshandle_t *fshandlep; int fd = -1, fsfd = -1; int error = -1; char *tname; fshandlep = jdm_getfshandle(getparent (fname) ); if (!fshandlep) { fsrprintf(_("unable to construct sys handle for %s: %s\n"), fname, strerror(errno)); goto out; } /* * Need to open something on the same filesystem as the * file. Open the parent. */ fsfd = open(getparent(fname), O_RDONLY); if (fsfd < 0) { fsrprintf(_("unable to open sys handle for %s: %s\n"), fname, strerror(errno)); goto out; } if ((xfs_bulkstat_single(fsfd, &ino, &statbuf)) < 0) { fsrprintf(_("unable to get bstat on %s: %s\n"), fname, strerror(errno)); goto out; } fd = jdm_open(fshandlep, &statbuf, O_RDWR|O_DIRECT); if (fd < 0) { fsrprintf(_("unable to open handle %s: %s\n"), fname, strerror(errno)); goto out; } /* Get the fs geometry */ if (xfs_getgeom(fsfd, &fsgeom) < 0 ) { fsrprintf(_("Unable to get geom on fs for: %s\n"), fname); goto out; } tname = gettmpname(fname); if (tname) error = fsrfile_common(fname, tname, NULL, fd, &statbuf); out: if (fsfd >= 0) close(fsfd); if (fd >= 0) close(fd); free(fshandlep); return error; } /* * This is the common defrag code for either a full fs * defragmentation or a single file. Check as much as * possible with the file, fork a process to setuid to the * target file owner's uid and defragment the file. * This is done so the new extents created in a tmp file are * reflected in the owners' quota without having to do any * special code in the kernel. When the existing extents * are removed, the quotas will be correct. It's ugly but * it saves us from doing some quota re-construction in * the extent swap. The price is that the defragmentation * will fail if the owner of the target file is already at * their quota limit. */ static int fsrfile_common( char *fname, char *tname, char *fsname, int fd, xfs_bstat_t *statp) { int error; struct statvfs vfss; struct fsxattr fsx; unsigned long bsize; if (vflag) fsrprintf("%s\n", fname); if (fsync(fd) < 0) { fsrprintf(_("sync failed: %s: %s\n"), fname, strerror(errno)); return -1; } if (statp->bs_size == 0) { if (vflag) fsrprintf(_("%s: zero size, ignoring\n"), fname); return(0); } /* Check if a mandatory lock is set on the file to try and * avoid blocking indefinitely on the reads later. Note that * someone could still set a mandatory lock after this check * but before all reads have completed to block fsr reads. * This change just closes the window a bit. */ if ( (statp->bs_mode & S_ISGID) && ( ! (statp->bs_mode&S_IXGRP) ) ) { struct flock fl; fl.l_type = F_RDLCK; fl.l_whence = SEEK_SET; fl.l_start = (off_t)0; fl.l_len = 0; if ((fcntl(fd, F_GETLK, &fl)) < 0 ) { if (vflag) fsrprintf(_("locking check failed: %s\n"), fname); return(-1); } if (fl.l_type != F_UNLCK) { /* Mandatory lock is set */ if (vflag) fsrprintf(_("mandatory lock: %s: ignoring\n"), fname); return(-1); } } /* * Check if there is room to copy the file. * * Note that xfs_bstat.bs_blksize returns the filesystem blocksize, * not the optimal I/O size as struct stat. */ if (statvfs(fsname ? fsname : fname, &vfss) < 0) { fsrprintf(_("unable to get fs stat on %s: %s\n"), fname, strerror(errno)); return -1; } bsize = vfss.f_frsize ? vfss.f_frsize : vfss.f_bsize; if (statp->bs_blksize * statp->bs_blocks > vfss.f_bfree * bsize - minimumfree) { fsrprintf(_("insufficient freespace for: %s: " "size=%lld: ignoring\n"), fname, statp->bs_blksize * statp->bs_blocks); return 1; } if ((ioctl(fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { fsrprintf(_("failed to get inode attrs: %s\n"), fname); return(-1); } if (fsx.fsx_xflags & (FS_XFLAG_IMMUTABLE|FS_XFLAG_APPEND)) { if (vflag) fsrprintf(_("%s: immutable/append, ignoring\n"), fname); return(0); } if (fsx.fsx_xflags & FS_XFLAG_NODEFRAG) { if (vflag) fsrprintf(_("%s: marked as don't defrag, ignoring\n"), fname); return(0); } if (fsx.fsx_xflags & FS_XFLAG_REALTIME) { if (xfs_getrt(fd, &vfss) < 0) { fsrprintf(_("cannot get realtime geometry for: %s\n"), fname); return(-1); } if (statp->bs_size > ((vfss.f_bfree * bsize) - minimumfree)) { fsrprintf(_("low on realtime free space: %s: " "ignoring file\n"), fname); return(-1); } } if ((RealUid != ROOT) && (RealUid != statp->bs_uid)) { fsrprintf(_("cannot open: %s: Permission denied\n"), fname); return -1; } /* * Previously the code forked here, & the child changed it's uid to * that of the file's owner and then called packfile(), to keep * quota counts correct. (defragged files could use fewer blocks). * * Instead, just fchown() the temp file to the uid,gid of the * file we're defragging, in packfile(). */ if ((error = packfile(fname, tname, fd, statp, &fsx))) return error; return -1; /* no error */ } /* * Attempt to set the attr fork up correctly. This is simple for attr1 * filesystems as they have a fixed inode fork offset. In that case * just create an attribute and that's all we need to do. * * For attr2 filesystems, see if we have the actual fork offset in * the bstat structure. If so, just create additional attributes on * the temporary inode until the offset matches. * * If it doesn't exist, we can only do best effort. Add an attribute at a time * to move the inode fork around, but take into account that the attribute * might be too small to move the fork every time we add one. This should * hopefully put the fork offset in the right place. It's not a big deal if we * don't get it right - the kernel will reject it when we try to swap extents. */ static int fsr_setup_attr_fork( int fd, int tfd, xfs_bstat_t *bstatp) { #ifdef HAVE_FSETXATTR struct stat tstatbuf; int i; int diff = 0; int last_forkoff = 0; int no_change_cnt = 0; int ret; if (!(bstatp->bs_xflags & FS_XFLAG_HASATTR)) return 0; /* * use the old method if we have attr1 or the kernel does not yet * support passing the fork offset in the bulkstat data. */ if (!(fsgeom.flags & XFS_FSOP_GEOM_FLAGS_ATTR2) || bstatp->bs_forkoff == 0) { /* attr1 */ ret = fsetxattr(tfd, "user.X", "X", 1, XATTR_CREATE); if (ret) { fsrprintf(_("could not set ATTR\n")); return -1; } goto out; } /* attr2 w/ fork offsets */ if (fstat(tfd, &tstatbuf) < 0) { fsrprintf(_("unable to stat temp file: %s\n"), strerror(errno)); return -1; } i = 0; do { xfs_bstat_t tbstat; xfs_ino_t ino; char name[64]; /* * bulkstat the temp inode to see what the forkoff is. Use * this to compare against the target and determine what we * need to do. */ ino = tstatbuf.st_ino; if ((xfs_bulkstat_single(tfd, &ino, &tbstat)) < 0) { fsrprintf(_("unable to get bstat on temp file: %s\n"), strerror(errno)); return -1; } if (dflag) fsrprintf(_("orig forkoff %d, temp forkoff %d\n"), bstatp->bs_forkoff, tbstat.bs_forkoff); diff = tbstat.bs_forkoff - bstatp->bs_forkoff; /* if they are equal, we are done */ if (!diff) goto out; snprintf(name, sizeof(name), "user.%d", i); /* * If there is no attribute, then we need to create one to get * an attribute fork at the default location. */ if (!tbstat.bs_forkoff) { ASSERT(i == 0); ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE); if (ret) { fsrprintf(_("could not set ATTR\n")); return -1; } continue; } else if (i == 0) { /* * First pass, and temp file already has an inline * xattr, probably due to selinux. * * It's *possible* that the temp file attr area * is larger than the target file's: * * Target Temp * +-------+ 0 +-------+ 0 * | | | | * | | | Data | * | Data | | | * | | v-------v forkoff * | | | | * v-------v forkoff | Attr | local * | Attr | | | * +-------+ +-------+ */ /* * If target attr area is less than the temp's * (diff < 0) write a big attr to the temp file to knock * the attr out of local format. * (This should actually *increase* the temp file's * forkoffset when the attr moves out of the inode) */ if (diff < 0) { char val[2048]; memset(val, 'X', 2048); if (fsetxattr(tfd, name, val, 2048, 0)) { fsrprintf(_("big ATTR set failed\n")); return -1; } /* Go back & see where we're at now */ continue; } } /* * make a progress check so we don't get stuck trying to extend * a large btree form attribute fork. */ if (last_forkoff == tbstat.bs_forkoff) { if (no_change_cnt++ > 10) break; } else /* progress! */ no_change_cnt = 0; last_forkoff = tbstat.bs_forkoff; /* work out which way to grow the fork */ if (abs(diff) > fsgeom.inodesize - sizeof(struct xfs_dinode)) { fsrprintf(_("forkoff diff %d too large!\n"), diff); return -1; } /* * if the temp inode fork offset is still smaller then we have * to grow the data fork */ if (diff < 0) { /* * create some temporary extents in the inode to move * the fork in the direction we need. This can be done * by preallocating some single block extents at * non-contiguous offsets. */ /* XXX: unimplemented! */ if (dflag) printf(_("data fork growth unimplemented\n")); goto out; } /* we need to grow the attr fork, so create another attr */ ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE); if (ret) { fsrprintf(_("could not set ATTR\n")); return -1; } } while (++i < 100); /* don't go forever */ out: if (dflag) fsrprintf(_("set temp attr\n")); /* We failed to resolve the fork difference */ if (dflag && diff) fsrprintf(_("failed to match fork offset\n"));; #endif /* HAVE_FSETXATTR */ return 0; } /* * Do the defragmentation of a single file. * We already are pretty sure we can and want to * defragment the file. Create the tmp file, copy * the data (maintaining holes) and call the kernel * extent swap routine. * * Return values: * -1: Some error was encountered * 0: Successfully defragmented the file * 1: No change / No Error */ static int packfile(char *fname, char *tname, int fd, xfs_bstat_t *statp, struct fsxattr *fsxp) { int tfd = -1; int srval; int retval = -1; /* Failure is the default */ int nextents, extent, cur_nextents, new_nextents; unsigned blksz_dio; unsigned dio_min; struct dioattr dio; static xfs_swapext_t sx; struct xfs_flock64 space; off64_t cnt, pos; void *fbuf = NULL; int ct, wc, wc_b4; char ffname[SMBUFSZ]; int ffd = -1; /* * Work out the extent map - nextents will be set to the * minimum number of extents needed for the file (taking * into account holes), cur_nextents is the current number * of extents. */ nextents = read_fd_bmap(fd, statp, &cur_nextents); if (cur_nextents == 1 || cur_nextents <= nextents) { if (vflag) fsrprintf(_("%s already fully defragmented.\n"), fname); retval = 1; /* indicates no change/no error */ goto out; } if (dflag) fsrprintf(_("%s extents=%d can_save=%d tmp=%s\n"), fname, cur_nextents, (cur_nextents - nextents), tname); if ((tfd = open(tname, openopts, 0666)) < 0) { if (vflag) fsrprintf(_("could not open tmp file: %s: %s\n"), tname, strerror(errno)); goto out; } unlink(tname); /* Setup extended attributes */ if (fsr_setup_attr_fork(fd, tfd, statp) != 0) { fsrprintf(_("failed to set ATTR fork on tmp: %s:\n"), tname); goto out; } /* Setup extended inode flags, project identifier, etc */ if (fsxp->fsx_xflags || fsxp->fsx_projid) { if (ioctl(tfd, FS_IOC_FSSETXATTR, fsxp) < 0) { fsrprintf(_("could not set inode attrs on tmp: %s\n"), tname); goto out; } } if ((ioctl(tfd, XFS_IOC_DIOINFO, &dio)) < 0 ) { fsrprintf(_("could not get DirectIO info on tmp: %s\n"), tname); goto out; } dio_min = dio.d_miniosz; if (statp->bs_size <= dio_min) { blksz_dio = dio_min; } else { blksz_dio = min(dio.d_maxiosz, BUFFER_MAX - pagesize); if (argv_blksz_dio != 0) blksz_dio = min(argv_blksz_dio, blksz_dio); blksz_dio = (min(statp->bs_size, blksz_dio) / dio_min) * dio_min; } if (dflag) { fsrprintf(_("DEBUG: " "fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n"), statp->bs_size, blksz_dio, dio.d_miniosz, dio.d_maxiosz, pagesize); } if (!(fbuf = (char *)memalign(dio.d_mem, blksz_dio))) { fsrprintf(_("could not allocate buf: %s\n"), tname); goto out; } if (nfrags) { /* Create new tmp file in same AG as first */ sprintf(ffname, "%s.frag", tname); /* Open the new file for sync writes */ if ((ffd = open(ffname, openopts, 0666)) < 0) { fsrprintf(_("could not open fragfile: %s : %s\n"), ffname, strerror(errno)); goto out; } unlink(ffname); } /* Loop through block map allocating new extents */ for (extent = 0; extent < nextents; extent++) { pos = outmap[extent].bmv_offset; if (outmap[extent].bmv_block == -1) { space.l_whence = SEEK_SET; space.l_start = pos; space.l_len = outmap[extent].bmv_length; if (ioctl(tfd, XFS_IOC_UNRESVSP64, &space) < 0) { fsrprintf(_("could not trunc tmp %s\n"), tname); } if (lseek(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) { fsrprintf(_("could not lseek in tmpfile: %s : %s\n"), tname, strerror(errno)); goto out; } continue; } else if (outmap[extent].bmv_length == 0) { /* to catch holes at the beginning of the file */ continue; } if (! nfrags) { space.l_whence = SEEK_CUR; space.l_start = 0; space.l_len = outmap[extent].bmv_length; if (ioctl(tfd, XFS_IOC_RESVSP64, &space) < 0) { fsrprintf(_("could not pre-allocate tmp space:" " %s\n"), tname); goto out; } if (lseek(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) { fsrprintf(_("could not lseek in tmpfile: %s : %s\n"), tname, strerror(errno)); goto out; } } } /* end of space allocation loop */ if (lseek(tfd, 0, SEEK_SET)) { fsrprintf(_("Couldn't rewind on temporary file\n")); goto out; } /* Check if the temporary file has fewer extents */ new_nextents = getnextents(tfd); if (dflag) fsrprintf(_("Temporary file has %d extents (%d in original)\n"), new_nextents, cur_nextents); if (cur_nextents <= new_nextents) { if (vflag) fsrprintf(_("No improvement will be made (skipping): %s\n"), fname); retval = 1; /* no change/no error */ goto out; } /* Loop through block map copying the file. */ for (extent = 0; extent < nextents; extent++) { pos = outmap[extent].bmv_offset; if (outmap[extent].bmv_block == -1) { if (lseek(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) { fsrprintf(_("could not lseek in tmpfile: %s : %s\n"), tname, strerror(errno)); goto out; } if (lseek(fd, outmap[extent].bmv_length, SEEK_CUR) < 0) { fsrprintf(_("could not lseek in file: %s : %s\n"), fname, strerror(errno)); goto out; } continue; } else if (outmap[extent].bmv_length == 0) { /* to catch holes at the beginning of the file */ continue; } for (cnt = outmap[extent].bmv_length; cnt > 0; cnt -= ct, pos += ct) { if (nfrags && --nfrags) { ct = min(cnt, dio_min); } else if (cnt % dio_min == 0) { ct = min(cnt, blksz_dio); } else { ct = min(cnt + dio_min - (cnt % dio_min), blksz_dio); } ct = read(fd, fbuf, ct); if (ct == 0) { /* EOF, stop trying to read */ extent = nextents; break; } /* Ensure we do direct I/O to correct block * boundaries. */ if (ct % dio_min != 0) { wc = ct + dio_min - (ct % dio_min); } else { wc = ct; } wc_b4 = wc; if (ct < 0 || ((wc = write(tfd, fbuf, wc)) != wc_b4)) { if (ct < 0) fsrprintf(_("bad read of %d bytes " "from %s: %s\n"), wc_b4, fname, strerror(errno)); else if (wc < 0) fsrprintf(_("bad write of %d bytes " "to %s: %s\n"), wc_b4, tname, strerror(errno)); else { /* * Might be out of space * * Try to finish write */ int resid = ct-wc; if ((wc = write(tfd, ((char *)fbuf)+wc, resid)) == resid) { /* worked on second attempt? */ continue; } else if (wc < 0) { fsrprintf(_("bad write2 of %d " "bytes to %s: %s\n"), resid, tname, strerror(errno)); } else { fsrprintf(_("bad copy to %s\n"), tname); } } goto out; } if (nfrags) { /* Do a matching write to the tmp file */ wc_b4 = wc; if (((wc = write(ffd, fbuf, wc)) != wc_b4)) { fsrprintf(_("bad write of %d bytes " "to %s: %s\n"), wc_b4, ffname, strerror(errno)); } } } } if (ftruncate(tfd, statp->bs_size) < 0) { fsrprintf(_("could not truncate tmpfile: %s : %s\n"), fname, strerror(errno)); goto out; } if (fsync(tfd) < 0) { fsrprintf(_("could not fsync tmpfile: %s : %s\n"), fname, strerror(errno)); goto out; } sx.sx_stat = *statp; /* struct copy */ sx.sx_version = XFS_SX_VERSION; sx.sx_fdtarget = fd; sx.sx_fdtmp = tfd; sx.sx_offset = 0; sx.sx_length = statp->bs_size; /* switch to the owner's id, to keep quota in line */ if (fchown(tfd, statp->bs_uid, statp->bs_gid) < 0) { if (vflag) fsrprintf(_("failed to fchown tmpfile %s: %s\n"), tname, strerror(errno)); goto out; } /* Swap the extents */ srval = xfs_swapext(fd, &sx); if (srval < 0) { if (errno == ENOTSUP) { if (vflag || dflag) fsrprintf(_("%s: file type not supported\n"), fname); } else if (errno == EFAULT) { /* The file has changed since we started the copy */ if (vflag || dflag) fsrprintf(_("%s: file modified defrag aborted\n"), fname); } else if (errno == EBUSY) { /* Timestamp has changed or mmap'ed file */ if (vflag || dflag) fsrprintf(_("%s: file busy\n"), fname); } else { fsrprintf(_("XFS_IOC_SWAPEXT failed: %s: %s\n"), fname, strerror(errno)); } goto out; } /* Report progress */ if (vflag) fsrprintf(_("extents before:%d after:%d %s %s\n"), cur_nextents, new_nextents, (new_nextents <= nextents ? "DONE" : " " ), fname); retval = 0; out: free(fbuf); if (tfd != -1) close(tfd); if (ffd != -1) close(ffd); return retval; } char * gettmpname(char *fname) { static char buf[PATH_MAX+1]; char sbuf[SMBUFSZ]; char *ptr; sprintf(sbuf, "/.fsr%d", getpid()); strncpy(buf, fname, PATH_MAX); buf[PATH_MAX] = '\0'; ptr = strrchr(buf, '/'); if (ptr) { *ptr = '\0'; } else { strcpy(buf, "."); } if ((strlen(buf) + strlen (sbuf)) > PATH_MAX) { fsrprintf(_("tmp file name too long: %s\n"), fname); return(NULL); } strcat(buf, sbuf); return(buf); } char * getparent(char *fname) { static char buf[PATH_MAX+1]; char *ptr; strncpy(buf, fname, PATH_MAX); buf[PATH_MAX] = '\0'; ptr = strrchr(buf, '/'); if (ptr) { if (ptr == &buf[0]) ++ptr; *ptr = '\0'; } else { strcpy(buf, "."); } return(buf); } /* * Read in block map of the input file, coalesce contiguous * extents into a single range, keep all holes. Convert from 512 byte * blocks to bytes. * * This code was borrowed from mv.c with some minor mods. */ #define MAPSIZE 128 #define OUTMAP_SIZE_INCREMENT MAPSIZE int read_fd_bmap(int fd, xfs_bstat_t *sin, int *cur_nextents) { int i, cnt; struct getbmap map[MAPSIZE]; #define BUMP_CNT \ if (++cnt >= outmap_size) { \ outmap_size += OUTMAP_SIZE_INCREMENT; \ outmap = (struct getbmap *)realloc(outmap, \ outmap_size*sizeof(*outmap)); \ if (outmap == NULL) { \ fsrprintf(_("realloc failed: %s\n"), \ strerror(errno)); \ exit(1); \ } \ } /* Initialize the outmap array. It always grows - never shrinks. * Left-over memory allocation is saved for the next files. */ if (outmap_size == 0) { outmap_size = OUTMAP_SIZE_INCREMENT; /* Initial size */ outmap = (struct getbmap *)malloc(outmap_size*sizeof(*outmap)); if (!outmap) { fsrprintf(_("malloc failed: %s\n"), strerror(errno)); exit(1); } } outmap[0].bmv_block = 0; outmap[0].bmv_offset = 0; outmap[0].bmv_length = sin->bs_size; /* * If a non regular file is involved then forget holes */ if (!S_ISREG(sin->bs_mode)) return(1); outmap[0].bmv_length = 0; map[0].bmv_offset = 0; map[0].bmv_block = 0; map[0].bmv_entries = 0; map[0].bmv_count = MAPSIZE; map[0].bmv_length = -1; cnt = 0; *cur_nextents = 0; do { if (ioctl(fd, XFS_IOC_GETBMAP, map) < 0) { fsrprintf(_("failed reading extents: inode %llu"), (unsigned long long)sin->bs_ino); exit(1); } /* Concatenate extents together and replicate holes into * the output map. */ *cur_nextents += map[0].bmv_entries; for (i = 0; i < map[0].bmv_entries; i++) { if (map[i + 1].bmv_block == -1) { BUMP_CNT; outmap[cnt] = map[i+1]; } else if (outmap[cnt].bmv_block == -1) { BUMP_CNT; outmap[cnt] = map[i+1]; } else { outmap[cnt].bmv_length += map[i + 1].bmv_length; } } } while (map[0].bmv_entries == (MAPSIZE-1)); for (i = 0; i <= cnt; i++) { outmap[i].bmv_offset = BBTOB(outmap[i].bmv_offset); outmap[i].bmv_length = BBTOB(outmap[i].bmv_length); } outmap[cnt].bmv_length = sin->bs_size - outmap[cnt].bmv_offset; return(cnt+1); } /* * Read the block map and return the number of extents. */ int getnextents(int fd) { int nextents; struct getbmap map[MAPSIZE]; map[0].bmv_offset = 0; map[0].bmv_block = 0; map[0].bmv_entries = 0; map[0].bmv_count = MAPSIZE; map[0].bmv_length = -1; nextents = 0; do { if (ioctl(fd,XFS_IOC_GETBMAP, map) < 0) { fsrprintf(_("failed reading extents")); exit(1); } nextents += map[0].bmv_entries; } while (map[0].bmv_entries == (MAPSIZE-1)); return(nextents); } /* * Get the fs geometry */ int xfs_getgeom(int fd, xfs_fsop_geom_v1_t * fsgeom) { if (xfs_fsgeometry(fd, fsgeom) < 0) { return -1; } return 0; } /* * Get xfs realtime space information */ int xfs_getrt(int fd, struct statvfs *sfbp) { unsigned long bsize; unsigned long factor; xfs_fsop_counts_t cnt; if (!fsgeom.rtblocks) return -1; if (xfs_fscounts(fd, &cnt) < 0) { close(fd); return -1; } bsize = (sfbp->f_frsize ? sfbp->f_frsize : sfbp->f_bsize); factor = fsgeom.blocksize / bsize; /* currently this is == 1 */ sfbp->f_bfree = (cnt.freertx * fsgeom.rtextsize) * factor; return 0; } int fsrprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (gflag) { static int didopenlog; if (!didopenlog) { openlog("fsr", LOG_PID, LOG_USER); didopenlog = 1; } vsyslog(LOG_INFO, fmt, ap); } else vprintf(fmt, ap); va_end(ap); return 0; } /* * Initialize a directory for tmp file use. This is used * by the full filesystem defragmentation when we're walking * the inodes and do not know the path for the individual * files. Multiple directories are used to spread out the * tmp data around to different ag's (since file data is * usually allocated to the same ag as the directory and * directories allocated round robin from the same * parent directory). */ static void tmp_init(char *mnt) { int i; static char buf[SMBUFSZ]; mode_t mask; tmp_agi = 0; sprintf(buf, "%s/.fsr", mnt); mask = umask(0); if (mkdir(buf, 0700) < 0) { if (errno == EEXIST) { if (dflag) fsrprintf(_("tmpdir already exists: %s\n"), buf); } else { fsrprintf(_("could not create tmpdir: %s: %s\n"), buf, strerror(errno)); exit(-1); } } for (i=0; i < fsgeom.agcount; i++) { sprintf(buf, "%s/.fsr/ag%d", mnt, i); if (mkdir(buf, 0700) < 0) { if (errno == EEXIST) { if (dflag) fsrprintf( _("tmpdir already exists: %s\n"), buf); } else { fsrprintf(_("cannot create tmpdir: %s: %s\n"), buf, strerror(errno)); exit(-1); } } } (void)umask(mask); return; } static char * tmp_next(char *mnt) { static char buf[SMBUFSZ]; sprintf(buf, "%s/.fsr/ag%d/tmp%d", ( (strcmp(mnt, "/") == 0) ? "" : mnt), tmp_agi, getpid()); if (++tmp_agi == fsgeom.agcount) tmp_agi = 0; return(buf); } static void tmp_close(char *mnt) { static char buf[SMBUFSZ]; int i; /* No data is ever actually written so we can just do rmdir's */ for (i=0; i < fsgeom.agcount; i++) { sprintf(buf, "%s/.fsr/ag%d", mnt, i); if (rmdir(buf) < 0) { if (errno != ENOENT) { fsrprintf( _("could not remove tmpdir: %s: %s\n"), buf, strerror(errno)); } } } sprintf(buf, "%s/.fsr", mnt); if (rmdir(buf) < 0) { if (errno != ENOENT) { fsrprintf(_("could not remove tmpdir: %s: %s\n"), buf, strerror(errno)); } } } xfsprogs-4.9.0+nmu1ubuntu2/growfs/0000755000000000000000000000000013063067174014004 5ustar xfsprogs-4.9.0+nmu1ubuntu2/growfs/Makefile0000644000000000000000000000134213063067173015443 0ustar # # Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_growfs CFILES = xfs_growfs.c LLDLIBS = $(LIBXFS) $(LIBXCMD) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) ifeq ($(ENABLE_READLINE),yes) LLDLIBS += $(LIBREADLINE) $(LIBTERMCAP) endif ifeq ($(ENABLE_EDITLINE),yes) LLDLIBS += $(LIBEDITLINE) $(LIBTERMCAP) endif LTDEPENDENCIES = $(LIBXFS) $(LIBXCMD) LLDFLAGS = -static-libtool-libs LSRCFILES = xfs_info.sh default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) $(INSTALL) -m 755 xfs_info.sh $(PKG_SBIN_DIR)/xfs_info install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/growfs/xfs_growfs.c0000644000000000000000000003332713063067173016346 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "path.h" static void usage(void) { fprintf(stderr, _( "Usage: %s [options] mountpoint\n\n\ Options:\n\ -d grow data/metadata section\n\ -l grow log section\n\ -r grow realtime section\n\ -n don't change anything, just show geometry\n\ -i convert log from external to internal format\n\ -t alternate location for mount table (/etc/mtab)\n\ -x convert log from internal to external format\n\ -D size grow data/metadata section to size blks\n\ -L size grow/shrink log section to size blks\n\ -R size grow realtime section to size blks\n\ -e size set realtime extent size to size blks\n\ -m imaxpct set inode max percent to imaxpct\n\ -V print version information\n"), progname); exit(2); } void report_info( xfs_fsop_geom_t geo, char *mntpoint, int isint, char *logname, char *rtname, int lazycount, int dirversion, int logversion, int attrversion, int projid32bit, int crcs_enabled, int cimode, int ftype_enabled, int finobt_enabled, int spinodes, int rmapbt_enabled, int reflink_enabled) { printf(_( "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u rmapbt=%u\n" " =%-22s reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n"), mntpoint, geo.inodesize, geo.agcount, geo.agblocks, "", geo.sectsize, attrversion, projid32bit, "", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled, "", reflink_enabled, "", geo.blocksize, (unsigned long long)geo.datablocks, geo.imaxpct, "", geo.sunit, geo.swidth, dirversion, geo.dirblocksize, cimode, ftype_enabled, isint ? _("internal") : logname ? logname : _("external"), geo.blocksize, geo.logblocks, logversion, "", geo.logsectsize, geo.logsunit / geo.blocksize, lazycount, !geo.rtblocks ? _("none") : rtname ? rtname : _("external"), geo.rtextsize * geo.blocksize, (unsigned long long)geo.rtblocks, (unsigned long long)geo.rtextents); } int main(int argc, char **argv) { int aflag; /* fake flag, do all pieces */ int c; /* current option character */ long long ddsize; /* device size in 512-byte blocks */ int dflag; /* -d flag */ int attrversion;/* attribute version number */ int dirversion; /* directory version number */ int logversion; /* log version number */ long long dlsize; /* device size in 512-byte blocks */ long long drsize; /* device size in 512-byte blocks */ long long dsize; /* new data size in fs blocks */ int error; /* we have hit an error */ long esize; /* new rt extent size */ int ffd; /* mount point file descriptor */ xfs_fsop_geom_t geo; /* current fs geometry */ int iflag; /* -i flag */ int isint; /* log is currently internal */ int lflag; /* -l flag */ long long lsize; /* new log size in fs blocks */ int maxpct; /* -m flag value */ int mflag; /* -m flag */ int nflag; /* -n flag */ xfs_fsop_geom_t ngeo; /* new fs geometry */ int rflag; /* -r flag */ long long rsize; /* new rt size in fs blocks */ int ci; /* ASCII case-insensitive fs */ int lazycount; /* lazy superblock counters */ int xflag; /* -x flag */ char *fname; /* mount point name */ char *datadev; /* data device name */ char *logdev; /* log device name */ char *rtdev; /* RT device name */ fs_path_t *fs; /* mount point information */ libxfs_init_t xi; /* libxfs structure */ int projid32bit; int crcs_enabled; int ftype_enabled = 0; int finobt_enabled; /* free inode btree */ int spinodes; int rmapbt_enabled; int reflink_enabled; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); maxpct = esize = 0; dsize = lsize = rsize = 0LL; aflag = dflag = iflag = lflag = mflag = nflag = rflag = xflag = 0; while ((c = getopt(argc, argv, "dD:e:ilL:m:np:rR:t:xV")) != EOF) { switch (c) { case 'D': dsize = strtoll(optarg, NULL, 10); /* fall through */ case 'd': dflag = 1; break; case 'e': esize = atol(optarg); rflag = 1; break; case 'i': lflag = iflag = 1; break; case 'L': lsize = strtoll(optarg, NULL, 10); /* fall through */ case 'l': lflag = 1; break; case 'm': mflag = 1; maxpct = atoi(optarg); break; case 'n': nflag = 1; break; case 'p': progname = optarg; break; case 'R': rsize = strtoll(optarg, NULL, 10); /* fall through */ case 'r': rflag = 1; break; case 't': mtab_file = optarg; break; case 'x': lflag = xflag = 1; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); case '?': default: usage(); } } if (argc - optind != 1) usage(); if (iflag && xflag) usage(); if (dflag + lflag + rflag + mflag == 0) aflag = 1; fs_table_initialise(0, NULL, 0, NULL); fs = fs_table_lookup(argv[optind], FS_MOUNT_POINT); if (!fs) { fprintf(stderr, _("%s: %s is not a mounted XFS filesystem\n"), progname, argv[optind]); return 1; } fname = fs->fs_dir; datadev = fs->fs_name; logdev = fs->fs_log; rtdev = fs->fs_rt; ffd = open(fname, O_RDONLY); if (ffd < 0) { perror(fname); return 1; } if (!platform_test_xfs_fd(ffd)) { fprintf(stderr, _("%s: specified file " "[\"%s\"] is not on an XFS filesystem\n"), progname, fname); exit(1); } /* get the current filesystem size & geometry */ if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY, &geo) < 0) { /* * OK, new xfsctl barfed - back off and try earlier version * as we're probably running an older kernel version. * Only field added in the v2 geometry xfsctl is "logsunit" * so we'll zero that out for later display (as zero). */ geo.logsunit = 0; if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY_V1, &geo) < 0) { fprintf(stderr, _( "%s: cannot determine geometry of filesystem" " mounted at %s: %s\n"), progname, fname, strerror(errno)); exit(1); } } isint = geo.logstart > 0; lazycount = geo.flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0; dirversion = geo.flags & XFS_FSOP_GEOM_FLAGS_DIRV2 ? 2 : 1; logversion = geo.flags & XFS_FSOP_GEOM_FLAGS_LOGV2 ? 2 : 1; attrversion = geo.flags & XFS_FSOP_GEOM_FLAGS_ATTR2 ? 2 : \ (geo.flags & XFS_FSOP_GEOM_FLAGS_ATTR ? 1 : 0); ci = geo.flags & XFS_FSOP_GEOM_FLAGS_DIRV2CI ? 1 : 0; projid32bit = geo.flags & XFS_FSOP_GEOM_FLAGS_PROJID32 ? 1 : 0; crcs_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_V5SB ? 1 : 0; ftype_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_FTYPE ? 1 : 0; finobt_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_FINOBT ? 1 : 0; spinodes = geo.flags & XFS_FSOP_GEOM_FLAGS_SPINODES ? 1 : 0; rmapbt_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_RMAPBT ? 1 : 0; reflink_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_REFLINK ? 1 : 0; if (nflag) { report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, attrversion, projid32bit, crcs_enabled, ci, ftype_enabled, finobt_enabled, spinodes, rmapbt_enabled, reflink_enabled); exit(0); } /* * Need root access from here on (using raw devices)... */ memset(&xi, 0, sizeof(xi)); xi.dname = datadev; xi.logname = logdev; xi.rtname = rtdev; xi.isreadonly = LIBXFS_ISREADONLY; if (!libxfs_init(&xi)) usage(); /* check we got the info for all the sections we are trying to modify */ if (!xi.ddev) { fprintf(stderr, _("%s: failed to access data device for %s\n"), progname, fname); exit(1); } if (lflag && !isint && !xi.logdev) { fprintf(stderr, _("%s: failed to access external log for %s\n"), progname, fname); exit(1); } if (rflag && !xi.rtdev) { fprintf(stderr, _("%s: failed to access realtime device for %s\n"), progname, fname); exit(1); } report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, attrversion, projid32bit, crcs_enabled, ci, ftype_enabled, finobt_enabled, spinodes, rmapbt_enabled, reflink_enabled); ddsize = xi.dsize; dlsize = ( xi.logBBsize? xi.logBBsize : geo.logblocks * (geo.blocksize / BBSIZE) ); drsize = xi.rtsize; /* * Ok, Linux only has a 1024-byte resolution on device _size_, * and the sizes below are in basic 512-byte blocks, * so if we have (size % 2), on any partition, we can't get * to the last 512 bytes. Just chop it down by a block. */ ddsize -= (ddsize % 2); dlsize -= (dlsize % 2); drsize -= (drsize % 2); error = 0; if (dflag | mflag | aflag) { xfs_growfs_data_t in; if (!mflag) maxpct = geo.imaxpct; if (!dflag && !aflag) /* Only mflag, no data size change */ dsize = geo.datablocks; else if (!dsize) dsize = ddsize / (geo.blocksize / BBSIZE); else if (dsize > ddsize / (geo.blocksize / BBSIZE)) { fprintf(stderr, _( "data size %lld too large, maximum is %lld\n"), (long long)dsize, (long long)(ddsize/(geo.blocksize/BBSIZE))); error = 1; } if (!error && dsize < geo.datablocks) { fprintf(stderr, _("data size %lld too small," " old size is %lld\n"), (long long)dsize, (long long)geo.datablocks); error = 1; } else if (!error && dsize == geo.datablocks && maxpct == geo.imaxpct) { if (dflag) fprintf(stderr, _( "data size unchanged, skipping\n")); if (mflag) fprintf(stderr, _( "inode max pct unchanged, skipping\n")); } else if (!error && !nflag) { in.newblocks = (__u64)dsize; in.imaxpct = (__u32)maxpct; if (xfsctl(fname, ffd, XFS_IOC_FSGROWFSDATA, &in) < 0) { if (errno == EWOULDBLOCK) fprintf(stderr, _( "%s: growfs operation in progress already\n"), progname); else fprintf(stderr, _( "%s: XFS_IOC_FSGROWFSDATA xfsctl failed: %s\n"), progname, strerror(errno)); error = 1; } } } if (!error && (rflag | aflag)) { xfs_growfs_rt_t in; if (!esize) esize = (__u32)geo.rtextsize; if (!rsize) rsize = drsize / (geo.blocksize / BBSIZE); else if (rsize > drsize / (geo.blocksize / BBSIZE)) { fprintf(stderr, _( "realtime size %lld too large, maximum is %lld\n"), rsize, drsize / (geo.blocksize / BBSIZE)); error = 1; } if (!error && rsize < geo.rtblocks) { fprintf(stderr, _( "realtime size %lld too small, old size is %lld\n"), (long long)rsize, (long long)geo.rtblocks); error = 1; } else if (!error && rsize == geo.rtblocks) { if (rflag) fprintf(stderr, _( "realtime size unchanged, skipping\n")); } else if (!error && !nflag) { in.newblocks = (__u64)rsize; in.extsize = (__u32)esize; if (xfsctl(fname, ffd, XFS_IOC_FSGROWFSRT, &in) < 0) { if (errno == EWOULDBLOCK) fprintf(stderr, _( "%s: growfs operation in progress already\n"), progname); else if (errno == ENOSYS) fprintf(stderr, _( "%s: realtime growth not implemented\n"), progname); else fprintf(stderr, _( "%s: XFS_IOC_FSGROWFSRT xfsctl failed: %s\n"), progname, strerror(errno)); error = 1; } } } if (!error && (lflag | aflag)) { xfs_growfs_log_t in; if (!lsize) lsize = dlsize / (geo.blocksize / BBSIZE); if (iflag) in.isint = 1; else if (xflag) in.isint = 0; else in.isint = xi.logBBsize == 0; if (lsize == geo.logblocks && (in.isint == isint)) { if (lflag) fprintf(stderr, _("log size unchanged, skipping\n")); } else if (!nflag) { in.newblocks = (__u32)lsize; if (xfsctl(fname, ffd, XFS_IOC_FSGROWFSLOG, &in) < 0) { if (errno == EWOULDBLOCK) fprintf(stderr, _("%s: growfs operation in progress already\n"), progname); else if (errno == ENOSYS) fprintf(stderr, _("%s: log growth not supported yet\n"), progname); else fprintf(stderr, _("%s: XFS_IOC_FSGROWFSLOG xfsctl failed: %s\n"), progname, strerror(errno)); error = 1; } } } if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY_V1, &ngeo) < 0) { fprintf(stderr, _("%s: XFS_IOC_FSGEOMETRY xfsctl failed: %s\n"), progname, strerror(errno)); exit(1); } if (geo.datablocks != ngeo.datablocks) printf(_("data blocks changed from %lld to %lld\n"), (long long)geo.datablocks, (long long)ngeo.datablocks); if (geo.imaxpct != ngeo.imaxpct) printf(_("inode max percent changed from %d to %d\n"), geo.imaxpct, ngeo.imaxpct); if (geo.logblocks != ngeo.logblocks) printf(_("log blocks changed from %d to %d\n"), geo.logblocks, ngeo.logblocks); if ((geo.logstart == 0) != (ngeo.logstart == 0)) printf(_("log changed from %s to %s\n"), geo.logstart ? _("internal") : _("external"), ngeo.logstart ? _("internal") : _("external")); if (geo.rtblocks != ngeo.rtblocks) printf(_("realtime blocks changed from %lld to %lld\n"), (long long)geo.rtblocks, (long long)ngeo.rtblocks); if (geo.rtextsize != ngeo.rtextsize) printf(_("realtime extent size changed from %d to %d\n"), geo.rtextsize, ngeo.rtextsize); exit(error); } xfsprogs-4.9.0+nmu1ubuntu2/growfs/xfs_info.sh0000755000000000000000000000073013063067173016155 0ustar #!/bin/sh -f # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # OPTS="" USAGE="Usage: xfs_info [-V] [-t mtab] mountpoint" while getopts "t:V" c do case $c in t) OPTS="-t $OPTARG" ;; V) xfs_growfs -p xfs_info -V status=$? exit $status ;; *) echo $USAGE 1>&2 exit 2 ;; esac done set -- extra "$@" shift $OPTIND case $# in 1) xfs_growfs -p xfs_info -n $OPTS "$1" status=$? ;; *) echo $USAGE 1>&2 exit 2 ;; esac exit $status xfsprogs-4.9.0+nmu1ubuntu2/include/0000755000000000000000000000000013136024635014114 5ustar xfsprogs-4.9.0+nmu1ubuntu2/include/Makefile0000644000000000000000000000340013063067171015552 0ustar # # Copyright (c) 2000-2006 Silicon Graphics, Inc. # All Rights Reserved. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # TOPDIR = .. include $(TOPDIR)/include/builddefs LIBHFILES = libxfs.h \ libxlog.h \ libxcmd.h \ atomic.h \ bitops.h \ cache.h \ hlist.h \ kmem.h \ list.h \ parent.h \ radix-tree.h \ xfs_btree_trace.h \ xfs_inode.h \ xfs_log_recover.h \ xfs_metadump.h \ xfs_mount.h \ xfs_quota_defs.h \ xfs_sb.h \ xfs_shared.h \ xfs_trace.h \ xfs_trans.h \ command.h \ input.h \ path.h \ project.h \ platform_defs.h HFILES = handle.h \ jdm.h \ $(PKG_PLATFORM).h \ xfs.h \ xqm.h \ xfs_arch.h PHFILES = darwin.h freebsd.h irix.h linux.h gnukfreebsd.h LSRCFILES = $(shell echo $(PHFILES) | sed -e "s/$(PKG_PLATFORM).h//g") LSRCFILES += platform_defs.h.in builddefs.in buildmacros buildrules install-sh LSRCFILES += $(DKHFILES) $(LIBHFILES) LDIRT = disk LDIRDIRT = xfs default: disk disk: @echo " [LN] $@" $(Q)$(LN_S) . $@ include $(BUILDRULES) # set up include/xfs header directory install-headers: $(addsuffix -hdrs, $(PHFILES) $(DKHFILES) $(HFILES)) %-hdrs: $(Q)$(LN_S) -f $(CURDIR)/$* xfs/$* install: default $(INSTALL) -m 755 -d $(PKG_INC_DIR) install-dev: install $(INSTALL) -m 644 $(HFILES) $(PKG_INC_DIR) xfsprogs-4.9.0+nmu1ubuntu2/include/atomic.h0000644000000000000000000000233313063067171015543 0ustar /* * Copyright (c) 2011 RedHat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __ATOMIC_H__ #define __ATOMIC_H__ /* * Warning: These are not really atomic at all. They are wrappers around the * kernel atomic variable interface. If we do need these variables to be atomic * (due to multithreading of the code that uses them) we need to add some * pthreads magic here. */ typedef int32_t atomic_t; typedef int64_t atomic64_t; #define atomic_inc_return(x) (++(*(x))) #define atomic_dec_return(x) (--(*(x))) #define atomic64_read(x) *(x) #define atomic64_set(x, v) (*(x) = v) #endif /* __ATOMIC_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/bitops.h0000644000000000000000000000144013063067172015566 0ustar #ifndef __BITOPS_H__ #define __BITOPS_H__ /* * fls: find last bit set. */ #ifndef HAVE_FLS static inline int fls(int x) { int r = 32; if (!x) return 0; if (!(x & 0xffff0000u)) { x <<= 16; r -= 16; } if (!(x & 0xff000000u)) { x <<= 8; r -= 8; } if (!(x & 0xf0000000u)) { x <<= 4; r -= 4; } if (!(x & 0xc0000000u)) { x <<= 2; r -= 2; } if (!(x & 0x80000000u)) { r -= 1; } return r; } #endif /* HAVE_FLS */ static inline int fls64(__u64 x) { __u32 h = x >> 32; if (h) return fls(h) + 32; return fls(x); } static inline unsigned fls_long(unsigned long l) { if (sizeof(l) == 4) return fls(l); return fls64(l); } /* * ffz: find first zero bit. * Result is undefined if no zero bit exists. */ #define ffz(x) ffs(~(x)) #endif xfsprogs-4.9.0+nmu1ubuntu2/include/builddefs.in0000644000000000000000000001063313063067172016412 0ustar # # Copyright (c) 2004-2006 Silicon Graphics, Inc. # All Rights Reserved. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # @configure_input@ # ifndef _BUILDDEFS_INCLUDED_ _BUILDDEFS_INCLUDED_ = 1 DEBUG = @debug_build@ OPTIMIZER = @opt_build@ MALLOCLIB = @malloc_lib@ LOADERFLAGS = @LDFLAGS@ LTLDFLAGS = @LDFLAGS@ CFLAGS = @CFLAGS@ -D_FILE_OFFSET_BITS=64 LIBRT = @librt@ LIBUUID = @libuuid@ LIBPTHREAD = @libpthread@ LIBTERMCAP = @libtermcap@ LIBEDITLINE = @libeditline@ LIBREADLINE = @libreadline@ LIBBLKID = @libblkid@ LIBXFS = $(TOPDIR)/libxfs/libxfs.la LIBXCMD = $(TOPDIR)/libxcmd/libxcmd.la LIBXLOG = $(TOPDIR)/libxlog/libxlog.la LIBHANDLE = $(TOPDIR)/libhandle/libhandle.la PKG_NAME = @pkg_name@ PKG_USER = @pkg_user@ PKG_GROUP = @pkg_group@ PKG_RELEASE = @pkg_release@ PKG_VERSION = @pkg_version@ PKG_PLATFORM = @pkg_platform@ PKG_DISTRIBUTION= @pkg_distribution@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ top_builddir = @top_builddir@ PKG_SBIN_DIR = @sbindir@ PKG_ROOT_SBIN_DIR = @root_sbindir@ PKG_ROOT_LIB_DIR= @root_libdir@@libdirsuffix@ PKG_LIB_DIR = @libdir@@libdirsuffix@ PKG_INC_DIR = @includedir@/xfs DK_INC_DIR = @includedir@/disk PKG_MAN_DIR = @mandir@ PKG_DOC_DIR = @datadir@/doc/@pkg_name@ PKG_LOCALE_DIR = @datadir@/locale CC = @cc@ BUILD_CC = @BUILD_CC@ AWK = @awk@ SED = @sed@ TAR = @tar@ ZIP = @zip@ MAKE = @make@ ECHO = @echo@ SORT = @sort@ LN_S = @LN_S@ SHELL = @SHELL@ LIBTOOL = @LIBTOOL@ MAKEDEPEND = @makedepend@ MSGFMT = @msgfmt@ MSGMERGE = @msgmerge@ XGETTEXT = @xgettext@ LOCALIZED_FILES = @LOCALIZED_FILES@ RPM = @rpm@ RPMBUILD = @rpmbuild@ RPM_VERSION = @rpm_version@ ENABLE_SHARED = @enable_shared@ ENABLE_GETTEXT = @enable_gettext@ ENABLE_EDITLINE = @enable_editline@ ENABLE_READLINE = @enable_readline@ ENABLE_BLKID = @enable_blkid@ HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@ HAVE_FADVISE = @have_fadvise@ HAVE_MADVISE = @have_madvise@ HAVE_MINCORE = @have_mincore@ HAVE_SENDFILE = @have_sendfile@ HAVE_GETMNTENT = @have_getmntent@ HAVE_GETMNTINFO = @have_getmntinfo@ HAVE_FALLOCATE = @have_fallocate@ HAVE_FIEMAP = @have_fiemap@ HAVE_PREADV = @have_preadv@ HAVE_COPY_FILE_RANGE = @have_copy_file_range@ HAVE_SYNC_FILE_RANGE = @have_sync_file_range@ HAVE_READDIR = @have_readdir@ HAVE_MNTENT = @have_mntent@ HAVE_FLS = @have_fls@ HAVE_FSETXATTR = @have_fsetxattr@ HAVE_MREMAP = @have_mremap@ NEED_INTERNAL_FSXATTR = @need_internal_fsxattr@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl ifeq ($(PKG_PLATFORM),linux) PCFLAGS = -D_GNU_SOURCE $(GCCFLAGS) ifeq ($(HAVE_UMODE_T),yes) PCFLAGS += -DHAVE_UMODE_T endif DEPENDFLAGS = -D__linux__ endif ifeq ($(PKG_PLATFORM),gnukfreebsd) PCFLAGS = -D_GNU_SOURCE $(GCCFLAGS) endif ifeq ($(PKG_PLATFORM),darwin) PCFLAGS = $(GCCFLAGS) DEPENDFLAGS = -D__APPLE__ -D_DARWIN_FEATURE_64_BIT_INODE endif ifeq ($(PKG_PLATFORM),irix) PLDLIBS = -ldisk -lgen DEPENDFLAGS = -D__sgi__ endif ifeq ($(PKG_PLATFORM),freebsd) PLDLIBS = -L/usr/local/lib -lintl PCFLAGS = -I/usr/local/include $(GCCFLAGS) DEPENDFLAGS = -D__FreeBSD__ endif ifeq ($(HAVE_FLS),yes) LCFLAGS+= -DHAVE_FLS endif ifeq ($(HAVE_MNTENT),yes) PCFLAGS+= -DHAVE_MNTENT endif ifeq ($(HAVE_FSETXATTR),yes) PCFLAGS+= -DHAVE_FSETXATTR endif ifeq ($(ENABLE_BLKID),yes) PCFLAGS+= -DENABLE_BLKID endif ifeq ($(NEED_INTERNAL_FSXATTR),yes) PCFLAGS+= -DOVERRIDE_SYSTEM_FSXATTR endif GCFLAGS = $(OPTIMIZER) $(DEBUG) \ -DVERSION=\"$(PKG_VERSION)\" -DLOCALEDIR=\"$(PKG_LOCALE_DIR)\" \ -DPACKAGE=\"$(PKG_NAME)\" -I$(TOPDIR)/include -I$(TOPDIR)/libxfs ifeq ($(ENABLE_GETTEXT),yes) GCFLAGS += -DENABLE_GETTEXT endif # First, Global, Platform, Local CFLAGS CFLAGS += $(FCFLAGS) $(GCFLAGS) $(PCFLAGS) $(LCFLAGS) include $(TOPDIR)/include/buildmacros endif # # For targets that should always be rebuilt, # define a target that is never up-to-date. # Targets needing this should depend on $(_FORCE) _FORCE = __force_build xfsprogs-4.9.0+nmu1ubuntu2/include/buildmacros0000644000000000000000000000756213063067172016357 0ustar # # Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. # BUILDRULES = $(TOPDIR)/include/buildrules # LCFLAGS, LLDFLAGS, LLDLIBS, LSRCFILES and LDIRT may be specified in # user Makefiles. Note: LSRCFILES is anything other than Makefile, $(CFILES) # $(CXXFILES), or $(HFILES) and is used to construct the manifest list # during the "dist" phase (packaging). LDFLAGS += $(LOADERFLAGS) $(LLDFLAGS) LTLDFLAGS += $(LOADERFLAGS) LDLIBS = $(LLDLIBS) $(PLDLIBS) $(MALLOCLIB) MAKEOPTS = --no-print-directory Q=$(Q) SRCFILES = Makefile $(HFILES) $(CFILES) $(LSRCFILES) $(LFILES) $(YFILES) SRCFILES += $(QAHFILES) DEPDIRT = dep dep.bak MANDIRT = *.[1-9].gz PODIRT = *.tmpo *.mo CDIRT = $(OBJECTS) $(LTOBJECTS) $(LTCOMMAND) $(LTLIBRARY) DIRT = $(LDIRT) $(DEPDIRT) $(MANDIRT) $(PODIRT) $(CDIRT) LIBDIRT = .libs DIRDIRT = $(LDIRDIRT) $(LIBDIRT) OBJECTS = $(ASFILES:.s=.o) \ $(CFILES:.c=.o) \ $(LFILES:.l=.o) \ $(YFILES:%.y=%.tab.o) INSTALL = $(TOPDIR)/install-sh -o $(PKG_USER) -g $(PKG_GROUP) IMAGES_DIR = $(TOPDIR)/all-images DIST_DIR = $(TOPDIR)/dist CCF = $(CC) $(CFLAGS) $(CPPFLAGS) MAKEF = $(MAKE) $(MAKEOPTS) CXXF = $(CXX) $(CXXFLAGS) # For libtool. LIBNAME = $(basename $(LTLIBRARY)) LTOBJECTS = $(OBJECTS:.o=.lo) LTVERSION = $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) LTLINK = $(LIBTOOL) --quiet --tag=CC --mode=link $(CC) LTEXEC = $(LIBTOOL) --quiet --mode=execute LTINSTALL = $(LIBTOOL) --quiet --mode=install $(INSTALL) LTCOMPILE = $(LIBTOOL) --quiet --tag=CC --mode=compile $(CCF) ifeq ($(ENABLE_SHARED),yes) LTLDFLAGS += -rpath $(PKG_ROOT_LIB_DIR) LTLDFLAGS += -version-info $(LTVERSION) endif ifeq ($(ENABLE_SHARED),yes) INSTALL_LTLIB = \ cd $(TOPDIR)/$(LIBNAME)/.libs; \ ../$(INSTALL) -m 755 -d $(PKG_ROOT_LIB_DIR); \ ../$(INSTALL) -m 755 -T so_dot_version $(LIBNAME).lai $(PKG_ROOT_LIB_DIR); \ ../$(INSTALL) -T so_dot_current $(LIBNAME).lai $(PKG_ROOT_LIB_DIR) endif # Libtool thinks the static and shared libs should be in the same dir, so # make the static lib appear in the place we chose as rpath (using the two # symlinks below). # Other things want the shared libs to appear in /usr/lib, else they'll # link with the static libs there. So, another symlink to get the .so into # /usr/lib. ifeq ($(ENABLE_SHARED),yes) INSTALL_LTLIB_DEV = \ cd $(TOPDIR)/$(LIBNAME)/.libs; \ ../$(INSTALL) -m 755 -d $(PKG_LIB_DIR); \ ../$(INSTALL) -m 644 -T old_lib $(LIBNAME).lai $(PKG_LIB_DIR); \ ../$(INSTALL) -m 644 $(LIBNAME).lai $(PKG_LIB_DIR)/$(LIBNAME).la ; \ ../$(INSTALL) -m 755 -d $(PKG_ROOT_LIB_DIR); \ ../$(INSTALL) -T so_base $(LIBNAME).lai $(PKG_ROOT_LIB_DIR); else INSTALL_LTLIB_DEV = $(INSTALL_LTLIB_STATIC) endif INSTALL_LTLIB_STATIC = \ cd $(TOPDIR)/$(LIBNAME)/.libs; \ ../$(INSTALL) -m 755 -d $(PKG_LIB_DIR); \ ../$(INSTALL) -m 644 -T old_lib $(LIBNAME).lai $(PKG_LIB_DIR) INSTALL_MAN = \ @for d in $(MAN_PAGES); do \ first=true; \ for m in `$(AWK) \ '/^\.S[h|H] NAME/ {ok=1; next} ok {print; exit}' $$d \ | $(SED) \ -e 's/^\.Nm //' -e 's/,/ /g' -e 's/\\-.*//' \ -e 's/\\\f[0-9]//g' -e 's/ / /g;q'`; \ do \ [ -z "$$m" -o "$$m" = "\\" ] && continue; \ t=$(MAN_DEST)/$$m.$(MAN_SECTION); \ if $$first; then \ if $(HAVE_ZIPPED_MANPAGES); then \ $(ZIP) -9 -c $$d > $$d.gz; _sfx=.gz; \ fi; \ u=$$m.$(MAN_SECTION)$$_sfx; \ echo $(INSTALL) -m 644 $${d}$$_sfx $${t}$$_sfx;\ $(INSTALL) -m 644 $${d}$$_sfx $${t}$$_sfx; \ else \ echo $(INSTALL) -S $$u $${t}$$_sfx; \ $(INSTALL) -S $$u $${t}$$_sfx; \ fi; \ first=false; \ done; \ done ifeq ($(ENABLE_GETTEXT),yes) INSTALL_LINGUAS = \ @for l in $(LINGUAS) ""; do \ if test -f "$$l.mo" ; then \ ldir=$(PKG_LOCALE_DIR)/$$l/LC_MESSAGES; \ $(INSTALL) -m 755 -d $$ldir; \ $(INSTALL) -m 644 $$l.mo $$ldir/$(PKG_NAME).mo; \ fi; \ done endif MAN_MAKERULE = \ @for f in *.[12345678] ""; do \ if test ! -z "$$f"; then \ $(ZIP) --best -c < $$f > $$f.gz; \ fi; \ done xfsprogs-4.9.0+nmu1ubuntu2/include/buildrules0000644000000000000000000000530013063067172016211 0ustar # # Copyright (c) 1999, 2001-2003 Silicon Graphics, Inc. All Rights Reserved. # ifndef _BUILDRULES_INCLUDED_ _BUILDRULES_INCLUDED_ = 1 include $(TOPDIR)/include/builddefs clean clobber : $(addsuffix -clean,$(SUBDIRS)) @rm -f $(DIRT) .ltdep .dep @rm -fr $(DIRDIRT) %-clean: @echo "Cleaning $*" $(Q)$(MAKE) $(MAKEOPTS) -C $* clean ifdef HDR_SUBDIRS .PHONY: .xfs headers: $(addsuffix -headers, $(HDR_SUBDIRS)) %-headers: .xfs @echo " [HEADERS] $*" $(Q)$(MAKE) $(MAKEOPTS) -C $* NODEP=1 install-headers .xfs: @mkdir -p include/xfs endif # Never blow away subdirs ifdef SUBDIRS .PRECIOUS: $(SUBDIRS) .PHONY: $(SUBDIRS) $(SUBDIRS): @echo "Building $@" $(Q)$(MAKE) $(MAKEOPTS) -q -C $@ || $(MAKE) $(MAKEOPTS) -C $@ endif # # Standard targets # ifdef LTCOMMAND $(LTCOMMAND) : $(SUBDIRS) $(OBJECTS) $(LTDEPENDENCIES) @echo " [LD] $@" $(Q)$(LTLINK) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS) endif ifdef LTLIBRARY $(LTLIBRARY) : $(SUBDIRS) $(LTOBJECTS) @echo " [LD] $@" $(Q)$(LTLINK) $(LTLDFLAGS) -o $(LTLIBRARY) $(LTOBJECTS) $(LTLIBS) %.lo: %.c @echo " [CC] $@" $(Q)$(LTCOMPILE) -c $< else %.o: %.c @echo " [CC] $@" $(Q)$(CC) $(CFLAGS) -c $< endif ifdef POTHEAD $(POTHEAD): $(XGETTEXTFILES) @echo " [GETTXT] $@" $(Q)$(XGETTEXT) --language=C --keyword=_ --keyword=N_ -o $@ $(XGETTEXTFILES) # Update translations update-po: $(POTHEAD) $(wildcard $(TOPDIR)/po/*.po) catalogs="$(wildcard $(TOPDIR)/po/*.po)"; \ for cat in $$catalogs; do \ lang=`basename $$cat .po`; \ mv $$lang.po $$lang.old.po; \ echo "$$lang:"; \ if $(MSGMERGE) $$lang.old.po $(POTHEAD) -o $$lang.po; then \ rm -f $$lang.old.po; \ else \ echo "msgmerge for $$lang failed!"; \ rm -f $$lang.po; \ mv $$lang.old.po $$lang.po; \ fi; \ done %.mo: %.po @echo " [MSGFMT] $@" $(Q)$(MSGFMT) -c --statistics -o $@ $< endif endif # _BUILDRULES_INCLUDED_ $(_FORCE): # dependency build is automatic, relies on gcc -MM to generate. # # This is a bit messy. It regenerates the dependencies on each build so # that we catch files being added and removed. There are other ways of doing # this (e.g. per-file dependency files) but that requires more in-depth changes # to the build system. Compile time is not an issue for us, so the # rebuild on every make invocation isn't a problem we need to care about. Just # do it silently so it doesn't make the build unnecessarily noisy. .PHONY : depend ltdepend MAKEDEP := $(MAKEDEPEND) $(CFLAGS) ltdepend: rmltdep .ltdep rmltdep: $(Q)rm -f .ltdep .ltdep: $(CFILES) $(HFILES) $(Q)$(MAKEDEP) $(CFILES) | $(SED) -e 's,^\([^:]*\)\.o,\1.lo,' > .ltdep depend: rmdep .dep rmdep: $(Q)rm -f .dep .dep: $(CFILES) $(HFILES) $(Q)$(MAKEDEP) $(CFILES) > .dep xfsprogs-4.9.0+nmu1ubuntu2/include/cache.h0000644000000000000000000001156113063067172015336 0ustar /* * Copyright (c) 2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CACHE_H__ #define __CACHE_H__ /* * initialisation flags */ /* * xfs_db always writes changes immediately, and so we need to purge buffers * when we get a buffer lookup mismatch due to reading the same block with a * different buffer configuration. */ #define CACHE_MISCOMPARE_PURGE (1 << 0) /* * cache object campare return values */ enum { CACHE_HIT, CACHE_MISS, CACHE_PURGE, }; #define HASH_CACHE_RATIO 8 /* * Cache priorities range from BASE to MAX. * * For prefetch support, the top half of the range starts at * CACHE_PREFETCH_PRIORITY and everytime the buffer is fetched and is at or * above this priority level, it is reduced to below this level (refer to * libxfs_getbuf). * * If we have dirty nodes, we can't recycle them until they've been cleaned. To * keep these out of the reclaimable lists (as there can be lots of them) give * them their own priority that the shaker doesn't attempt to walk. */ #define CACHE_BASE_PRIORITY 0 #define CACHE_PREFETCH_PRIORITY 8 #define CACHE_MAX_PRIORITY 15 #define CACHE_DIRTY_PRIORITY (CACHE_MAX_PRIORITY + 1) #define CACHE_NR_PRIORITIES CACHE_DIRTY_PRIORITY /* * Simple, generic implementation of a cache (arbitrary data). * Provides a hash table with a capped number of cache entries. */ struct cache; struct cache_node; typedef void *cache_key_t; typedef void (*cache_walk_t)(struct cache_node *); typedef struct cache_node * (*cache_node_alloc_t)(cache_key_t); typedef int (*cache_node_flush_t)(struct cache_node *); typedef void (*cache_node_relse_t)(struct cache_node *); typedef unsigned int (*cache_node_hash_t)(cache_key_t, unsigned int, unsigned int); typedef int (*cache_node_compare_t)(struct cache_node *, cache_key_t); typedef unsigned int (*cache_bulk_relse_t)(struct cache *, struct list_head *); struct cache_operations { cache_node_hash_t hash; cache_node_alloc_t alloc; cache_node_flush_t flush; cache_node_relse_t relse; cache_node_compare_t compare; cache_bulk_relse_t bulkrelse; /* optional */ }; struct cache_hash { struct list_head ch_list; /* hash chain head */ unsigned int ch_count; /* hash chain length */ pthread_mutex_t ch_mutex; /* hash chain mutex */ }; struct cache_mru { struct list_head cm_list; /* MRU head */ unsigned int cm_count; /* MRU length */ pthread_mutex_t cm_mutex; /* MRU lock */ }; struct cache_node { struct list_head cn_hash; /* hash chain */ struct list_head cn_mru; /* MRU chain */ unsigned int cn_count; /* reference count */ unsigned int cn_hashidx; /* hash chain index */ int cn_priority; /* priority, -1 = free list */ int cn_old_priority;/* saved pre-dirty prio */ pthread_mutex_t cn_mutex; /* node mutex */ }; struct cache { int c_flags; /* behavioural flags */ unsigned int c_maxcount; /* max cache nodes */ unsigned int c_count; /* count of nodes */ pthread_mutex_t c_mutex; /* node count mutex */ cache_node_hash_t hash; /* node hash function */ cache_node_alloc_t alloc; /* allocation function */ cache_node_flush_t flush; /* flush dirty data function */ cache_node_relse_t relse; /* memory free function */ cache_node_compare_t compare; /* comparison routine */ cache_bulk_relse_t bulkrelse; /* bulk release routine */ unsigned int c_hashsize; /* hash bucket count */ unsigned int c_hashshift; /* hash key shift */ struct cache_hash *c_hash; /* hash table buckets */ struct cache_mru c_mrus[CACHE_DIRTY_PRIORITY + 1]; unsigned long long c_misses; /* cache misses */ unsigned long long c_hits; /* cache hits */ unsigned int c_max; /* max nodes ever used */ }; struct cache *cache_init(int, unsigned int, struct cache_operations *); void cache_destroy(struct cache *); void cache_walk(struct cache *, cache_walk_t); void cache_purge(struct cache *); void cache_flush(struct cache *); int cache_node_get(struct cache *, cache_key_t, struct cache_node **); void cache_node_put(struct cache *, struct cache_node *); void cache_node_set_priority(struct cache *, struct cache_node *, int); int cache_node_get_priority(struct cache_node *); int cache_node_purge(struct cache *, cache_key_t, struct cache_node *); void cache_report(FILE *fp, const char *, struct cache *); int cache_overflowed(struct cache *); #endif /* __CACHE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/command.h0000644000000000000000000000370313063067172015710 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __COMMAND_H__ #define __COMMAND_H__ #include #define CMD_FLAG_GLOBAL (1<<31) /* don't iterate "args" */ #define CMD_FLAG_FOREIGN_OK (1<<30) /* command not restricted to XFS */ typedef int (*cfunc_t)(int argc, char **argv); typedef void (*helpfunc_t)(void); typedef struct cmdinfo { const char *name; const char *altname; cfunc_t cfunc; int argmin; int argmax; int canpush; int flags; const char *args; const char *oneline; helpfunc_t help; } cmdinfo_t; extern cmdinfo_t *cmdtab; extern int ncmds; extern void help_init(void); extern void quit_init(void); typedef int (*argsfunc_t)(int index); typedef int (*checkfunc_t)(const cmdinfo_t *ci); extern void add_command(const cmdinfo_t *ci); extern void add_user_command(char *optarg); extern void add_args_command(argsfunc_t af); extern void add_check_command(checkfunc_t cf); extern const cmdinfo_t *find_command(const char *cmd); extern void command_loop(void); extern int command_usage(const cmdinfo_t *ci); extern int command(const cmdinfo_t *ci, int argc, char **argv); extern void report_io_times(const char *verb, struct timeval *t2, long long offset, long long count, long long total, int ops, int compact); #endif /* __COMMAND_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/darwin.h0000644000000000000000000001765713136024635015571 0ustar /* * Copyright (c) 2004-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_DARWIN_H__ #define __XFS_DARWIN_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include # ifndef SYS_fsctl # define SYS_fsctl 242 # endif #ifndef XATTR_LIST_MAX #define XATTR_LIST_MAX 65536 #endif static __inline__ int xfsctl(const char *path, int fd, int cmd, void *p) { return syscall(SYS_fsctl, path, cmd, p, 0); } static __inline__ int platform_test_xfs_fd(int fd) { struct statfs buf; if (fstatfs(fd, &buf) < 0) return 0; return strncmp(buf.f_fstypename, "xfs", 4) == 0; } static __inline__ int platform_test_xfs_path(const char *path) { struct statfs buf; if (statfs(path, &buf) < 0) return 0; return strncmp(buf.f_fstypename, "xfs", 4) == 0; } static __inline__ int platform_fstatfs(int fd, struct statfs *buf) { return fstatfs(fd, buf); } static __inline__ void platform_getoptreset(void) { extern int optreset; optreset = 0; } static __inline__ int platform_uuid_compare(uuid_t *uu1, uuid_t *uu2) { return uuid_compare(*uu1, *uu2); } static __inline__ void platform_uuid_unparse(uuid_t *uu, char *buffer) { uuid_unparse(*uu, buffer); } static __inline__ int platform_uuid_parse(char *buffer, uuid_t *uu) { return uuid_parse(buffer, *uu); } static __inline__ int platform_uuid_is_null(uuid_t *uu) { return uuid_is_null(*uu); } static __inline__ void platform_uuid_generate(uuid_t *uu) { uuid_generate(*uu); } static __inline__ void platform_uuid_clear(uuid_t *uu) { uuid_clear(*uu); } static __inline__ void platform_uuid_copy(uuid_t *dst, uuid_t *src) { uuid_copy(*dst, *src); } typedef unsigned char __u8; typedef signed char __s8; typedef unsigned short __u16; typedef signed short __s16; typedef unsigned int __u32; typedef signed int __s32; typedef unsigned long long int __u64; typedef signed long long int __s64; #define __int8_t int8_t #define __int16_t int16_t #define __int32_t int32_t #define __int32_t int32_t #define __int64_t int64_t #define __uint8_t u_int8_t #define __uint16_t u_int16_t #define __uint32_t u_int32_t #define __uint64_t u_int64_t typedef off_t xfs_off_t; typedef u_int64_t xfs_ino_t; typedef u_int32_t xfs_dev_t; typedef int64_t xfs_daddr_t; typedef __u32 xfs_nlink_t; #define fdatasync fsync #define memalign(a,sz) valloc(sz) #define O_LARGEFILE 0 #ifndef O_DIRECT #define O_DIRECT 0 #endif #ifndef O_SYNC #define O_SYNC 0 #endif #define EFSCORRUPTED 990 /* Filesystem is corrupted */ #define EFSBADCRC 991 /* Bad CRC detected */ #define HAVE_FID 1 static __inline__ int platform_discard_blocks(int fd, uint64_t start, uint64_t len) { return 0; } /* * POSIX timer replacement. * It really just do the minimum we need for xfs_repair. * Also, as setitimer can't create multiple timers, * the timerid things are useless - we have only one ITIMER_REAL * timer. */ #define CLOCK_REALTIME ITIMER_REAL #define itimerspec itimerval typedef uint64_t timer_t; typedef double timer_c; typedef clock_id_t clockid_t; static inline int timer_create (clockid_t __clock_id, struct sigevent *__restrict __evp, timer_t *__restrict timer) { // set something, to initialize the variable, just in case *timer = 0; return 0; } static inline int timer_settime (timer_t timerid, int flags, const struct itimerspec *__restrict timerspec, struct itimerspec *__restrict ovalue) { return setitimer(ITIMER_REAL, timerspec, ovalue); } static inline int timer_delete (timer_t timerid) { struct itimerspec timespec; timespec.it_interval.tv_sec=0; timespec.it_interval.tv_usec=0; timespec.it_value.tv_sec=0; timespec.it_value.tv_usec=0; return setitimer(ITIMER_REAL, ×pec, NULL); } static inline int timer_gettime (timer_t timerid, struct itimerspec *value) { return getitimer(ITIMER_REAL, value); } /* FSR */ # include # include #include #include #define _PATH_MOUNTED "/etc/mtab" struct mntent { char *mnt_fsname; char *mnt_dir; char *mnt_type; char *mnt_opts; int mnt_freq; int mnt_passno; }; static inline void mntinfo2mntent (struct statfs * stats, struct mntent * mnt) { mnt->mnt_fsname = stats->f_mntfromname; mnt->mnt_dir = stats->f_mntonname; mnt->mnt_type = stats->f_fstypename; } /** * Abstraction of mountpoints. */ struct mntent_cursor { FILE *mtabp; struct statfs *stats; int count; int i; }; /** * OS X uses getmntinfo, which doesn't use a mtab file. So we just ignore it. */ static inline int platform_mntent_open(struct mntent_cursor * cursor, char *mtab) { if ((cursor->count = getmntinfo(&cursor->stats, 0)) < 0) { fprintf(stderr, "Error: getmntinfo() failed: %s\n", strerror(errno)); return 1; } cursor->i = 0; return 0; } static inline struct mntent * platform_mntent_next(struct mntent_cursor * cursor) { struct mntent * t = NULL; if (cursor->i >= cursor->count){ return NULL; } mntinfo2mntent(&cursor->stats[cursor->i], t); cursor->i++; return t; } static inline void platform_mntent_close(struct mntent_cursor * cursor) { cursor->count = 0; cursor->i = 0; } /* check whether we have to define FS_IOC_FS[GS]ETXATTR ourselves */ #ifndef HAVE_FSXATTR struct fsxattr { __u32 fsx_xflags; /* xflags field value (get/set) */ __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ unsigned char fsx_pad[8]; }; /* * Flags for the fsx_xflags field */ #define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */ #define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */ #define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */ #define FS_XFLAG_APPEND 0x00000010 /* all writes append */ #define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */ #define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */ #define FS_XFLAG_NODUMP 0x00000080 /* do not include in backups */ #define FS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ #define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ #define FS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ #define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ #define FS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) #define FS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) #endif #ifndef FS_XFLAG_COWEXTSIZE #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ #endif #endif /* __XFS_DARWIN_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/freebsd.h0000644000000000000000000001306613136024635015705 0ustar /* * Copyright (c) 2004-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_FREEBSD_H__ #define __XFS_FREEBSD_H__ #include #include #include #include #include #include #include #include #include #include #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN /* FreeBSD file API is 64-bit aware */ #define fdatasync fsync #define memalign(a,sz) valloc(sz) #define EFSCORRUPTED 990 /* Filesystem is corrupted */ #define EFSBADCRC 991 /* Bad CRC detected */ typedef unsigned char __u8; typedef signed char __s8; typedef unsigned short __u16; typedef signed short __s16; typedef unsigned int __u32; typedef signed int __s32; typedef unsigned long long int __u64; typedef signed long long int __s64; typedef off_t xfs_off_t; typedef __uint64_t xfs_ino_t; typedef __uint32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; typedef __u32 xfs_nlink_t; #define O_LARGEFILE 0 #define HAVE_FID 1 static __inline__ int xfsctl(const char *path, int fd, int cmd, void *p) { return ioctl(fd, cmd, p); } static __inline__ int platform_test_xfs_fd(int fd) { struct statfs buf; if (fstatfs(fd, &buf) < 0) return 0; return strncmp(buf.f_fstypename, "xfs", 4) == 0; } static __inline__ int platform_test_xfs_path(const char *path) { struct statfs buf; if (statfs(path, &buf) < 0) return 0; return strncmp(buf.f_fstypename, "xfs", 4) == 0; } static __inline__ int platform_fstatfs(int fd, struct statfs *buf) { return fstatfs(fd, buf); } static __inline__ void platform_getoptreset(void) { extern int optind; optind = 0; } static __inline__ int platform_uuid_compare(uuid_t *uu1, uuid_t *uu2) { return uuid_compare(uu1, uu2, NULL); } static __inline__ void platform_uuid_unparse(uuid_t *uu, char *buffer) { uint32_t status; char *s; uuid_to_string(uu, &s, &status); if (status == uuid_s_ok) strcpy(buffer, s); else buffer[0] = '\0'; free(s); } static __inline__ int platform_uuid_parse(char *buffer, uuid_t *uu) { uint32_t status; uuid_from_string(buffer, uu, &status); return (status == uuid_s_ok); } static __inline__ int platform_uuid_is_null(uuid_t *uu) { return uuid_is_nil(uu, NULL); } static __inline__ void platform_uuid_generate(uuid_t *uu) { uuid_create(uu, NULL); } static __inline__ void platform_uuid_clear(uuid_t *uu) { uuid_create_nil(uu, NULL); } static __inline__ void platform_uuid_copy(uuid_t *dst, uuid_t *src) { memcpy(dst, src, sizeof(uuid_t)); } static __inline__ int platform_discard_blocks(int fd, uint64_t start, uint64_t len) { return 0; } /** * Abstraction of mountpoints. */ struct mntent_cursor { FILE *mtabp; }; static inline int platform_mntent_open(struct mntent_cursor * cursor, char *mtab) { cursor->mtabp = setmntent(mtab, "r"); if (!cursor->mtabp) { fprintf(stderr, "Error: cannot read %s\n", mtab); return 1; } return 0; } static inline struct mntent * platform_mntent_next(struct mntent_cursor * cursor) { return getmntent(cursor->mtabp); } static inline void platform_mntent_close(struct mntent_cursor * cursor) { endmntent(cursor->mtabp); } /* check whether we have to define FS_IOC_FS[GS]ETXATTR ourselves */ #ifndef HAVE_FSXATTR struct fsxattr { __u32 fsx_xflags; /* xflags field value (get/set) */ __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ unsigned char fsx_pad[8]; }; /* * Flags for the fsx_xflags field */ #define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */ #define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */ #define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */ #define FS_XFLAG_APPEND 0x00000010 /* all writes append */ #define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */ #define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */ #define FS_XFLAG_NODUMP 0x00000080 /* do not include in backups */ #define FS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ #define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ #define FS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ #define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ #define FS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) #define FS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) #endif #ifndef FS_XFLAG_COWEXTSIZE #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ #endif #endif /* __XFS_FREEBSD_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/gnukfreebsd.h0000644000000000000000000000677313063067172016603 0ustar /* * Copyright (c) 2004-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_KFREEBSD_H__ #define __XFS_KFREEBSD_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define EFSCORRUPTED 990 /* Filesystem is corrupted */ #define EFSBADCRC 991 /* Bad CRC detected */ typedef unsigned char __u8; typedef signed char __s8; typedef unsigned short __u16; typedef signed short __s16; typedef unsigned int __u32; typedef signed int __s32; typedef unsigned long long int __u64; typedef signed long long int __s64; typedef off_t xfs_off_t; typedef __uint64_t xfs_ino_t; typedef __uint32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; typedef __u32 xfs_nlink_t; #define HAVE_FID 1 static __inline__ int xfsctl(const char *path, int fd, int cmd, void *p) { return ioctl(fd, cmd, p); } static __inline__ int platform_test_xfs_fd(int fd) { struct statfs buf; if (fstatfs(fd, &buf) < 0) return 0; return strncmp(buf.f_fstypename, "xfs", 4) == 0; } static __inline__ int platform_test_xfs_path(const char *path) { struct statfs buf; if (statfs(path, &buf) < 0) return 0; return strncmp(buf.f_fstypename, "xfs", 4) == 0; } static __inline__ int platform_fstatfs(int fd, struct statfs *buf) { return fstatfs(fd, buf); } static __inline__ void platform_getoptreset(void) { extern int optind; optind = 0; } static __inline__ int platform_uuid_compare(uuid_t *uu1, uuid_t *uu2) { return uuid_compare(*uu1, *uu2); } static __inline__ void platform_uuid_unparse(uuid_t *uu, char *buffer) { uuid_unparse(*uu, buffer); } static __inline__ int platform_uuid_parse(char *buffer, uuid_t *uu) { return uuid_parse(buffer, *uu); } static __inline__ int platform_uuid_is_null(uuid_t *uu) { return uuid_is_null(*uu); } static __inline__ void platform_uuid_generate(uuid_t *uu) { uuid_generate(*uu); } static __inline__ void platform_uuid_clear(uuid_t *uu) { uuid_clear(*uu); } static __inline__ void platform_uuid_copy(uuid_t *dst, uuid_t *src) { uuid_copy(*dst, *src); } static __inline__ int platform_discard_blocks(int fd, uint64_t start, uint64_t len) { return 0; } /** * Abstraction of mountpoints. */ struct mntent_cursor { FILE *mtabp; }; static inline int platform_mntent_open(struct mntent_cursor * cursor, char *mtab) { cursor->mtabp = setmntent(mtab, "r"); if (!cursor->mtabp) { fprintf(stderr, "Error: cannot read %s\n", mtab); return 1; } return 0; } static inline struct mntent * platform_mntent_next(struct mntent_cursor * cursor) { return getmntent(cursor->mtabp); } static inline void platform_mntent_close(struct mntent_cursor * cursor) { endmntent(cursor->mtabp); } #endif /* __XFS_KFREEBSD_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/handle.h0000644000000000000000000000422613063067172015526 0ustar /* * Copyright (c) 1995, 2001-2003, 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __HANDLE_H__ #define __HANDLE_H__ #ifdef __cplusplus extern "C" { #endif struct fsdmidata; struct attrlist_cursor; struct parent; extern int path_to_handle (char *__path, void **__hanp, size_t *__hlen); extern int path_to_fshandle (char *__path, void **__fshanp, size_t *__fshlen); extern int fd_to_handle (int fd, void **hanp, size_t *hlen); extern int handle_to_fshandle (void *__hanp, size_t __hlen, void **__fshanp, size_t *__fshlen); extern void free_handle (void *__hanp, size_t __hlen); extern int open_by_fshandle (void *__fshanp, size_t __fshlen, int __rw); extern int open_by_handle (void *__hanp, size_t __hlen, int __rw); extern int readlink_by_handle (void *__hanp, size_t __hlen, void *__buf, size_t __bs); extern int attr_multi_by_handle (void *__hanp, size_t __hlen, void *__buf, int __rtrvcnt, int __flags); extern int attr_list_by_handle (void *__hanp, size_t __hlen, void *__buf, size_t __bufsize, int __flags, struct attrlist_cursor *__cursor); extern int parents_by_handle(void *__hanp, size_t __hlen, struct parent *__buf, size_t __bufsize, unsigned int *__count); extern int parentpaths_by_handle(void *__hanp, size_t __hlen, struct parent *__buf, size_t __bufsize, unsigned int *__count); extern int fssetdm_by_handle (void *__hanp, size_t __hlen, struct fsdmidata *__fsdmi); #ifdef __cplusplus } #endif #endif /* __HANDLE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/hlist.h0000644000000000000000000000402313063067172015411 0ustar /* * double-linked hash list with single head implementation taken from linux * kernel headers as of 2.6.38-rc1. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __HLIST_H__ #define __HLIST_H__ struct hlist_node { struct hlist_node *next; struct hlist_node **pprev; }; struct hlist_head { struct hlist_node *first; }; #define HLIST_HEAD_INIT { .first = NULL } static inline void INIT_HLIST_NODE(struct hlist_node *h) { h->next = NULL; h->pprev = NULL; } static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; if (first) first->pprev = &n->next; h->first = n; n->pprev = &h->first; } static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; *pprev = next; if (next) next->pprev = pprev; } static inline void hlist_del(struct hlist_node *n) { __hlist_del(n); } #define hlist_entry(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #define hlist_for_each(pos, head) \ for (pos = (head)->first; pos; pos = pos->next) #define hlist_for_each_entry(tpos, pos, head, member) \ for (pos = (head)->first; \ pos && ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = pos->next) #endif /* __LIST_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/input.h0000644000000000000000000000363213063067172015432 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __INPUT_H__ #define __INPUT_H__ #include #include #include #include "project.h" #include extern char **breakline(char *input, int *count); extern void doneline(char *input, char **vec); extern char *fetchline(void); extern long long cvtnum(size_t blocksize, size_t sectorsize, char *s); extern void cvtstr(double value, char *str, size_t sz); extern unsigned long cvttime(char *s); extern struct timeval tadd(struct timeval t1, struct timeval t2); extern struct timeval tsub(struct timeval t1, struct timeval t2); extern double tdiv(double value, struct timeval tv); enum { DEFAULT_TIME = 0x0, TERSE_FIXED_TIME = 0x1, VERBOSE_FIXED_TIME = 0x2 }; extern void timestr(struct timeval *tv, char *str, size_t sz, int flags); extern uid_t uid_from_string(char *user); extern gid_t gid_from_string(char *group); extern prid_t prid_from_string(char *project); extern bool isdigits_only(const char *str); #define HAVE_FTW_H 1 /* TODO: configure me */ #ifdef HAVE_FTW_H #include #else struct FTW; struct stat; extern int nftw( char *dir, int (*fn)(const char *, const struct stat *, int, struct FTW *), int depth, int flags); #endif #endif /* __INPUT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/install-sh0000755000000000000000000001544513063067172016133 0ustar #! /bin/bash # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # # This script emulates bsd install and also recognises # two environment variables, with the following semantics :- # # $DIST_MANIFEST - if set, the name of the file to append manifest # information in the following format: # File : f mode owner group src target # Directory: d mode owner group target # Symlink : l linkval target # # $DIST_ROOT - if set, prepend to target # # The sematics of all combinations of these two variables # are as follows: # # $DIST_MANIFEST? $DIST_ROOT? | Copy? Append Manifest? # -----------------------------+-------------------------- # not set not set | yes no # not set set | yes no # set not set | no yes # set set | yes yes # _usage() { echo "Usage: $prog [-o owner] [-g group] [-m mode] -d directory" echo "or $prog [-D] [-o owner] [-g group] [-m mode] file directory/file" echo "or $prog [-o owner] [-g group] [-m mode] file [file ...] directory" echo "or $prog -S file target (creates \"target\" symlink)" echo "or $prog -T lt_arg [-o owner] [-g group] [-m mode] libtool.lai directory" echo "" echo "The \$DIST_MANIFEST and \$DIST_ROOT environment variables affect the" echo "behaviour of this command - see comments in the script." echo "The -D flag is only available for the second usage, and causes" echo "the target directory to be created before installing the file." echo "" exit 1 } _chown () { _st=255 if [ $# -eq 3 ] ; then chown $1:$2 $3 _st=$? if [ $_st -ne 0 ] ; then if [ $REAL_UID != '0' ] ; then if [ ! -f $DIST_ROOT/.chown.quiet ] ; then echo '===============================================' echo Ownership of files under ${DIST_ROOT:-/} echo cannot be changed echo '===============================================' if [ -n "$DIST_ROOT" ] ; then touch $DIST_ROOT/.chown.quiet fi fi _st=0 fi fi fi return $_st } _manifest () { echo $* | sed -e 's/\/\//\//g' >>${DIST_MANIFEST:-/dev/null} } prog=`basename $0` HERE=`pwd` dflag=false Dflag=false Sflag=false Tflag=false DIRMODE=755 FILEMODE=644 OWNER=`id -u` GROUP=`id -g` REAL_UID=$OWNER # default is to install and don't append manifest INSTALL=true MANIFEST=: : ${DIST_ROOT:=${DESTDIR}} [ -n "$DIST_MANIFEST" -a -z "$DIST_ROOT" ] && INSTALL=false [ -n "$DIST_MANIFEST" ] && MANIFEST="_manifest" [ $# -eq 0 ] && _usage if $INSTALL then CP=cp; LN=ln; MKDIR=mkdir; CHMOD=chmod; CHOWN=_chown else CP=true; LN=true; MKDIR=true; CHMOD=true; CHOWN=true fi [ -n "$DIST_ROOT" -a $REAL_UID -ne 0 ] && CHOWN=true while getopts "Dcm:d:S:o:g:T:" c $* do case $c in c) ;; g) GROUP=$OPTARG ;; o) OWNER=$OPTARG ;; m) DIRMODE=`expr $OPTARG` FILEMODE=$DIRMODE ;; D) Dflag=true ;; S) symlink=$OPTARG Sflag=true ;; d) dir=$DIST_ROOT/$OPTARG dflag=true ;; T) lt_install=$OPTARG Tflag=true ;; *) _usage ;; esac done shift `expr $OPTIND - 1` status=0 if $dflag then # # first usage # $MKDIR -p $dir status=$? if [ $status -eq 0 ] then $CHMOD $DIRMODE $dir status=$? fi if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST d $DIRMODE $OWNER $GROUP ${dir#$DIST_ROOT} elif $Sflag then # # fourth usage (symlink) # if [ $# -ne 1 ] then _usage else target=$DIST_ROOT/$1 fi $LN -s -f $symlink $target status=$? $MANIFEST l $symlink ${target#$DIST_ROOT} elif $Tflag then # # -T (install libs built by libtool) # if [ $# -ne 2 ] then _usage else libtool_lai=$1 # source the libtool variables if [ ! -f $libtool_lai ] then echo "$prog: Unable to find libtool library file $libtool_lai" exit 2 fi . ./$libtool_lai target=$DIST_ROOT/$2 fi case $lt_install in so_dot_version) # Loop until we find libfoo.so.x.y.z, then break out. for solib in $library_names do # does it have enough parts? libfoo.so.x.y.z == 5 cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq 5 ] then install_name=$target/$solib $CP $solib $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$solib ${install_name#$DIST_ROOT} break fi done ;; so_*) case $lt_install in so_dot_current) # ln -s libfoo.so.x.y.z to libfoo.so.x from_parts=5 # libfoo.so.x.y.z to_parts=3 # libfoo.so.x ;; so_base) # ln -s libfoo.so.x to libfoo.so from_parts=3 # libfoo.so.x to_parts=2 # libfoo.so ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac # Loop until we find the names, then break out. for solib in $library_names do # does it have enough parts? cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq $from_parts ] then from_name=$solib elif [ $cnt -eq $to_parts ] then to_name=$solib fi if [ -n "$from_name" ] && [ -n "$to_name" ] then install_name=$target/$to_name $LN -s -f $from_name $install_name status=$? $MANIFEST l $from_name ${install_name#$DIST_ROOT} break fi done ;; old_lib) install_name=$target/$old_library $CP $old_library $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$old_library ${install_name#$DIST_ROOT} ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac case $lt_install in old_lib|so_dot_version) if [ $status -eq 0 ] then $CHMOD $FILEMODE $install_name $CHOWN $OWNER $GROUP $install_name fi ;; esac else list="" dir="" if [ $# -eq 2 ] then # # second usage # f=$1 dir=$DIST_ROOT/$2 if $Dflag then mkdir -p `dirname $dir` fi $CP $f $dir status=$? if [ $status -eq 0 ] then if [ -f $dir/$f ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f else $CHMOD $FILEMODE $dir status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$dir ${dir#$DIST_ROOT} fi fi else # # third usage # n=1 while [ $# -gt 0 ] do if [ $# -gt 1 ] then list="$list $1" else dir=$DIST_ROOT/$1 fi shift done # echo DIR=$dir list=\"$list\" for f in $list do $CP $f $dir status=$? if [ $status -eq 0 ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f fi [ $status -ne 0 ] && break done fi fi exit $status xfsprogs-4.9.0+nmu1ubuntu2/include/irix.h0000644000000000000000000003546213136024635015252 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_IRIX_H__ #define __XFS_IRIX_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __int8_t char #define __int16_t short #define __uint8_t unsigned char #define __uint16_t unsigned short typedef unsigned char __u8; typedef signed char __s8; typedef unsigned short __u16; typedef signed short __s16; typedef unsigned int __u32; typedef signed int __s32; typedef unsigned long long int __u64; typedef signed long long int __s64; typedef off_t xfs_off_t; typedef __int64_t xfs_ino_t; typedef __int32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; typedef __u32 xfs_nlink_t; #define xfs_flock64 flock64 #define xfs_flock64_t struct flock64 #define EFSBADCRC 991 /* Bad CRC detected */ typedef struct xfs_error_injection { __int32_t fd; __int32_t errtag; } xfs_error_injection_t; /* --- xfs_fsop_*req - request data structures --- */ typedef struct xfs_fsop_bulkreq { ino64_t *lastip; __int32_t icount; xfs_bstat_t *ubuffer; __int32_t *ocount; } xfs_fsop_bulkreq_t; typedef struct xfs_fsop_handlereq { __u32 fd; /* fd for FD_TO_HANDLE */ void *path; /* user pathname */ __u32 oflags; /* open flags */ void *ihandle; /* user supplied handle */ __u32 ihandlen; /* user supplied length */ void *ohandle; /* user buffer for handle */ __u32 *ohandlen; /* user buffer length */ } xfs_fsop_handlereq_t; typedef struct xfs_fsop_setdm_handlereq { struct xfs_fsop_handlereq hreq; /* handle information */ struct fsdmidata *data; /* DMAPI data */ } xfs_fsop_setdm_handlereq_t; typedef struct xfs_attrlist_cursor { __u32 opaque[4]; } xfs_attrlist_cursor_t; typedef struct xfs_fsop_attrlist_handlereq { struct xfs_fsop_handlereq hreq; /* handle interface structure */ struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */ __u32 flags; /* which namespace to use */ __u32 buflen; /* length of buffer supplied */ void *buffer; /* returned names */ } xfs_fsop_attrlist_handlereq_t; typedef struct xfs_fsop_getparents_handlereq { struct xfs_fsop_handlereq hreq; /* handle interface structure */ struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */ __u32 buflen; /* length of buffer supplied */ void *buffer; /* returned data */ __u32 *ocount; /* return number of links */ __u32 *omore; /* return whether more to come */ } xfs_fsop_getparents_handlereq_t; typedef struct xfs_attr_multiop { __u32 am_opcode; __s32 am_error; void *am_attrname; void *am_attrvalue; __u32 am_length; __u32 am_flags; } xfs_attr_multiop_t; typedef struct xfs_fsop_attrmulti_handlereq { struct xfs_fsop_handlereq hreq; /* handle interface structure */ __u32 opcount;/* count of following multiop */ struct xfs_attr_multiop *ops; /* attr_multi data */ } xfs_fsop_attrmulti_handlereq_t; /* start doing packed stuctures here */ #define HAVE_FORMAT32 1 #pragma pack 1 typedef struct xfs_inode_log_format_32 { __u16 ilf_type; /* inode log item type */ __u16 ilf_size; /* size of this item */ __u32 ilf_fields; /* flags for fields logged */ __u16 ilf_asize; /* size of attr d/ext/root */ __u16 ilf_dsize; /* size of data/ext/root */ __u64 ilf_ino; /* inode number */ union { __u32 ilfu_rdev; /* rdev value for dev inode*/ uuid_t ilfu_uuid; /* mount point value */ } ilf_u; __s64 ilf_blkno; /* blkno of inode buffer */ __s32 ilf_len; /* len of inode buffer */ __s32 ilf_boffset; /* off of inode in buffer */ } xfs_inode_log_format_32_t; typedef struct xfs_extent_32 { __u64 ext_start; __u32 ext_len; } xfs_extent_32_t; typedef struct xfs_efi_log_format_32 { __u16 efi_type; /* efi log item type */ __u16 efi_size; /* size of this item */ __u32 efi_nextents; /* # extents to free */ __u64 efi_id; /* efi identifier */ xfs_extent_32_t efi_extents[1]; /* array of extents to free */ } xfs_efi_log_format_32_t; typedef struct xfs_efd_log_format_32 { __u16 efd_type; /* efd log item type */ __u16 efd_size; /* size of this item */ __u32 efd_nextents; /* # of extents freed */ __u64 efd_efi_id; /* id of corresponding efi */ xfs_extent_32_t efd_extents[1]; /* array of extents freed */ } xfs_efd_log_format_32_t; #pragma pack 0 /* end of packed stuctures */ #include #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN /* Map some gcc macros for the MipsPRO compiler */ #ifndef __GNUC__ #define __builtin_constant_p(x) (0) #define __FUNCTION__ "XFS" #define __sgi__ __sgi #define __inline__ __inline #define inline __inline #endif /*ARGSUSED*/ static __inline__ int xfsctl(const char *path, int fd, int cmd, void *arg) { if (cmd >= 0 && cmd < XFS_FSOPS_COUNT) { /* * We have a problem in that xfsctl takes 1 arg but * some sgi xfs ops take an input arg and/or an output arg * So have to special case the ops to decide if xfsctl arg * is an input or an output argument. */ if (cmd == XFS_FS_GOINGDOWN) return syssgi(SGI_XFS_FSOPERATIONS, fd, cmd, arg, 0); return syssgi(SGI_XFS_FSOPERATIONS, fd, cmd, 0, arg); } switch (cmd) { case SGI_FS_INUMBERS: case SGI_FS_BULKSTAT: return syssgi(cmd, fd, ((xfs_fsop_bulkreq_t*)arg)->lastip, ((xfs_fsop_bulkreq_t*)arg)->icount, ((xfs_fsop_bulkreq_t*)arg)->ubuffer, ((xfs_fsop_bulkreq_t*)arg)->ocount); case SGI_FS_BULKSTAT_SINGLE: return syssgi(SGI_FS_BULKSTAT_SINGLE, fd, ((xfs_fsop_bulkreq_t*)arg)->lastip, ((xfs_fsop_bulkreq_t*)arg)->ubuffer); case SGI_XFS_INJECT_ERROR: return syssgi(SGI_XFS_INJECT_ERROR, ((xfs_error_injection_t*)arg)->errtag, fd); case SGI_XFS_CLEARALL_ERROR: return syssgi(SGI_XFS_CLEARALL_ERROR, fd); case SGI_PATH_TO_HANDLE: case SGI_PATH_TO_FSHANDLE: return syssgi(cmd, ((xfs_fsop_handlereq_t*)arg)->path, ((xfs_fsop_handlereq_t*)arg)->ohandle, ((xfs_fsop_handlereq_t*)arg)->ohandlen); case SGI_FD_TO_HANDLE: return syssgi(cmd, ((xfs_fsop_handlereq_t*)arg)->fd, ((xfs_fsop_handlereq_t*)arg)->ohandle, ((xfs_fsop_handlereq_t*)arg)->ohandlen); case SGI_OPEN_BY_HANDLE: return syssgi(cmd, ((xfs_fsop_handlereq_t*)arg)->ihandle, ((xfs_fsop_handlereq_t*)arg)->ihandlen, ((xfs_fsop_handlereq_t*)arg)->oflags); case SGI_READLINK_BY_HANDLE: return syssgi(cmd, ((xfs_fsop_handlereq_t*)arg)->ihandle, ((xfs_fsop_handlereq_t*)arg)->ihandlen, ((xfs_fsop_handlereq_t*)arg)->ohandle, ((xfs_fsop_handlereq_t*)arg)->ohandlen); case SGI_ATTR_LIST_BY_HANDLE: return syssgi(cmd, ((xfs_fsop_attrlist_handlereq_t*)arg)->hreq.ihandle, ((xfs_fsop_attrlist_handlereq_t*)arg)->hreq.ihandlen, ((xfs_fsop_attrlist_handlereq_t*)arg)->buffer, ((xfs_fsop_attrlist_handlereq_t*)arg)->buflen, ((xfs_fsop_attrlist_handlereq_t*)arg)->flags, &(((xfs_fsop_attrlist_handlereq_t*)arg)->pos)); case SGI_XFS_GETPARENTS: case SGI_XFS_GETPARENTPATHS: return syssgi(cmd, ((xfs_fsop_getparents_handlereq_t*)arg)->hreq.ihandle, ((xfs_fsop_getparents_handlereq_t*)arg)->hreq.ihandlen, ((xfs_fsop_getparents_handlereq_t*)arg)->buffer, ((xfs_fsop_getparents_handlereq_t*)arg)->buflen, &(((xfs_fsop_getparents_handlereq_t*)arg)->pos), ((xfs_fsop_getparents_handlereq_t*)arg)->ocount, ((xfs_fsop_getparents_handlereq_t*)arg)->omore); case SGI_ATTR_MULTI_BY_HANDLE: return syssgi(cmd, ((xfs_fsop_attrmulti_handlereq_t*)arg)->hreq.ihandle, ((xfs_fsop_attrmulti_handlereq_t*)arg)->hreq.ihandlen, ((xfs_fsop_attrmulti_handlereq_t*)arg)->ops, ((xfs_fsop_attrmulti_handlereq_t*)arg)->opcount, ((xfs_fsop_attrmulti_handlereq_t*)arg)->hreq.oflags); case SGI_FSSETDM_BY_HANDLE: return syssgi(cmd, ((xfs_fsop_setdm_handlereq_t*)arg)->hreq.ihandle, ((xfs_fsop_setdm_handlereq_t*)arg)->hreq.ihandlen, ((xfs_fsop_setdm_handlereq_t*)arg)->data); } return fcntl(fd, cmd, arg); } static __inline__ int platform_test_xfs_fd(int fd) { struct statvfs sbuf; if (fstatvfs(fd, &sbuf) < 0) return 0; return strncmp(sbuf.f_basetype, "xfs", 4) == 0; } static __inline__ int platform_test_xfs_path(const char *path) { struct statvfs sbuf; if (statvfs(path, &sbuf) < 0) return 0; return strncmp(sbuf.f_basetype, "xfs", 4) == 0; } static __inline__ int platform_fstatfs(int fd, struct statfs *buf) { return fstatfs(fd, buf, sizeof(struct statfs), 0); } static __inline__ void platform_getoptreset(void) { getoptreset(); } static __inline__ int platform_uuid_compare(uuid_t *uu1, uuid_t *uu2) { __uint32_t status; return uuid_compare(uu1, uu2, &status); } static __inline__ void platform_uuid_unparse(uuid_t *uu, char *buffer) { __uint32_t status; char *s; uuid_to_string(uu, &s, &status); if (status == uuid_s_ok) strcpy(buffer, s); else buffer[0] = '\0'; free(s); } static __inline__ int platform_uuid_parse(char *buffer, uuid_t *uu) { __uint32_t status; uuid_from_string(buffer, uu, &status); return (status == uuid_s_ok); } static __inline__ int platform_uuid_is_null(uuid_t *uu) { uint status; return uuid_is_nil(uu, &status); } static __inline__ void platform_uuid_generate(uuid_t *uu) { __uint32_t status; uuid_create(uu, &status); } static __inline__ void platform_uuid_clear(uuid_t *uu) { __uint32_t status; uuid_create_nil(uu, &status); } static __inline__ void platform_uuid_copy(uuid_t *dst, uuid_t *src) { memcpy(dst, src, sizeof(uuid_t)); } static __inline__ int platform_discard_blocks(int fd, uint64_t start, uint64_t len) { return 0; } static __inline__ char * strsep(char **s, const char *ct) { char *sbegin = *s, *end; if (!sbegin) return NULL; end = strpbrk(sbegin, ct); if (end) *end++ = '\0'; *s = end; return sbegin; } #define HAVE_DIOATTR 1 #define HAVE_FSXATTR 1 #define HAVE_GETBMAP 1 #define HAVE_GETBMAPX 1 #define HAVE_FSDMIDATA 1 #define HAVE_FID 1 #define HAVE_IOCMACROS 1 #define HAVE_BBMACROS 1 #define __XFS_FS_H__ 1 #define XFS_IOC_DIOINFO F_DIOINFO #define XFS_IOC_ALLOCSP64 F_ALLOCSP64 #define XFS_IOC_FREESP64 F_FREESP64 #define XFS_IOC_GETBMAP F_GETBMAP #define XFS_IOC_FSSETDM F_FSSETDM #define XFS_IOC_RESVSP F_RESVSP #define XFS_IOC_RESVSP64 F_RESVSP64 #define XFS_IOC_UNRESVSP F_UNRESVSP #define XFS_IOC_UNRESVSP64 F_UNRESVSP64 #define XFS_IOC_GETBMAPA F_GETBMAPA #define XFS_IOC_FSGETXATTRA F_FSGETXATTRA #define XFS_IOC_GETBMAPX F_GETBMAPX #define XFS_IOC_FSGEOMETRY_V1 XFS_FS_GEOMETRY #define XFS_IOC_FSBULKSTAT SGI_FS_BULKSTAT #define XFS_IOC_FSBULKSTAT_SINGLE SGI_FS_BULKSTAT_SINGLE #define XFS_IOC_FSINUMBERS SGI_FS_INUMBERS #define XFS_IOC_PATH_TO_FSHANDLE SGI_PATH_TO_FSHANDLE #define XFS_IOC_PATH_TO_HANDLE SGI_PATH_TO_HANDLE #define XFS_IOC_FD_TO_HANDLE SGI_FD_TO_HANDLE #define XFS_IOC_OPEN_BY_HANDLE SGI_OPEN_BY_HANDLE #define XFS_IOC_READLINK_BY_HANDLE SGI_READLINK_BY_HANDLE #define XFS_IOC_SWAPEXT /* TODO */ #define XFS_IOC_FSGROWFSDATA XFS_GROWFS_DATA #define XFS_IOC_FSGROWFSLOG XFS_GROWFS_LOG #define XFS_IOC_FSGROWFSRT XFS_GROWFS_RT #define XFS_IOC_FSCOUNTS XFS_FS_COUNTS #define XFS_IOC_SET_RESBLKS XFS_SET_RESBLKS #define XFS_IOC_GET_RESBLKS XFS_GET_RESBLKS #define XFS_IOC_ERROR_INJECTION SGI_XFS_INJECT_ERROR #define XFS_IOC_ERROR_CLEARALL SGI_XFS_CLEARALL_ERROR #define XFS_IOC_FREEZE XFS_FS_FREEZE #define XFS_IOC_THAW XFS_FS_THAW #define XFS_IOC_FSSETDM_BY_HANDLE SGI_FSSETDM_BY_HANDLE #define XFS_IOC_ATTRLIST_BY_HANDLE SGI_ATTR_LIST_BY_HANDLE #define XFS_IOC_ATTRMULTI_BY_HANDLE SGI_ATTR_MULTI_BY_HANDLE #define XFS_IOC_FSGEOMETRY XFS_FS_GEOMETRY #define XFS_IOC_GOINGDOWN XFS_FS_GOINGDOWN #define XFS_IOC_GETPARENTS SGI_XFS_GETPARENTS #define XFS_IOC_GETPARENTPATHS SGI_XFS_GETPARENTPATHS #define _AIOCB64_T_DEFINED 1 /* check whether we have to define FS_IOC_FS[GS]ETXATTR ourselves */ #ifndef HAVE_FSXATTR struct fsxattr { __u32 fsx_xflags; /* xflags field value (get/set) */ __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ unsigned char fsx_pad[8]; }; /* * Flags for the fsx_xflags field */ #define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */ #define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */ #define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */ #define FS_XFLAG_APPEND 0x00000010 /* all writes append */ #define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */ #define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */ #define FS_XFLAG_NODUMP 0x00000080 /* do not include in backups */ #define FS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ #define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ #define FS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ #define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ #define FS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR F_FSGETXATTR #define FS_IOC_FSSETXATTR F_FSSETXATTR #endif #ifndef FS_XFLAG_COWEXTSIZE #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ #endif /** * Abstraction of mountpoints. */ struct mntent_cursor { FILE *mtabp; }; static inline int platform_mntent_open(struct mntent_cursor * cursor, char *mtab) { cursor->mtabp = setmntent(mtab, "r"); if (!cursor->mtabp) { fprintf(stderr, "Error: cannot read %s\n", mtab); return 1; } return 0; } static inline struct mntent * platform_mntent_next(struct mntent_cursor * cursor) { return getmntent(cursor->mtabp); } static inline void platform_mntent_close(struct mntent_cursor * cursor) { endmntent(cursor->mtabp); } #endif /* __XFS_IRIX_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/jdm.h0000644000000000000000000000460213063067172015043 0ustar /* * Copyright (c) 2000-2002, 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __JDM_H__ #define __JDM_H__ typedef int intgen_t; typedef void jdm_fshandle_t; /* filesystem handle */ typedef void jdm_filehandle_t; /* filehandle */ struct xfs_bstat; struct attrlist_cursor; struct parent; extern jdm_fshandle_t * jdm_getfshandle( char *mntpnt); extern void jdm_new_filehandle( jdm_filehandle_t **handlep, /* new filehandle */ size_t *hlen, /* new filehandle size */ jdm_fshandle_t *fshandlep, /* filesystem filehandle */ struct xfs_bstat *sp); /* bulkstat info */ extern void jdm_delete_filehandle( jdm_filehandle_t *handlep,/* filehandle to delete */ size_t hlen); /* filehandle size */ extern intgen_t jdm_open( jdm_fshandle_t *fshandlep, struct xfs_bstat *sp, intgen_t oflags); extern intgen_t jdm_readlink( jdm_fshandle_t *fshandlep, struct xfs_bstat *sp, char *bufp, size_t bufsz); extern intgen_t jdm_attr_multi( jdm_fshandle_t *fshp, xfs_bstat_t *statp, char *bufp, int rtrvcnt, int flags); extern intgen_t jdm_attr_list( jdm_fshandle_t *fshp, xfs_bstat_t *statp, char *bufp, size_t bufsz, int flags, struct attrlist_cursor *cursor); extern int jdm_parents( jdm_fshandle_t *fshp, xfs_bstat_t *statp, struct parent *bufp, size_t bufsz, unsigned int *count); extern int jdm_parentpaths( jdm_fshandle_t *fshp, xfs_bstat_t *statp, struct parent *bufp, size_t bufsz, unsigned int *count); /* macro for determining the size of a structure member */ #define sizeofmember( t, m ) sizeof( ( ( t * )0 )->m ) /* macro for calculating the offset of a structure member */ #define offsetofmember( t, m ) ( ( size_t )( char * )&( ( ( t * )0 )->m ) ) #endif /* __JDM_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/kmem.h0000644000000000000000000000302313063067172015216 0ustar /* * Copyright (c) 2008 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __KMEM_H__ #define __KMEM_H__ #define KM_SLEEP 0x0001u #define KM_NOSLEEP 0x0002u #define KM_NOFS 0x0004u #define KM_MAYFAIL 0x0008u #define KM_LARGE 0x0010u typedef struct kmem_zone { int zone_unitsize; /* Size in bytes of zone unit */ char *zone_name; /* tag name */ int allocated; /* debug: How many currently allocated */ } kmem_zone_t; extern kmem_zone_t *kmem_zone_init(int, char *); extern void *kmem_zone_alloc(kmem_zone_t *, int); extern void *kmem_zone_zalloc(kmem_zone_t *, int); static inline void kmem_zone_free(kmem_zone_t *zone, void *ptr) { zone->allocated--; free(ptr); } extern void *kmem_alloc(size_t, int); extern void *kmem_zalloc(size_t, int); static inline void kmem_free(void *ptr) { free(ptr); } extern void *kmem_realloc(void *, size_t, int); #endif xfsprogs-4.9.0+nmu1ubuntu2/include/libxcmd.h0000644000000000000000000000265213033541503015706 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LIBXCMD_H__ #define __LIBXCMD_H__ #include "libxfs.h" #include /* * Device topology information. */ typedef struct fs_topology { int dsunit; /* stripe unit - data subvolume */ int dswidth; /* stripe width - data subvolume */ int rtswidth; /* stripe width - rt subvolume */ int lsectorsize; /* logical sector size &*/ int psectorsize; /* physical sector size */ } fs_topology_t; extern void get_topology( libxfs_init_t *xi, struct fs_topology *ft, int force_overwrite); extern void calc_default_ag_geometry( int blocklog, __uint64_t dblocks, int multidisk, __uint64_t *agsize, __uint64_t *agcount); extern int check_overwrite( const char *device); #endif /* __LIBXCMD_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/libxfs.h0000644000000000000000000001765413063067172015573 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LIBXFS_H__ #define __LIBXFS_H__ #include "libxfs_api_defs.h" #include "platform_defs.h" #include "xfs.h" #include "list.h" #include "hlist.h" #include "cache.h" #include "bitops.h" #include "kmem.h" #include "radix-tree.h" #include "atomic.h" #include "xfs_types.h" #include "xfs_fs.h" #include "xfs_arch.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_quota_defs.h" #include "xfs_trans_resv.h" /* CRC stuff, buffer API dependent on it */ extern uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len); extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len); #define crc32(c,p,l) crc32_le((c),(unsigned char const *)(p),(l)) #define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l)) #include "xfs_cksum.h" /* * This mirrors the kernel include for xfs_buf.h - it's implicitly included in * every files via a similar include in the kernel xfs_linux.h. */ #include "libxfs_io.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_attr_sf.h" #include "xfs_inode_fork.h" #include "xfs_inode_buf.h" #include "xfs_inode.h" #include "xfs_alloc.h" #include "xfs_btree.h" #include "xfs_btree_trace.h" #include "xfs_bmap.h" #include "xfs_trace.h" #include "xfs_trans.h" #include "xfs_rmap_btree.h" #include "xfs_rmap.h" #include "xfs_refcount_btree.h" #include "xfs_refcount.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif #ifndef XFS_SUPER_MAGIC #define XFS_SUPER_MAGIC 0x58465342 #endif #define xfs_isset(a,i) ((a)[(i)/(sizeof(*(a))*NBBY)] & (1ULL<<((i)%(sizeof(*(a))*NBBY)))) /* * Argument structure for libxfs_init(). */ typedef struct { /* input parameters */ char *volname; /* pathname of volume */ char *dname; /* pathname of data "subvolume" */ char *logname; /* pathname of log "subvolume" */ char *rtname; /* pathname of realtime "subvolume" */ int isreadonly; /* filesystem is only read in applic */ int isdirect; /* we can attempt to use direct I/O */ int disfile; /* data "subvolume" is a regular file */ int dcreat; /* try to create data subvolume */ int lisfile; /* log "subvolume" is a regular file */ int lcreat; /* try to create log subvolume */ int risfile; /* realtime "subvolume" is a reg file */ int rcreat; /* try to create realtime subvolume */ int setblksize; /* attempt to set device blksize */ int usebuflock; /* lock xfs_buf_t's - for MT usage */ /* output results */ dev_t ddev; /* device for data subvolume */ dev_t logdev; /* device for log subvolume */ dev_t rtdev; /* device for realtime subvolume */ long long dsize; /* size of data subvolume (BBs) */ long long logBBsize; /* size of log subvolume (BBs) */ /* (blocks allocated for use as * log is stored in mount structure) */ long long logBBstart; /* start block of log subvolume (BBs) */ long long rtsize; /* size of realtime subvolume (BBs) */ int dbsize; /* data subvolume device blksize */ int lbsize; /* log subvolume device blksize */ int rtbsize; /* realtime subvolume device blksize */ int dfd; /* data subvolume file descriptor */ int logfd; /* log subvolume file descriptor */ int rtfd; /* realtime subvolume file descriptor */ int icache_flags; /* cache init flags */ int bcache_flags; /* cache init flags */ } libxfs_init_t; #define LIBXFS_EXIT_ON_FAILURE 0x0001 /* exit the program if a call fails */ #define LIBXFS_ISREADONLY 0x0002 /* disallow all mounted filesystems */ #define LIBXFS_ISINACTIVE 0x0004 /* allow mounted only if mounted ro */ #define LIBXFS_DANGEROUSLY 0x0008 /* repairing a device mounted ro */ #define LIBXFS_EXCLUSIVELY 0x0010 /* disallow other accesses (O_EXCL) */ #define LIBXFS_DIRECT 0x0020 /* can use direct I/O, not buffered */ extern char *progname; extern xfs_lsn_t libxfs_max_lsn; extern int libxfs_init (libxfs_init_t *); extern void libxfs_destroy (void); extern int libxfs_device_to_fd (dev_t); extern dev_t libxfs_device_open (char *, int, int, int); extern void libxfs_device_close (dev_t); extern int libxfs_device_alignment (void); extern void libxfs_report(FILE *); extern void platform_findsizes(char *path, int fd, long long *sz, int *bsz); extern int platform_nproc(void); /* check or write log footer: specify device, log size in blocks & uuid */ typedef char *(libxfs_get_block_t)(char *, int, void *); /* * Helpers to clear the log to a particular log cycle. */ #define XLOG_INIT_CYCLE 1 extern int libxfs_log_clear(struct xfs_buftarg *, char *, xfs_daddr_t, uint, uuid_t *, int, int, int, int, bool); extern int libxfs_log_header(char *, uuid_t *, int, int, int, xfs_lsn_t, xfs_lsn_t, libxfs_get_block_t *, void *); /* Shared utility routines */ extern unsigned int libxfs_log2_roundup(unsigned int i); extern int libxfs_alloc_file_space (struct xfs_inode *, xfs_off_t, xfs_off_t, int, int); extern void libxfs_fs_repair_cmn_err(int, struct xfs_mount *, char *, ...); extern void libxfs_fs_cmn_err(int, struct xfs_mount *, char *, ...); /* XXX: this is messy and needs fixing */ #ifndef __LIBXFS_INTERNAL_XFS_H__ extern void cmn_err(int, char *, ...); enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC }; #endif extern int libxfs_nproc(void); extern unsigned long libxfs_physmem(void); /* in kilobytes */ #include "xfs_ialloc.h" #include "xfs_attr_leaf.h" #include "xfs_attr_remote.h" #include "xfs_trans_space.h" #define XFS_INOBT_IS_FREE_DISK(rp,i) \ ((be64_to_cpu((rp)->ir_free) & XFS_INOBT_MASK(i)) != 0) static inline bool xfs_inobt_is_sparse_disk( struct xfs_inobt_rec *rp, int offset) { int spshift; uint16_t holemask; holemask = be16_to_cpu(rp->ir_u.sp.ir_holemask); spshift = offset / XFS_INODES_PER_HOLEMASK_BIT; if ((1 << spshift) & holemask) return true; return false; } static inline void libxfs_bmbt_disk_get_all( struct xfs_bmbt_rec *rp, struct xfs_bmbt_irec *irec) { struct xfs_bmbt_rec_host hrec; hrec.l0 = get_unaligned_be64(&rp->l0); hrec.l1 = get_unaligned_be64(&rp->l1); libxfs_bmbt_get_all(&hrec, irec); } /* XXX: this is clearly a bug - a shared header needs to export this */ /* xfs_rtalloc.c */ int libxfs_rtfree_extent(struct xfs_trans *, xfs_rtblock_t, xfs_extlen_t); /* XXX: need parts of xfs_attr.h in userspace */ #define LIBXFS_ATTR_ROOT 0x0002 /* use attrs in root namespace */ #define LIBXFS_ATTR_SECURE 0x0008 /* use attrs in security namespace */ #define LIBXFS_ATTR_CREATE 0x0010 /* create, but fail if attr exists */ #define LIBXFS_ATTR_REPLACE 0x0020 /* set, but fail if attr not exists */ int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags); int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name, unsigned char *value, int valuelen, int flags); #endif /* __LIBXFS_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/libxlog.h0000644000000000000000000001125013063067172015726 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc.All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIBXLOG_H #define LIBXLOG_H /* * define the userlevel xlog_t to be the subset of the kernel's * xlog_t that we actually need to get our work done, avoiding * the need to define any exotic kernel types in userland. */ struct xlog { xfs_lsn_t l_tail_lsn; /* lsn of 1st LR w/ unflush buffers */ xfs_lsn_t l_last_sync_lsn;/* lsn of last LR on disk */ xfs_mount_t *l_mp; /* mount point */ struct xfs_buftarg *l_dev; /* dev_t of log */ xfs_daddr_t l_logBBstart; /* start block of log */ int l_logBBsize; /* size of log in 512 byte chunks */ int l_curr_cycle; /* Cycle number of log writes */ int l_prev_cycle; /* Cycle # b4 last block increment */ int l_curr_block; /* current logical block of log */ int l_prev_block; /* previous logical block of log */ int l_iclog_size; /* size of log in bytes */ int l_iclog_size_log;/* log power size of log */ int l_iclog_bufs; /* number of iclog buffers */ atomic64_t l_grant_reserve_head; atomic64_t l_grant_write_head; uint l_sectbb_log; /* log2 of sector size in bbs */ uint l_sectbb_mask; /* sector size (in BBs) * alignment mask */ int l_sectBBsize; /* size of log sector in 512 byte chunks */ }; #include "xfs_log_recover.h" /* * macros mapping kernel code to user code * * XXX: this is duplicated stuff - should be shared with libxfs. */ #ifndef EFSCORRUPTED #define EFSCORRUPTED 990 #endif #define STATIC static #define XFS_ERROR(e) (e) #ifdef DEBUG #define XFS_ERROR_REPORT(e,l,mp) fprintf(stderr, "ERROR: %s\n", e) #else #define XFS_ERROR_REPORT(e,l,mp) ((void) 0) #endif #define XFS_CORRUPTION_ERROR(e,l,mp,m) ((void) 0) #define XFS_MOUNT_WAS_CLEAN 0x1 #define unlikely(x) (x) #define xfs_alert(mp,fmt,args...) cmn_err(CE_ALERT,fmt, ## args) #define xfs_warn(mp,fmt,args...) cmn_err(CE_WARN,fmt, ## args) #define xfs_hex_dump(d,n) ((void) 0) #define __round_mask(x, y) ((__typeof__(x))((y)-1)) #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) #define round_down(x, y) ((x) & ~__round_mask(x, y)) extern void xlog_warn(char *fmt,...); extern void xlog_exit(char *fmt,...); extern void xlog_panic(char *fmt,...); /* exports */ extern int print_exit; extern int print_skip_uuid; extern int print_record_header; /* libxfs parameters */ extern libxfs_init_t x; extern int xlog_is_dirty(struct xfs_mount *, struct xlog *, libxfs_init_t *, int); extern struct xfs_buf *xlog_get_bp(struct xlog *, int); extern void xlog_put_bp(struct xfs_buf *); extern int xlog_bread(struct xlog *log, xfs_daddr_t blk_no, int nbblks, xfs_buf_t *bp, char **offset); extern int xlog_bread_noalign(struct xlog *log, xfs_daddr_t blk_no, int nbblks, xfs_buf_t *bp); extern int xlog_find_zeroed(struct xlog *log, xfs_daddr_t *blk_no); extern int xlog_find_cycle_start(struct xlog *log, xfs_buf_t *bp, xfs_daddr_t first_blk, xfs_daddr_t *last_blk, uint cycle); extern int xlog_find_tail(struct xlog *log, xfs_daddr_t *head_blk, xfs_daddr_t *tail_blk); extern int xlog_test_footer(struct xlog *log); extern int xlog_recover(struct xlog *log, int readonly); extern void xlog_recover_print_data(char *p, int len); extern void xlog_recover_print_logitem(xlog_recover_item_t *item); extern void xlog_recover_print_trans_head(xlog_recover_t *tr); extern int xlog_print_find_oldest(struct xlog *log, xfs_daddr_t *last_blk); /* for transactional view */ extern void xlog_recover_print_trans_head(xlog_recover_t *tr); extern void xlog_recover_print_trans(xlog_recover_t *trans, struct list_head *itemq, int print); extern int xlog_do_recovery_pass(struct xlog *log, xfs_daddr_t head_blk, xfs_daddr_t tail_blk, int pass); extern int xlog_recover_do_trans(struct xlog *log, xlog_recover_t *trans, int pass); extern int xlog_header_check_recover(xfs_mount_t *mp, xlog_rec_header_t *head); extern int xlog_header_check_mount(xfs_mount_t *mp, xlog_rec_header_t *head); #define xlog_assign_atomic_lsn(l,a,b) ((void) 0) #define xlog_assign_grant_head(l,a,b) ((void) 0) #endif /* LIBXLOG_H */ xfsprogs-4.9.0+nmu1ubuntu2/include/linux.h0000644000000000000000000001407113136024635015427 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_LINUX_H__ #define __XFS_LINUX_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef OVERRIDE_SYSTEM_FSXATTR # define fsxattr sys_fsxattr #endif #include /* fsxattr defintion for new kernels */ #ifdef OVERRIDE_SYSTEM_FSXATTR # undef fsxattr #endif static __inline__ int xfsctl(const char *path, int fd, int cmd, void *p) { return ioctl(fd, cmd, p); } /* * platform_test_xfs_*() implies that xfsctl will succeed on the file; * on Linux, at least, special files don't get xfs file ops, * so return 0 for those */ static __inline__ int platform_test_xfs_fd(int fd) { struct statfs statfsbuf; struct stat statbuf; if (fstatfs(fd, &statfsbuf) < 0) return 0; if (fstat(fd, &statbuf) < 0) return 0; if (!S_ISREG(statbuf.st_mode) && !S_ISDIR(statbuf.st_mode)) return 0; return (statfsbuf.f_type == 0x58465342); /* XFSB */ } static __inline__ int platform_test_xfs_path(const char *path) { struct statfs statfsbuf; struct stat statbuf; if (statfs(path, &statfsbuf) < 0) return 0; if (stat(path, &statbuf) < 0) return 0; if (!S_ISREG(statbuf.st_mode) && !S_ISDIR(statbuf.st_mode)) return 0; return (statfsbuf.f_type == 0x58465342); /* XFSB */ } static __inline__ int platform_fstatfs(int fd, struct statfs *buf) { return fstatfs(fd, buf); } static __inline__ void platform_getoptreset(void) { extern int optind; optind = 0; } static __inline__ int platform_uuid_compare(uuid_t *uu1, uuid_t *uu2) { return uuid_compare(*uu1, *uu2); } static __inline__ void platform_uuid_unparse(uuid_t *uu, char *buffer) { uuid_unparse(*uu, buffer); } static __inline__ int platform_uuid_parse(char *buffer, uuid_t *uu) { return uuid_parse(buffer, *uu); } static __inline__ int platform_uuid_is_null(uuid_t *uu) { return uuid_is_null(*uu); } static __inline__ void platform_uuid_generate(uuid_t *uu) { uuid_generate(*uu); } static __inline__ void platform_uuid_clear(uuid_t *uu) { uuid_clear(*uu); } static __inline__ void platform_uuid_copy(uuid_t *dst, uuid_t *src) { uuid_copy(*dst, *src); } #ifndef BLKDISCARD #define BLKDISCARD _IO(0x12,119) #endif static __inline__ int platform_discard_blocks(int fd, uint64_t start, uint64_t len) { __uint64_t range[2] = { start, len }; if (ioctl(fd, BLKDISCARD, &range) < 0) return errno; return 0; } #define ENOATTR ENODATA /* Attribute not found */ #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ #define EFSBADCRC EBADMSG /* Bad CRC detected */ typedef off_t xfs_off_t; typedef __uint64_t xfs_ino_t; typedef __uint32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; typedef __u32 xfs_nlink_t; /** * Abstraction of mountpoints. */ struct mntent_cursor { FILE *mtabp; }; static inline int platform_mntent_open(struct mntent_cursor * cursor, char *mtab) { cursor->mtabp = setmntent(mtab, "r"); if (!cursor->mtabp) { fprintf(stderr, "Error: cannot read %s\n", mtab); return 1; } return 0; } static inline struct mntent * platform_mntent_next(struct mntent_cursor * cursor) { return getmntent(cursor->mtabp); } static inline void platform_mntent_close(struct mntent_cursor * cursor) { endmntent(cursor->mtabp); } /* * Check whether we have to define FS_IOC_FS[GS]ETXATTR ourselves. These * are a copy of the definitions moved to linux/uapi/fs.h in the 4.5 kernel, * so this is purely for supporting builds against old kernel headers. */ #if !defined FS_IOC_FSGETXATTR || defined OVERRIDE_SYSTEM_FSXATTR struct fsxattr { __u32 fsx_xflags; /* xflags field value (get/set) */ __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ unsigned char fsx_pad[8]; }; #endif #ifndef FS_IOC_FSGETXATTR /* * Flags for the fsx_xflags field */ #define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */ #define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */ #define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */ #define FS_XFLAG_APPEND 0x00000010 /* all writes append */ #define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */ #define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */ #define FS_XFLAG_NODUMP 0x00000080 /* do not include in backups */ #define FS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ #define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ #define FS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ #define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ #define FS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) #define FS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) #endif #ifndef FS_XFLAG_COWEXTSIZE #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ #endif #endif /* __XFS_LINUX_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/list.h0000644000000000000000000001417713063067172015254 0ustar /* * Copyright (c) 2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LIST_H__ #define __LIST_H__ /* * This undef is here because BSD 4.4 added some LIST_ macros into system * header file sys/queue.h. This header is included in many other system * headers and thus causes "macro redefined" warnings. * * As OS X is kind of a derivate of BSD, this affects OS X too. * * To use our own LIST_ macros (copied from kernel code), we have to * at first undefine the conflicting system macros. * */ #undef LIST_HEAD #undef LIST_HEAD_INIT /* * Simple, generic doubly-linked list implementation. */ struct list_head { struct list_head *next; struct list_head *prev; }; #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) #define INIT_LIST_HEAD(list) list_head_init(list) static inline void list_head_init(struct list_head *list) { list->next = list->prev = list; } static inline void list_head_destroy(struct list_head *list) { list->next = list->prev = NULL; } static inline void __list_add(struct list_head *add, struct list_head *prev, struct list_head *next) { next->prev = add; add->next = next; add->prev = prev; prev->next = add; } static inline void list_add(struct list_head *add, struct list_head *head) { __list_add(add, head, head->next); } static inline void list_add_tail(struct list_head *add, struct list_head *head) { __list_add(add, head->prev, head); } static inline void __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } static inline void list_del_init(struct list_head *entry) { __list_del(entry->prev, entry->next); list_head_init(entry); } static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); } static inline void list_move(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add(list, head); } static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add_tail(list, head); } static inline int list_empty(const struct list_head *head) { return head->next == head; } static inline void __list_splice(struct list_head *list, struct list_head *prev, struct list_head *next) { struct list_head *first = list->next; struct list_head *last = list->prev; first->prev = prev; prev->next = first; last->next = next; next->prev = last; } static inline void list_splice(struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head, head->next); } static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head, head->next); list_head_init(list); } } #define list_entry(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, struct list_head *a, struct list_head *b)); #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) /** * list_splice_tail_init - join two lists and reinitialise the emptied list * @list: the new list to add. * @head: the place to add it in the first list. * * Each of the lists is a queue. * The list at @list is reinitialised */ static inline void list_splice_tail_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head->prev, head); INIT_LIST_HEAD(list); } } /** * list_last_entry - get the last element from a list * @ptr: the list head to take the element from. * @type: the type of the struct this is embedded in. * @member: the name of the list_head within the struct. * * Note, that list is expected to be not empty. */ #define list_last_entry(ptr, type, member) \ list_entry((ptr)->prev, type, member) /** * list_prev_entry - get the prev element in list * @pos: the type * to cursor * @member: the name of the list_head within the struct. */ #define list_prev_entry(pos, member) \ list_entry((pos)->member.prev, typeof(*(pos)), member) /** * list_for_each_entry_reverse - iterate backwards over list of given type. * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_head within the struct. */ #define list_for_each_entry_reverse(pos, head, member) \ for (pos = list_last_entry(head, typeof(*pos), member); \ &pos->member != (head); \ pos = list_prev_entry(pos, member)) #endif /* __LIST_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/parent.h0000644000000000000000000000173013063067171015560 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PARENT_H__ #define __PARENT_H__ typedef struct parent { __u64 p_ino; __u32 p_gen; __u16 p_reclen; char p_name[1]; } parent_t; typedef struct parent_cursor { __u32 opaque[4]; /* an opaque cookie */ } parent_cursor_t; #endif xfsprogs-4.9.0+nmu1ubuntu2/include/path.h0000644000000000000000000000452413063067172015230 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PATH_H__ #define __PATH_H__ #include "platform_defs.h" /* * XFS Filesystem Paths * * Utility routines for iterating and searching through the list * of known mounted filesystems and project paths. */ #define FS_MOUNT_POINT (1<<0) #define FS_PROJECT_PATH (1<<1) #define FS_FOREIGN (1<<2) typedef struct fs_path { char *fs_name; /* Data device for filesystem */ dev_t fs_datadev; char *fs_log; /* External log device, if any */ dev_t fs_logdev; char *fs_rt; /* Realtime device, if any */ dev_t fs_rtdev; char *fs_dir; /* Directory / mount point */ uint fs_flags; /* FS_{MOUNT_POINT,PROJECT_PATH}*/ uint fs_prid; /* Project ID for tree root */ } fs_path_t; extern int fs_count; /* number of entries in fs table */ extern int xfs_fs_count; /* number of xfs entries in fs table */ extern fs_path_t *fs_table; /* array of entries in fs table */ extern fs_path_t *fs_path; /* current entry in the fs table */ extern char *mtab_file; extern void fs_table_initialise(int, char *[], int, char *[]); extern void fs_table_destroy(void); extern void fs_table_insert_project_path(char *__dir, uint __projid); extern fs_path_t *fs_table_lookup(const char *__dir, uint __flags); typedef struct fs_cursor { uint count; /* total count of mount entries */ uint index; /* current position in table */ uint flags; /* iterator flags: mounts/trees */ fs_path_t *table; /* local/global table pointer */ fs_path_t local; /* space for single-entry table */ } fs_cursor_t; extern void fs_cursor_initialise(char *__dir, uint __flags, fs_cursor_t *__cp); extern fs_path_t *fs_cursor_next_entry(fs_cursor_t *__cp); #endif /* __PATH_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/platform_defs.h.in0000644000000000000000000000501013063067172017515 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @configure_input@ */ #ifndef __XFS_PLATFORM_DEFS_H__ #define __XFS_PLATFORM_DEFS_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct filldir filldir_t; /* long and pointer must be either 32 bit or 64 bit */ #undef SIZEOF_LONG #undef SIZEOF_CHAR_P #define BITS_PER_LONG (SIZEOF_LONG * CHAR_BIT) /* Check whether to define umode_t ourselves. */ #ifndef HAVE_UMODE_T typedef unsigned short umode_t; #endif /* Define if you want gettext (I18N) support */ #undef ENABLE_GETTEXT #ifdef ENABLE_GETTEXT # include # define _(x) gettext(x) # define N_(x) x #else # define _(x) (x) # define N_(x) x # define textdomain(d) do { } while (0) # define bindtextdomain(d,dir) do { } while (0) #endif #include #define IRIX_DEV_BITSMAJOR 14 #define IRIX_DEV_BITSMINOR 18 #define IRIX_DEV_MAXMAJ 0x1ff #define IRIX_DEV_MAXMIN 0x3ffff #define IRIX_DEV_MAJOR(dev) ((int)(((unsigned)(dev) >> IRIX_DEV_BITSMINOR) \ & IRIX_DEV_MAXMAJ)) #define IRIX_DEV_MINOR(dev) ((int)((dev) & IRIX_DEV_MAXMIN)) #define IRIX_MKDEV(major,minor) ((xfs_dev_t)(((major) << IRIX_DEV_BITSMINOR) \ | (minor&IRIX_DEV_MAXMIN))) #define IRIX_DEV_TO_KDEVT(dev) makedev(IRIX_DEV_MAJOR(dev),IRIX_DEV_MINOR(dev)) #ifndef min #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b)) #endif #ifndef NBBY #define NBBY 8 #endif #ifdef DEBUG # define ASSERT(EX) assert(EX) #else # define ASSERT(EX) ((void) 0) #endif #endif /* __XFS_PLATFORM_DEFS_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/project.h0000644000000000000000000000313413063067172015736 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PROJECT_H__ #define __PROJECT_H__ #include "platform_defs.h" #include "xfs.h" extern int setprojid(const char *__name, int __fd, prid_t __id); extern int getprojid(const char *__name, int __fd, prid_t *__id); typedef struct fs_project { prid_t pr_prid; /* project identifier */ char *pr_name; /* project name */ } fs_project_t; extern void setprent(void); extern void endprent(void); extern fs_project_t *getprent(void); extern fs_project_t *getprnam(char *__name); extern fs_project_t *getprprid(prid_t __id); typedef struct fs_project_path { prid_t pp_prid; /* project identifier */ char *pp_pathname; /* pathname to root of project tree */ } fs_project_path_t; extern void setprpathent(void); extern void endprpathent(void); extern fs_project_path_t *getprpathent(void); extern void setprfiles(void); extern char *projid_file; extern char *projects_file; #endif /* __PROJECT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/radix-tree.h0000644000000000000000000000506413063067172016340 0ustar /* * Copyright (C) 2001 Momchil Velikov * Portions Copyright (C) 2001 Christoph Hellwig * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __XFS_SUPPORT_RADIX_TREE_H__ #define __XFS_SUPPORT_RADIX_TREE_H__ #define RADIX_TREE_TAGS struct radix_tree_root { unsigned int height; struct radix_tree_node *rnode; }; #define RADIX_TREE_INIT(mask) { \ .height = 0, \ .rnode = NULL, \ } #define RADIX_TREE(name, mask) \ struct radix_tree_root name = RADIX_TREE_INIT(mask) #define INIT_RADIX_TREE(root, mask) \ do { \ (root)->height = 0; \ (root)->rnode = NULL; \ } while (0) #ifdef RADIX_TREE_TAGS #define RADIX_TREE_MAX_TAGS 2 #endif int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); void *radix_tree_lookup(struct radix_tree_root *, unsigned long); void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); void *radix_tree_lookup_first(struct radix_tree_root *, unsigned long *); void *radix_tree_delete(struct radix_tree_root *, unsigned long); unsigned int radix_tree_gang_lookup(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items); unsigned int radix_tree_gang_lookup_ex(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned long last_index, unsigned int max_items); void radix_tree_init(void); #ifdef RADIX_TREE_TAGS void *radix_tree_tag_set(struct radix_tree_root *root, unsigned long index, unsigned int tag); void *radix_tree_tag_clear(struct radix_tree_root *root, unsigned long index, unsigned int tag); int radix_tree_tag_get(struct radix_tree_root *root, unsigned long index, unsigned int tag); unsigned int radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items, unsigned int tag); int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag); #endif #endif /* __XFS_SUPPORT_RADIX_TREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs.h0000644000000000000000000000410013063067172015062 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, * USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ #ifndef __XFS_H__ #define __XFS_H__ #if defined(__linux__) #include #elif defined(__FreeBSD__) #include #elif defined(__FreeBSD_kernel__) #include #elif defined(__APPLE__) #include #elif defined(__sgi__) || defined(__sgi) #include #else # error unknown platform... have fun porting! #endif /* * make sure that any user of the xfs headers has a 64bit off_t type */ extern int xfs_assert_largefile[sizeof(off_t)-8]; /* * sparse kernel source annotations */ #ifndef __user #define __user #endif /* * kernel struct packing shortcut */ #ifndef __packed #define __packed __attribute__((packed)) #endif #include #include #endif /* __XFS_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_arch.h0000644000000000000000000001766513063067172016103 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_ARCH_H__ #define __XFS_ARCH_H__ #if __BYTE_ORDER == __BIG_ENDIAN #define XFS_NATIVE_HOST 1 #else #undef XFS_NATIVE_HOST #endif #ifdef __CHECKER__ #define __bitwise __attribute__((bitwise)) #define __force __attribute__((force)) #else #define __bitwise #define __force #endif typedef __u16 __bitwise __le16; typedef __u32 __bitwise __le32; typedef __u64 __bitwise __le64; typedef __u16 __bitwise __be16; typedef __u32 __bitwise __be32; typedef __u64 __bitwise __be64; /* * Casts are necessary for constants, because we never know how for sure * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. */ #define ___swab16(x) \ ({ \ __u16 __x = (x); \ ((__u16)( \ (((__u16)(__x) & (__u16)0x00ffU) << 8) | \ (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \ }) #define ___swab32(x) \ ({ \ __u32 __x = (x); \ ((__u32)( \ (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ }) #define ___swab64(x) \ ({ \ __u64 __x = (x); \ ((__u64)( \ (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ }) #define ___constant_swab16(x) \ ((__u16)( \ (((__u16)(x) & (__u16)0x00ffU) << 8) | \ (((__u16)(x) & (__u16)0xff00U) >> 8) )) #define ___constant_swab32(x) \ ((__u32)( \ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) #define ___constant_swab64(x) \ ((__u64)( \ (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) /* * provide defaults when no architecture-specific optimization is detected */ #ifndef __arch__swab16 # define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); }) #endif #ifndef __arch__swab32 # define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); }) #endif #ifndef __arch__swab64 # define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); }) #endif #ifndef __arch__swab16p # define __arch__swab16p(x) __arch__swab16(*(x)) #endif #ifndef __arch__swab32p # define __arch__swab32p(x) __arch__swab32(*(x)) #endif #ifndef __arch__swab64p # define __arch__swab64p(x) __arch__swab64(*(x)) #endif #ifndef __arch__swab16s # define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0) #endif #ifndef __arch__swab32s # define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0) #endif #ifndef __arch__swab64s # define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0) #endif /* * Allow constant folding */ # define __swab16(x) \ (__builtin_constant_p((__u16)(x)) ? \ ___constant_swab16((x)) : \ __fswab16((x))) # define __swab32(x) \ (__builtin_constant_p((__u32)(x)) ? \ ___constant_swab32((x)) : \ __fswab32((x))) # define __swab64(x) \ (__builtin_constant_p((__u64)(x)) ? \ ___constant_swab64((x)) : \ __fswab64((x))) static __inline__ __u16 __fswab16(__u16 x) { return (__extension__ __arch__swab16(x)); } static __inline__ __u16 __swab16p(__u16 *x) { return (__extension__ __arch__swab16p(x)); } static __inline__ void __swab16s(__u16 *addr) { (__extension__ ({__arch__swab16s(addr);})); } static __inline__ __u32 __fswab32(__u32 x) { return (__extension__ __arch__swab32(x)); } static __inline__ __u32 __swab32p(__u32 *x) { return (__extension__ __arch__swab32p(x)); } static __inline__ void __swab32s(__u32 *addr) { (__extension__ ({__arch__swab32s(addr);})); } static __inline__ __u64 __fswab64(__u64 x) { # ifdef __SWAB_64_THRU_32__ __u32 h = x >> 32; __u32 l = x & ((1ULL<<32)-1); return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); # else return (__extension__ __arch__swab64(x)); # endif } static __inline__ __u64 __swab64p(__u64 *x) { return (__extension__ __arch__swab64p(x)); } static __inline__ void __swab64s(__u64 *addr) { (__extension__ ({__arch__swab64s(addr);})); } #ifdef XFS_NATIVE_HOST #define cpu_to_be16(val) ((__force __be16)(__u16)(val)) #define cpu_to_be32(val) ((__force __be32)(__u32)(val)) #define cpu_to_be64(val) ((__force __be64)(__u64)(val)) #define be16_to_cpu(val) ((__force __u16)(__be16)(val)) #define be32_to_cpu(val) ((__force __u32)(__be32)(val)) #define be64_to_cpu(val) ((__force __u64)(__be64)(val)) #define cpu_to_le32(val) ((__force __be32)__swab32((__u32)(val))) #define le32_to_cpu(val) (__swab32((__force __u32)(__le32)(val))) #define __constant_cpu_to_le32(val) \ ((__force __le32)___constant_swab32((__u32)(val))) #define __constant_cpu_to_be32(val) \ ((__force __be32)(__u32)(val)) #else #define cpu_to_be16(val) ((__force __be16)__swab16((__u16)(val))) #define cpu_to_be32(val) ((__force __be32)__swab32((__u32)(val))) #define cpu_to_be64(val) ((__force __be64)__swab64((__u64)(val))) #define be16_to_cpu(val) (__swab16((__force __u16)(__be16)(val))) #define be32_to_cpu(val) (__swab32((__force __u32)(__be32)(val))) #define be64_to_cpu(val) (__swab64((__force __u64)(__be64)(val))) #define cpu_to_le32(val) ((__force __le32)(__u32)(val)) #define le32_to_cpu(val) ((__force __u32)(__le32)(val)) #define __constant_cpu_to_le32(val) \ ((__force __le32)(__u32)(val)) #define __constant_cpu_to_be32(val) \ ((__force __be32)___constant_swab32((__u32)(val))) #endif static inline void be16_add_cpu(__be16 *a, __s16 b) { *a = cpu_to_be16(be16_to_cpu(*a) + b); } static inline void be32_add_cpu(__be32 *a, __s32 b) { *a = cpu_to_be32(be32_to_cpu(*a) + b); } static inline void be64_add_cpu(__be64 *a, __s64 b) { *a = cpu_to_be64(be64_to_cpu(*a) + b); } static inline __uint16_t get_unaligned_be16(void *p) { __uint8_t *__p = p; return __p[0] << 8 | __p[1]; } static inline __uint32_t get_unaligned_be32(void *p) { __uint8_t *__p = p; return __p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3]; } static inline __uint64_t get_unaligned_be64(void *p) { return (__uint64_t)get_unaligned_be32(p) << 32 | get_unaligned_be32(p + 4); } static inline void put_unaligned_be16(__uint16_t val, void *p) { __uint8_t *__p = p; *__p++ = val >> 8; *__p++ = val; } static inline void put_unaligned_be32(__uint32_t val, void *p) { __uint8_t *__p = p; put_unaligned_be16(val >> 16, __p); put_unaligned_be16(val, __p + 2); } static inline void put_unaligned_be64(__uint64_t val, void *p) { put_unaligned_be32(val >> 32, p); put_unaligned_be32(val, p + 4); } #endif /* __XFS_ARCH_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_btree_trace.h0000644000000000000000000000646213063067172017436 0ustar /* * Copyright (c) 2008 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_BTREE_TRACE_H__ #define __XFS_BTREE_TRACE_H__ struct xfs_btree_cur; struct xfs_buf; /* * Trace hooks. * i,j = integer (32 bit) * b = btree block buffer (xfs_buf_t) * p = btree ptr * r = btree record * k = btree key */ #ifdef XFS_BTREE_TRACE /* * Trace buffer entry types. */ #define XFS_BTREE_KTRACE_ARGBI 1 #define XFS_BTREE_KTRACE_ARGBII 2 #define XFS_BTREE_KTRACE_ARGFFFI 3 #define XFS_BTREE_KTRACE_ARGI 4 #define XFS_BTREE_KTRACE_ARGIPK 5 #define XFS_BTREE_KTRACE_ARGIPR 6 #define XFS_BTREE_KTRACE_ARGIK 7 #define XFS_BTREE_KTRACE_ARGR 8 #define XFS_BTREE_KTRACE_CUR 9 /* * Sub-types for cursor traces. */ #define XBT_ARGS 0 #define XBT_ENTRY 1 #define XBT_ERROR 2 #define XBT_EXIT 3 void xfs_btree_trace_argbi(const char *, struct xfs_btree_cur *, struct xfs_buf *, int, int); void xfs_btree_trace_argbii(const char *, struct xfs_btree_cur *, struct xfs_buf *, int, int, int); void xfs_btree_trace_argi(const char *, struct xfs_btree_cur *, int, int); void xfs_btree_trace_argipk(const char *, struct xfs_btree_cur *, int, union xfs_btree_ptr, union xfs_btree_key *, int); void xfs_btree_trace_argipr(const char *, struct xfs_btree_cur *, int, union xfs_btree_ptr, union xfs_btree_rec *, int); void xfs_btree_trace_argik(const char *, struct xfs_btree_cur *, int, union xfs_btree_key *, int); void xfs_btree_trace_argr(const char *, struct xfs_btree_cur *, union xfs_btree_rec *, int); void xfs_btree_trace_cursor(const char *, struct xfs_btree_cur *, int, int); #define XFS_BTREE_TRACE_ARGBI(c, b, i) \ xfs_btree_trace_argbi(__func__, c, b, i, __LINE__) #define XFS_BTREE_TRACE_ARGBII(c, b, i, j) \ xfs_btree_trace_argbii(__func__, c, b, i, j, __LINE__) #define XFS_BTREE_TRACE_ARGI(c, i) \ xfs_btree_trace_argi(__func__, c, i, __LINE__) #define XFS_BTREE_TRACE_ARGIPK(c, i, p, k) \ xfs_btree_trace_argipk(__func__, c, i, p, k, __LINE__) #define XFS_BTREE_TRACE_ARGIPR(c, i, p, r) \ xfs_btree_trace_argipr(__func__, c, i, p, r, __LINE__) #define XFS_BTREE_TRACE_ARGIK(c, i, k) \ xfs_btree_trace_argik(__func__, c, i, k, __LINE__) #define XFS_BTREE_TRACE_ARGR(c, r) \ xfs_btree_trace_argr(__func__, c, r, __LINE__) #define XFS_BTREE_TRACE_CURSOR(c, t) \ xfs_btree_trace_cursor(__func__, c, t, __LINE__) #else #define XFS_BTREE_TRACE_ARGBI(c, b, i) #define XFS_BTREE_TRACE_ARGBII(c, b, i, j) #define XFS_BTREE_TRACE_ARGI(c, i) #define XFS_BTREE_TRACE_ARGIPK(c, i, p, s) #define XFS_BTREE_TRACE_ARGIPR(c, i, p, r) #define XFS_BTREE_TRACE_ARGIK(c, i, k) #define XFS_BTREE_TRACE_ARGR(c, r) #define XFS_BTREE_TRACE_CURSOR(c, t) #endif /* XFS_BTREE_TRACE */ #endif /* __XFS_BTREE_TRACE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_inode.h0000644000000000000000000001066613063067172016256 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_INODE_H__ #define __XFS_INODE_H__ /* These match kernel side includes */ #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" struct xfs_trans; struct xfs_mount; struct xfs_inode_log_item; struct xfs_dir_ops; /* * Inode interface. This fakes up a "VFS inode" to make the xfs_inode appear * similar to the kernel which now is used tohold certain parts of the on-disk * metadata. */ struct inode { mode_t i_mode; uint32_t i_nlink; uint32_t i_generation; uint64_t i_version; struct timespec i_atime; struct timespec i_mtime; struct timespec i_ctime; }; typedef struct xfs_inode { struct cache_node i_node; struct xfs_mount *i_mount; /* fs mount struct ptr */ xfs_ino_t i_ino; /* inode number (agno/agino) */ struct xfs_imap i_imap; /* location for xfs_imap() */ struct xfs_buftarg i_dev; /* dev for this inode */ struct xfs_ifork *i_afp; /* attribute fork pointer */ struct xfs_ifork *i_cowfp; /* copy on write extents */ struct xfs_ifork i_df; /* data fork */ struct xfs_trans *i_transp; /* ptr to owning transaction */ struct xfs_inode_log_item *i_itemp; /* logging information */ unsigned int i_delayed_blks; /* count of delay alloc blks */ struct xfs_icdinode i_d; /* most of ondisk inode */ xfs_extnum_t i_cnextents; /* # of extents in cow fork */ unsigned int i_cformat; /* format of cow fork */ xfs_fsize_t i_size; /* in-memory size */ const struct xfs_dir_ops *d_ops; /* directory ops vector */ struct inode i_vnode; } xfs_inode_t; static inline struct inode *VFS_I(struct xfs_inode *ip) { return &ip->i_vnode; } /* * wrappers around the mode checks to simplify code */ static inline bool XFS_ISREG(struct xfs_inode *ip) { return S_ISREG(VFS_I(ip)->i_mode); } static inline bool XFS_ISDIR(struct xfs_inode *ip) { return S_ISDIR(VFS_I(ip)->i_mode); } /* * For regular files we only update the on-disk filesize when actually * writing data back to disk. Until then only the copy in the VFS inode * is uptodate. */ static inline xfs_fsize_t XFS_ISIZE(struct xfs_inode *ip) { if (XFS_ISREG(ip)) return ip->i_size; return ip->i_d.di_size; } #define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) /* inode link counts */ static inline void set_nlink(struct inode *inode, uint32_t nlink) { inode->i_nlink = nlink; } static inline void inc_nlink(struct inode *inode) { inode->i_nlink++; } /* * Project quota id helpers (previously projid was 16bit only and using two * 16bit values to hold new 32bit projid was chosen to retain compatibility with * "old" filesystems). * * Copied here from xfs_inode.h because it has to be defined after the struct * xfs_inode... */ static inline prid_t xfs_get_projid(struct xfs_icdinode *id) { return (prid_t)id->di_projid_hi << 16 | id->di_projid_lo; } static inline void xfs_set_projid(struct xfs_icdinode *id, prid_t projid) { id->di_projid_hi = (__uint16_t) (projid >> 16); id->di_projid_lo = (__uint16_t) (projid & 0xffff); } static inline bool xfs_is_reflink_inode(struct xfs_inode *ip) { return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; } typedef struct cred { uid_t cr_uid; gid_t cr_gid; } cred_t; extern int libxfs_inode_alloc (struct xfs_trans **, struct xfs_inode *, mode_t, nlink_t, xfs_dev_t, struct cred *, struct fsxattr *, struct xfs_inode **); extern void libxfs_trans_inode_alloc_buf (struct xfs_trans *, struct xfs_buf *); extern void libxfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); extern int libxfs_iflush_int (struct xfs_inode *, struct xfs_buf *); /* Inode Cache Interfaces */ extern int libxfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, uint, struct xfs_inode **); extern void libxfs_iput(struct xfs_inode *); #define IRELE(ip) libxfs_iput(ip) #endif /* __XFS_INODE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_log_recover.h0000644000000000000000000000373613063067172017466 0ustar /* * Copyright (c) 2000,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_LOG_RECOVER_H__ #define __XFS_LOG_RECOVER_H__ /* * Macros, structures, prototypes for internal log manager use. */ #define XLOG_RHASH_BITS 4 #define XLOG_RHASH_SIZE 16 #define XLOG_RHASH_SHIFT 2 #define XLOG_RHASH(tid) \ ((((__uint32_t)tid)>>XLOG_RHASH_SHIFT) & (XLOG_RHASH_SIZE-1)) #define XLOG_MAX_REGIONS_IN_ITEM (XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK / 2 + 1) /* * item headers are in ri_buf[0]. Additional buffers follow. */ typedef struct xlog_recover_item { struct list_head ri_list; int ri_type; int ri_cnt; /* count of regions found */ int ri_total; /* total regions */ xfs_log_iovec_t *ri_buf; /* ptr to regions buffer */ } xlog_recover_item_t; struct xlog_tid; typedef struct xlog_recover { struct hlist_node r_list; xlog_tid_t r_log_tid; /* log's transaction id */ xfs_trans_header_t r_theader; /* trans header for partial */ int r_state; /* not needed */ xfs_lsn_t r_lsn; /* xact lsn */ struct list_head r_itemq; /* q for items */ } xlog_recover_t; #define ITEM_TYPE(i) (*(unsigned short *)(i)->ri_buf[0].i_addr) /* * This is the number of entries in the l_buf_cancel_table used during * recovery. */ #define XLOG_BC_TABLE_SIZE 64 #define XLOG_RECOVER_PASS1 1 #define XLOG_RECOVER_PASS2 2 #endif /* __XFS_LOG_RECOVER_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_metadump.h0000644000000000000000000000200213063067172016755 0ustar /* * Copyright (c) 2007 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XFS_METADUMP_H_ #define _XFS_METADUMP_H_ #define XFS_MD_MAGIC 0x5846534d /* 'XFSM' */ typedef struct xfs_metablock { __be32 mb_magic; __be16 mb_count; __uint8_t mb_blocklog; __uint8_t mb_reserved; /* followed by an array of xfs_daddr_t */ } xfs_metablock_t; #endif /* _XFS_METADUMP_H_ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_mount.h0000644000000000000000000001637713063067172016327 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_MOUNT_H__ #define __XFS_MOUNT_H__ struct xfs_inode; struct xfs_buftarg; struct xfs_dir_ops; struct xfs_da_geometry; /* * Define a user-level mount structure with all we need * in order to make use of the numerous XFS_* macros. */ typedef struct xfs_mount { xfs_sb_t m_sb; /* copy of fs superblock */ #define m_icount m_sb.sb_icount #define m_ifree m_sb.sb_ifree #define m_fdblocks m_sb.sb_fdblocks char *m_fsname; /* filesystem name */ int m_bsize; /* fs logical block size */ xfs_agnumber_t m_agfrotor; /* last ag where space found */ xfs_agnumber_t m_agirotor; /* last ag dir inode alloced */ xfs_agnumber_t m_maxagi; /* highest inode alloc group */ uint m_rsumlevels; /* rt summary levels */ uint m_rsumsize; /* size of rt summary, bytes */ struct xfs_inode *m_rbmip; /* pointer to bitmap inode */ struct xfs_inode *m_rsumip; /* pointer to summary inode */ struct xfs_buftarg *m_ddev_targp; struct xfs_buftarg *m_logdev_targp; struct xfs_buftarg *m_rtdev_targp; #define m_dev m_ddev_targp #define m_logdev m_logdev_targp #define m_rtdev m_rtdev_targp __uint8_t m_dircook_elog; /* log d-cookie entry bits */ __uint8_t m_blkbit_log; /* blocklog + NBBY */ __uint8_t m_blkbb_log; /* blocklog - BBSHIFT */ __uint8_t m_sectbb_log; /* sectorlog - BBSHIFT */ __uint8_t m_agno_log; /* log #ag's */ __uint8_t m_agino_log; /* #bits for agino in inum */ uint m_inode_cluster_size;/* min inode buf size */ uint m_blockmask; /* sb_blocksize-1 */ uint m_blockwsize; /* sb_blocksize in words */ uint m_blockwmask; /* blockwsize-1 */ uint m_alloc_mxr[2]; /* XFS_ALLOC_BLOCK_MAXRECS */ uint m_alloc_mnr[2]; /* XFS_ALLOC_BLOCK_MINRECS */ uint m_bmap_dmxr[2]; /* XFS_BMAP_BLOCK_DMAXRECS */ uint m_bmap_dmnr[2]; /* XFS_BMAP_BLOCK_DMINRECS */ uint m_inobt_mxr[2]; /* XFS_INOBT_BLOCK_MAXRECS */ uint m_inobt_mnr[2]; /* XFS_INOBT_BLOCK_MINRECS */ uint m_rmap_mxr[2]; /* max rmap btree records */ uint m_rmap_mnr[2]; /* min rmap btree records */ uint m_refc_mxr[2]; /* max refc btree records */ uint m_refc_mnr[2]; /* min refc btree records */ uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */ uint m_rmap_maxlevels; /* max rmap btree levels */ uint m_refc_maxlevels; /* max refc btree levels */ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ uint m_alloc_set_aside; /* space we can't use */ uint m_ag_max_usable; /* max space per AG */ struct radix_tree_root m_perag_tree; uint m_flags; /* global mount flags */ uint m_qflags; /* quota status flags */ uint m_attroffset; /* inode attribute offset */ int m_ialloc_inos; /* inodes in inode allocation */ int m_ialloc_blks; /* blocks in inode allocation */ int m_ialloc_min_blks; /* min blocks in sparse inode * allocation */ int m_litino; /* size of inode union area */ int m_inoalign_mask;/* mask sb_inoalignmt if used */ struct xfs_trans_resv m_resv; /* precomputed res values */ __uint64_t m_maxicount; /* maximum inode count */ int m_dalign; /* stripe unit */ int m_swidth; /* stripe width */ int m_sinoalign; /* stripe unit inode alignmnt */ const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */ struct xfs_da_geometry *m_dir_geo; /* directory block geometry */ struct xfs_da_geometry *m_attr_geo; /* attribute block geometry */ const struct xfs_dir_ops *m_dir_inode_ops; /* vector of dir inode ops */ const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */ #define M_DIROPS(mp) ((mp)->m_dir_inode_ops) /* * anonymous struct to allow xfs_dquot_buf.c to compile. * Pointer is always null in userspace, so code does not use it at all */ struct { int qi_dqperchunk; } *m_quotainfo; /* * xlog is defined in libxlog and thus is not intialized by libxfs. This * allows an application to initialize and store a reference to the log * if warranted. */ struct xlog *m_log; } xfs_mount_t; /* per-AG block reservation data structures*/ enum xfs_ag_resv_type { XFS_AG_RESV_NONE = 0, XFS_AG_RESV_METADATA, XFS_AG_RESV_AGFL, }; struct xfs_ag_resv { /* number of blocks originally reserved here */ xfs_extlen_t ar_orig_reserved; /* number of blocks reserved here */ xfs_extlen_t ar_reserved; /* number of blocks originally asked for */ xfs_extlen_t ar_asked; }; /* * Per-ag incore structure, copies of information in agf and agi, * to improve the performance of allocation group selection. */ typedef struct xfs_perag { struct xfs_mount *pag_mount; /* owner filesystem */ xfs_agnumber_t pag_agno; /* AG this structure belongs to */ atomic_t pag_ref; /* perag reference count */ char pagf_init; /* this agf's entry is initialized */ char pagi_init; /* this agi's entry is initialized */ char pagf_metadata; /* the agf is preferred to be metadata */ char pagi_inodeok; /* The agi is ok for inodes */ __uint8_t pagf_levels[XFS_BTNUM_AGF]; /* # of levels in bno & cnt btree */ __uint32_t pagf_flcount; /* count of blocks in freelist */ xfs_extlen_t pagf_freeblks; /* total free blocks */ xfs_extlen_t pagf_longest; /* longest free space */ __uint32_t pagf_btreeblks; /* # of blocks held in AGF btrees */ xfs_agino_t pagi_freecount; /* number of free inodes */ xfs_agino_t pagi_count; /* number of allocated inodes */ /* * Inode allocation search lookup optimisation. * If the pagino matches, the search for new inodes * doesn't need to search the near ones again straight away */ xfs_agino_t pagl_pagino; xfs_agino_t pagl_leftrec; xfs_agino_t pagl_rightrec; int pagb_count; /* pagb slots in use */ /* Blocks reserved for all kinds of metadata. */ struct xfs_ag_resv pag_meta_resv; /* Blocks reserved for just AGFL-based metadata. */ struct xfs_ag_resv pag_agfl_resv; /* reference count */ __uint8_t pagf_refcount_level; } xfs_perag_t; static inline struct xfs_ag_resv * xfs_perag_resv( struct xfs_perag *pag, enum xfs_ag_resv_type type) { switch (type) { case XFS_AG_RESV_METADATA: return &pag->pag_meta_resv; case XFS_AG_RESV_AGFL: return &pag->pag_agfl_resv; default: return NULL; } } #define LIBXFS_MOUNT_DEBUGGER 0x0001 #define LIBXFS_MOUNT_32BITINODES 0x0002 #define LIBXFS_MOUNT_32BITINOOPT 0x0004 #define LIBXFS_MOUNT_COMPAT_ATTR 0x0008 #define LIBXFS_MOUNT_ATTR2 0x0010 #define LIBXFS_MOUNT_WANT_CORRUPTED 0x0020 #define LIBXFS_BHASHSIZE(sbp) (1<<10) extern xfs_mount_t *libxfs_mount (xfs_mount_t *, xfs_sb_t *, dev_t, dev_t, dev_t, int); extern void libxfs_umount (xfs_mount_t *); extern void libxfs_rtmount_destroy (xfs_mount_t *); #endif /* __XFS_MOUNT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_multidisk.h0000644000000000000000000000573413033541503017155 0ustar /* * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_MULTIDISK_H__ #define __XFS_MULTIDISK_H__ #define XFS_DFL_SB_VERSION_BITS \ (XFS_SB_VERSION_NLINKBIT | \ XFS_SB_VERSION_EXTFLGBIT | \ XFS_SB_VERSION_DIRV2BIT) #define XFS_DFL_BLOCKSIZE_LOG 12 /* 4096 byte blocks */ #define XFS_DINODE_DFL_LOG 8 /* 256 byte inodes */ #define XFS_DINODE_DFL_CRC_LOG 9 /* 512 byte inodes for CRCs */ #define XFS_MIN_DATA_BLOCKS 100 #define XFS_MIN_INODE_PERBLOCK 2 /* min inodes per block */ #define XFS_DFL_IMAXIMUM_PCT 25 /* max % of space for inodes */ #define XFS_IFLAG_ALIGN true /* -i align defaults on */ #define XFS_MIN_REC_DIRSIZE 12 /* 4096 byte dirblocks (V2) */ #define XFS_DFL_DIR_VERSION 2 /* default directory version */ #define XFS_DFL_LOG_SIZE 1000 /* default log size, blocks */ #define XFS_DFL_LOG_FACTOR 5 /* default log size, factor */ /* with max trans reservation */ #define XFS_MAX_INODE_SIG_BITS 32 /* most significant bits in an * inode number that we'll * accept w/o warnings */ #define XFS_AG_BYTES(bblog) ((long long)BBSIZE << (bblog)) #define XFS_AG_MIN_BYTES ((XFS_AG_BYTES(15))) /* 16 MB */ #define XFS_AG_MAX_BYTES ((XFS_AG_BYTES(31))) /* 1 TB */ #define XFS_AG_MIN_BLOCKS(blog) (XFS_AG_MIN_BYTES >> (blog)) #define XFS_AG_MAX_BLOCKS(blog) ((XFS_AG_MAX_BYTES - 1) >> (blog)) #define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1)) /* * These values define what we consider a "multi-disk" filesystem. That is, a * filesystem that is likely to be made up of multiple devices, and hence have * some level of parallelism available to it at the IO level. */ #define XFS_MULTIDISK_AGLOG 5 /* 32 AGs */ #define XFS_NOMULTIDISK_AGLOG 2 /* 4 AGs */ #define XFS_MULTIDISK_AGCOUNT (1 << XFS_MULTIDISK_AGLOG) extern long long cvtnum(unsigned int blksize, unsigned int sectsize, const char *str); /* proto.c */ extern char *setup_proto (char *fname); extern void parse_proto (xfs_mount_t *mp, struct fsxattr *fsx, char **pp); extern void res_failed (int err); /* maxtrres.c */ extern int max_trans_res(unsigned long agsize, int crcs_enabled, int dirversion, int sectorlog, int blocklog, int inodelog, int dirblocklog, int logversion, int log_sunit, int finobt, int rmapbt, int reflink); #endif /* __XFS_MULTIDISK_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_trace.h0000644000000000000000000003343713063067171016256 0ustar /* * Copyright (c) 2011 RedHat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TRACE_H__ #define __TRACE_H__ #define trace_xfs_alloc_exact_done(a) ((void) 0) #define trace_xfs_alloc_exact_notfound(a) ((void) 0) #define trace_xfs_alloc_exact_error(a) ((void) 0) #define trace_xfs_alloc_near_nominleft(a) ((void) 0) #define trace_xfs_alloc_near_first(a) ((void) 0) #define trace_xfs_alloc_near_greater(a) ((void) 0) #define trace_xfs_alloc_near_lesser(a) ((void) 0) #define trace_xfs_alloc_near_error(a) ((void) 0) #define trace_xfs_alloc_near_noentry(a) ((void) 0) #define trace_xfs_alloc_near_busy(a) ((void) 0) #define trace_xfs_alloc_size_neither(a) ((void) 0) #define trace_xfs_alloc_size_noentry(a) ((void) 0) #define trace_xfs_alloc_size_nominleft(a) ((void) 0) #define trace_xfs_alloc_size_done(a) ((void) 0) #define trace_xfs_alloc_size_error(a) ((void) 0) #define trace_xfs_alloc_size_busy(a) ((void) 0) #define trace_xfs_alloc_small_freelist(a) ((void) 0) #define trace_xfs_alloc_small_notenough(a) ((void) 0) #define trace_xfs_alloc_small_done(a) ((void) 0) #define trace_xfs_alloc_small_error(a) ((void) 0) #define trace_xfs_alloc_vextent_badargs(a) ((void) 0) #define trace_xfs_alloc_vextent_nofix(a) ((void) 0) #define trace_xfs_alloc_vextent_noagbp(a) ((void) 0) #define trace_xfs_alloc_vextent_loopfailed(a) ((void) 0) #define trace_xfs_alloc_vextent_allfailed(a) ((void) 0) #define trace_xfs_log_recover_item_reorder_head(a,b,c,d) ((void) 0) #define trace_xfs_log_recover_item_reorder_tail(a,b,c,d) ((void) 0) #define trace_xfs_log_recover_item_add_cont(a,b,c,d) ((void) 0) #define trace_xfs_log_recover_item_add(a,b,c,d) ((void) 0) #define trace_xfs_da_btree_corrupt(a,b) ((void) 0) #define trace_xfs_btree_corrupt(a,b) ((void) 0) #define trace_xfs_btree_updkeys(a,b,c) ((void) 0) #define trace_xfs_btree_overlapped_query_range(a,b,c) ((void) 0) #define trace_xfs_free_extent(a,b,c,d,e,f,g) ((void) 0) #define trace_xfs_agf(a,b,c,d) ((void) 0) #define trace_xfs_read_agf(a,b) ((void) 0) #define trace_xfs_alloc_read_agf(a,b) ((void) 0) #define trace_xfs_read_agi(a,b) ((void) 0) #define trace_xfs_ialloc_read_agi(a,b) ((void) 0) #define trace_xfs_irec_merge_pre(a,b,c,d,e,f) ((void) 0) #define trace_xfs_irec_merge_post(a,b,c,d) ((void) 0) #define trace_xfs_iext_insert(a,b,c,d,e) ((void) 0) #define trace_xfs_iext_remove(a,b,c,d) ((void) 0) #define trace_xfs_dir2_grow_inode(a,b) ((void) 0) #define trace_xfs_dir2_shrink_inode(a,b) ((void) 0) #define trace_xfs_dir2_leaf_to_node(a) ((void) 0) #define trace_xfs_dir2_leaf_to_block(a) ((void) 0) #define trace_xfs_dir2_leaf_addname(a) ((void) 0) #define trace_xfs_dir2_leaf_lookup(a) ((void) 0) #define trace_xfs_dir2_leaf_removename(a) ((void) 0) #define trace_xfs_dir2_leaf_replace(a) ((void) 0) #define trace_xfs_dir2_block_addname(a) ((void) 0) #define trace_xfs_dir2_block_to_leaf(a) ((void) 0) #define trace_xfs_dir2_block_to_sf(a) ((void) 0) #define trace_xfs_dir2_block_lookup(a) ((void) 0) #define trace_xfs_dir2_block_removename(a) ((void) 0) #define trace_xfs_dir2_block_replace(a) ((void) 0) #define trace_xfs_dir2_leafn_add(a,b) ((void) 0) #define trace_xfs_dir2_leafn_remove(a,b) ((void) 0) #define trace_xfs_dir2_leafn_moveents(a,b,c,d) ((void) 0) #define trace_xfs_dir2_node_to_leaf(a) ((void) 0) #define trace_xfs_dir2_node_addname(a) ((void) 0) #define trace_xfs_dir2_node_lookup(a) ((void) 0) #define trace_xfs_dir2_node_removename(a) ((void) 0) #define trace_xfs_dir2_node_replace(a) ((void) 0) #define trace_xfs_dir2_sf_to_block(a) ((void) 0) #define trace_xfs_dir2_sf_addname(a) ((void) 0) #define trace_xfs_dir2_sf_create(a) ((void) 0) #define trace_xfs_dir2_sf_lookup(a) ((void) 0) #define trace_xfs_dir2_sf_removename(a) ((void) 0) #define trace_xfs_dir2_sf_replace(a) ((void) 0) #define trace_xfs_dir2_sf_toino4(a) ((void) 0) #define trace_xfs_dir2_sf_toino8(a) ((void) 0) #define trace_xfs_da_node_create(a) ((void) 0) #define trace_xfs_da_split(a) ((void) 0) #define trace_xfs_attr_leaf_split_before(a) ((void) 0) #define trace_xfs_attr_leaf_split_after(a) ((void) 0) #define trace_xfs_da_root_split(a) ((void) 0) #define trace_xfs_da_node_split(a) ((void) 0) #define trace_xfs_da_node_rebalance(a) ((void) 0) #define trace_xfs_da_node_add(a) ((void) 0) #define trace_xfs_da_join(a) ((void) 0) #define trace_xfs_da_root_join(a) ((void) 0) #define trace_xfs_da_node_toosmall(a) ((void) 0) #define trace_xfs_da_fixhashpath(a) ((void) 0) #define trace_xfs_da_node_remove(a) ((void) 0) #define trace_xfs_da_node_unbalance(a) ((void) 0) #define trace_xfs_da_link_before(a) ((void) 0) #define trace_xfs_da_link_after(a) ((void) 0) #define trace_xfs_da_unlink_back(a) ((void) 0) #define trace_xfs_da_unlink_forward(a) ((void) 0) #define trace_xfs_da_path_shift(a) ((void) 0) #define trace_xfs_da_grow_inode(a) ((void) 0) #define trace_xfs_da_swap_lastblock(a) ((void) 0) #define trace_xfs_da_shrink_inode(a) ((void) 0) #define trace_xfs_attr_sf_create(a) ((void) 0) #define trace_xfs_attr_sf_add(a) ((void) 0) #define trace_xfs_attr_sf_remove(a) ((void) 0) #define trace_xfs_attr_sf_lookup(a) ((void) 0) #define trace_xfs_attr_sf_to_leaf(a) ((void) 0) #define trace_xfs_attr_leaf_to_sf(a) ((void) 0) #define trace_xfs_attr_leaf_to_node(a) ((void) 0) #define trace_xfs_attr_leaf_create(a) ((void) 0) #define trace_xfs_attr_leaf_split(a) ((void) 0) #define trace_xfs_attr_leaf_add_old(a) ((void) 0) #define trace_xfs_attr_leaf_add_new(a) ((void) 0) #define trace_xfs_attr_leaf_add(a) ((void) 0) #define trace_xfs_attr_leaf_add_work(a) ((void) 0) #define trace_xfs_attr_leaf_compact(a) ((void) 0) #define trace_xfs_attr_leaf_rebalance(a) ((void) 0) #define trace_xfs_attr_leaf_toosmall(a) ((void) 0) #define trace_xfs_attr_leaf_remove(a) ((void) 0) #define trace_xfs_attr_leaf_unbalance(a) ((void) 0) #define trace_xfs_attr_leaf_lookup(a) ((void) 0) #define trace_xfs_attr_leaf_clearflag(a) ((void) 0) #define trace_xfs_attr_leaf_setflag(a) ((void) 0) #define trace_xfs_attr_leaf_flipflags(a) ((void) 0) #define trace_xfs_attr_sf_addname(a) ((void) 0) #define trace_xfs_attr_leaf_addname(a) ((void) 0) #define trace_xfs_attr_leaf_replace(a) ((void) 0) #define trace_xfs_attr_leaf_removename(a) ((void) 0) #define trace_xfs_attr_leaf_get(a) ((void) 0) #define trace_xfs_attr_node_addname(a) ((void) 0) #define trace_xfs_attr_node_replace(a) ((void) 0) #define trace_xfs_attr_node_removename(a) ((void) 0) #define trace_xfs_attr_fillstate(a) ((void) 0) #define trace_xfs_attr_refillstate(a) ((void) 0) #define trace_xfs_attr_node_get(a) ((void) 0) #define trace_xfs_attr_rmtval_get(a) ((void) 0) #define trace_xfs_attr_rmtval_set(a) ((void) 0) #define trace_xfs_attr_rmtval_remove(a) ((void) 0) #define trace_xfs_bmap_pre_update(a,b,c,d) ((void) 0) #define trace_xfs_bmap_post_update(a,b,c,d) ((void) 0) #define trace_xfs_extlist(a,b,c,d) ((void) 0) #define trace_xfs_bunmap(a,b,c,d,e) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_put(a,b,c,d) ((c) = (c)) #define trace_xfs_defer_init(a,b) ((void) 0) #define trace_xfs_defer_cancel(a,b) ((void) 0) #define trace_xfs_defer_intake_work(a,b) ((void) 0) #define trace_xfs_defer_intake_cancel(a,b) ((void) 0) #define trace_xfs_defer_pending_commit(a,b) ((void) 0) #define trace_xfs_defer_pending_abort(a,b) ((void) 0) #define trace_xfs_defer_pending_cancel(a,b) ((void) 0) #define trace_xfs_defer_pending_finish(a,b) ((void) 0) #define trace_xfs_defer_trans_abort(a,b) ((void) 0) #define trace_xfs_defer_trans_roll(a,b) ((void) 0) #define trace_xfs_defer_trans_roll_error(a,b,c) ((void) 0) #define trace_xfs_defer_finish(a,b) ((void) 0) #define trace_xfs_defer_finish_error(a,b,c) ((void) 0) #define trace_xfs_defer_finish_done(a,b) ((void) 0) #define trace_xfs_bmap_free_defer(...) ((void) 0) #define trace_xfs_bmap_free_deferred(...) ((void) 0) #define trace_xfs_rmap_map(...) ((void) 0) #define trace_xfs_rmap_map_error(...) ((void) 0) #define trace_xfs_rmap_map_done(...) ((void) 0) #define trace_xfs_rmap_unmap(...) ((void) 0) #define trace_xfs_rmap_unmap_error(...) ((void) 0) #define trace_xfs_rmap_unmap_done(...) ((void) 0) #define trace_xfs_rmap_insert(...) ((void) 0) #define trace_xfs_rmap_insert_error(...) ((void) 0) #define trace_xfs_rmap_delete(...) ((void) 0) #define trace_xfs_rmap_convert(...) ((void) 0) #define trace_xfs_rmap_convert_state(...) ((void) 0) #define trace_xfs_rmap_convert_done(...) ((void) 0) #define trace_xfs_rmap_convert_error(...) ((void) 0) #define trace_xfs_rmap_update(...) ((void) 0) #define trace_xfs_rmap_update_error(...) ((void) 0) #define trace_xfs_rmap_defer(...) ((void) 0) #define trace_xfs_rmap_deferred(...) ((void) 0) #define trace_xfs_rmap_find_right_neighbor_result(...) ((void) 0) #define trace_xfs_rmap_find_left_neighbor_result(...) ((void) 0) #define trace_xfs_rmap_lookup_le_range_result(...) ((void) 0) #define trace_xfs_rmapbt_free_block(...) ((void) 0) #define trace_xfs_rmapbt_alloc_block(...) ((void) 0) #define trace_xfs_ag_resv_critical(...) ((void) 0) #define trace_xfs_ag_resv_needed(...) ((void) 0) #define trace_xfs_ag_resv_free(...) ((void) 0) #define trace_xfs_ag_resv_free_error(...) ((void) 0) #define trace_xfs_ag_resv_init(...) ((void) 0) #define trace_xfs_ag_resv_init_error(...) ((void) 0) #define trace_xfs_ag_resv_alloc_extent(...) ((void) 0) #define trace_xfs_ag_resv_free_extent(...) ((void) 0) #define trace_xfs_refcount_lookup(...) ((void) 0) #define trace_xfs_refcount_get(...) ((void) 0) #define trace_xfs_refcount_update(...) ((void) 0) #define trace_xfs_refcount_update_error(...) ((void) 0) #define trace_xfs_refcount_insert(...) ((void) 0) #define trace_xfs_refcount_insert_error(...) ((void) 0) #define trace_xfs_refcount_delete(...) ((void) 0) #define trace_xfs_refcount_delete_error(...) ((void) 0) #define trace_xfs_refcountbt_free_block(...) ((void) 0) #define trace_xfs_refcountbt_alloc_block(...) ((void) 0) #define trace_xfs_refcount_rec_order_error(...) ((void) 0) #define trace_xfs_refcount_lookup(...) ((void) 0) #define trace_xfs_refcount_get(...) ((void) 0) #define trace_xfs_refcount_update(...) ((void) 0) #define trace_xfs_refcount_update_error(...) ((void) 0) #define trace_xfs_refcount_insert(...) ((void) 0) #define trace_xfs_refcount_insert_error(...) ((void) 0) #define trace_xfs_refcount_delete(...) ((void) 0) #define trace_xfs_refcount_delete_error(...) ((void) 0) #define trace_xfs_refcountbt_free_block(...) ((void) 0) #define trace_xfs_refcountbt_alloc_block(...) ((void) 0) #define trace_xfs_refcount_rec_order_error(...) ((void) 0) #define trace_xfs_refcount_split_extent(...) ((void) 0) #define trace_xfs_refcount_split_extent_error(...) ((void) 0) #define trace_xfs_refcount_merge_center_extents_error(...) ((void) 0) #define trace_xfs_refcount_merge_left_extent_error(...) ((void) 0) #define trace_xfs_refcount_merge_right_extent_error(...) ((void) 0) #define trace_xfs_refcount_find_left_extent(...) ((void) 0) #define trace_xfs_refcount_find_left_extent_error(...) ((void) 0) #define trace_xfs_refcount_find_right_extent(...) ((void) 0) #define trace_xfs_refcount_find_right_extent_error(...) ((void) 0) #define trace_xfs_refcount_merge_center_extents(...) ((void) 0) #define trace_xfs_refcount_merge_left_extent(...) ((void) 0) #define trace_xfs_refcount_merge_right_extent(...) ((void) 0) #define trace_xfs_refcount_modify_extent(...) ((void) 0) #define trace_xfs_refcount_modify_extent_error(...) ((void) 0) #define trace_xfs_refcount_adjust_error(...) ((void) 0) #define trace_xfs_refcount_increase(...) ((void) 0) #define trace_xfs_refcount_decrease(...) ((void) 0) #define trace_xfs_refcount_deferred(...) ((void) 0) #define trace_xfs_refcount_defer(...) ((void) 0) #define trace_xfs_refcount_finish_one_leftover(...) ((void) 0) #define trace_xfs_refcount_find_shared(...) ((void) 0) #define trace_xfs_refcount_find_shared_result(...) ((void) 0) #define trace_xfs_refcount_find_shared_error(...) ((void) 0) #define trace_xfs_bmap_remap_alloc(...) ((void) 0) #define trace_xfs_bmap_remap_alloc_error(...) ((void) 0) #define trace_xfs_bmap_deferred(...) ((void) 0) #define trace_xfs_bmap_defer(...) ((void) 0) #define trace_xfs_refcount_adjust_cow_error(...) ((void) 0) #define trace_xfs_refcount_cow_increase(...) ((void) 0) #define trace_xfs_refcount_cow_decrease(...) ((void) 0) #define trace_xfs_refcount_recover_extent(...) ((void) 0) #define trace_xfs_rmap_find_left_neighbor_candidate(...) ((void) 0) #define trace_xfs_rmap_find_left_neighbor_query(...) ((void) 0) #define trace_xfs_rmap_find_left_neighbor_result(...) ((void) 0) #define trace_xfs_rmap_lookup_le_range_candidate(...) ((void) 0) #define trace_xfs_rmap_lookup_le_range(...) ((void) 0) #define trace_xfs_rmap_unmap(...) ((void) 0) #define trace_xfs_rmap_unmap_done(...) ((void) 0) #define trace_xfs_rmap_unmap_error(...) ((void) 0) #define trace_xfs_rmap_map(...) ((void) 0) #define trace_xfs_rmap_map_done(...) ((void) 0) #define trace_xfs_rmap_map_error(...) ((void) 0) #define trace_xfs_rmap_delete_error(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_put(a,b,c,d) ((c) = (c)) #endif /* __TRACE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xfs_trans.h0000644000000000000000000001233213063067171016276 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_TRANS_H__ #define __XFS_TRANS_H__ struct xfs_mount; struct xfs_buftarg; struct xfs_buf; struct xfs_buf_map; /* * Userspace Transaction interface */ typedef struct xfs_log_item { struct xfs_log_item_desc *li_desc; /* ptr to current desc*/ struct xfs_mount *li_mountp; /* ptr to fs mount */ uint li_type; /* item type */ xfs_lsn_t li_lsn; } xfs_log_item_t; typedef struct xfs_inode_log_item { xfs_log_item_t ili_item; /* common portion */ struct xfs_inode *ili_inode; /* inode pointer */ unsigned short ili_flags; /* misc flags */ unsigned int ili_fields; /* fields to be logged */ unsigned int ili_last_fields; /* fields when flushed*/ xfs_inode_log_format_t ili_format; /* logged structure */ } xfs_inode_log_item_t; typedef struct xfs_buf_log_item { xfs_log_item_t bli_item; /* common item structure */ struct xfs_buf *bli_buf; /* real buffer pointer */ unsigned int bli_flags; /* misc flags */ unsigned int bli_recur; /* recursion count */ xfs_buf_log_format_t bli_format; /* in-log header */ } xfs_buf_log_item_t; #define XFS_BLI_DIRTY (1<<0) #define XFS_BLI_HOLD (1<<1) #define XFS_BLI_STALE (1<<2) #define XFS_BLI_INODE_ALLOC_BUF (1<<3) typedef struct xfs_dq_logitem { xfs_log_item_t qli_item; /* common portion */ struct xfs_dquot *qli_dquot; /* dquot ptr */ xfs_lsn_t qli_flush_lsn; /* lsn at last flush */ xfs_dq_logformat_t qli_format; /* logged structure */ } xfs_dq_logitem_t; typedef struct xfs_qoff_logitem { xfs_log_item_t qql_item; /* common portion */ struct xfs_qoff_logitem *qql_start_lip; /* qoff-start logitem, if any */ xfs_qoff_logformat_t qql_format; /* logged structure */ } xfs_qoff_logitem_t; typedef struct xfs_trans { unsigned int t_type; /* transaction type */ unsigned int t_log_res; /* amt of log space resvd */ unsigned int t_log_count; /* count for perm log res */ unsigned int t_blk_res; /* # of blocks resvd */ struct xfs_mount *t_mountp; /* ptr to fs mount struct */ unsigned int t_flags; /* misc flags */ long t_icount_delta; /* superblock icount change */ long t_ifree_delta; /* superblock ifree change */ long t_fdblocks_delta; /* superblock fdblocks chg */ long t_frextents_delta; /* superblock freextents chg */ struct list_head t_items; /* first log item desc chunk */ } xfs_trans_t; void xfs_trans_init(struct xfs_mount *); int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); int libxfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp, uint blocks, uint rtextents, uint flags, struct xfs_trans **tpp); int libxfs_trans_commit(struct xfs_trans *); void libxfs_trans_cancel(struct xfs_trans *); struct xfs_buf *libxfs_trans_getsb(struct xfs_trans *, struct xfs_mount *, int); int libxfs_trans_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, uint, uint, struct xfs_inode **); void libxfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint); void libxfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, int); void libxfs_trans_log_inode (struct xfs_trans *, struct xfs_inode *, uint); void libxfs_trans_brelse(struct xfs_trans *, struct xfs_buf *); void libxfs_trans_binval(struct xfs_trans *, struct xfs_buf *); void libxfs_trans_bjoin(struct xfs_trans *, struct xfs_buf *); void libxfs_trans_bhold(struct xfs_trans *, struct xfs_buf *); void libxfs_trans_log_buf(struct xfs_trans *, struct xfs_buf *, uint, uint); struct xfs_buf *libxfs_trans_get_buf_map(struct xfs_trans *tp, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, uint flags); int libxfs_trans_read_buf_map(struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, uint flags, struct xfs_buf **bpp, const struct xfs_buf_ops *ops); static inline struct xfs_buf * libxfs_trans_get_buf( struct xfs_trans *tp, struct xfs_buftarg *btp, xfs_daddr_t blkno, int numblks, uint flags) { DEFINE_SINGLE_BUF_MAP(map, blkno, numblks); return libxfs_trans_get_buf_map(tp, btp, &map, 1, flags); } static inline int libxfs_trans_read_buf( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buftarg *btp, xfs_daddr_t blkno, int numblks, uint flags, struct xfs_buf **bpp, const struct xfs_buf_ops *ops) { DEFINE_SINGLE_BUF_MAP(map, blkno, numblks); return libxfs_trans_read_buf_map(mp, tp, btp, &map, 1, flags, bpp, ops); } void xfs_extent_free_init_defer_op(void); void xfs_rmap_update_init_defer_op(void); void xfs_refcount_update_init_defer_op(void); void xfs_bmap_update_init_defer_op(void); #endif /* __XFS_TRANS_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/include/xqm.h0000644000000000000000000001653613063067172015107 0ustar /* * Copyright (c) 1995, 2001, 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XQM_H__ #define __XQM_H__ #include /* * Disk quota - quotactl(2) commands for the XFS Quota Manager (XQM). */ #define XQM_CMD(x) (('X'<<8)+(x)) /* note: forms first QCMD argument */ #define Q_XQUOTAON XQM_CMD(1) /* enable accounting/enforcement */ #define Q_XQUOTAOFF XQM_CMD(2) /* disable accounting/enforcement */ #define Q_XGETQUOTA XQM_CMD(3) /* get disk limits and usage */ #define Q_XSETQLIM XQM_CMD(4) /* set disk limits */ #define Q_XGETQSTAT XQM_CMD(5) /* get quota subsystem status */ #define Q_XQUOTARM XQM_CMD(6) /* free disk space used by dquots */ #define Q_XQUOTASYNC XQM_CMD(7) /* delalloc flush, updates dquots */ #define Q_XGETQSTATV XQM_CMD(8) /* newer version of get quota */ #define Q_XGETNEXTQUOTA XQM_CMD(9) /* get disk limits and usage */ /* * fs_disk_quota structure: * * This contains the current quota information regarding a user/proj/group. * It is 64-bit aligned, and all the blk units are in BBs (Basic Blocks) of * 512 bytes. */ #define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */ typedef struct fs_disk_quota { __s8 d_version; /* version of this structure */ __s8 d_flags; /* XFS_{USER,PROJ,GROUP}_QUOTA */ __u16 d_fieldmask; /* field specifier */ __u32 d_id; /* user, project, or group ID */ __u64 d_blk_hardlimit;/* absolute limit on disk blks */ __u64 d_blk_softlimit;/* preferred limit on disk blks */ __u64 d_ino_hardlimit;/* maximum # allocated inodes */ __u64 d_ino_softlimit;/* preferred inode limit */ __u64 d_bcount; /* # disk blocks owned by the user */ __u64 d_icount; /* # inodes owned by the user */ __s32 d_itimer; /* zero if within inode limits */ /* if not, we refuse service */ __s32 d_btimer; /* similar to above; for disk blocks */ __u16 d_iwarns; /* # warnings issued wrt num inodes */ __u16 d_bwarns; /* # warnings issued wrt disk blocks */ __s32 d_padding2; /* padding2 - for future use */ __u64 d_rtb_hardlimit;/* absolute limit on realtime blks */ __u64 d_rtb_softlimit;/* preferred limit on RT disk blks */ __u64 d_rtbcount; /* # realtime blocks owned */ __s32 d_rtbtimer; /* similar to above; for RT disk blks */ __u16 d_rtbwarns; /* # warnings issued wrt RT disk blks */ __s16 d_padding3; /* padding3 - for future use */ char d_padding4[8]; /* yet more padding */ } fs_disk_quota_t; /* * These fields are sent to Q_XSETQLIM to specify fields that need to change. */ #define FS_DQ_ISOFT (1<<0) #define FS_DQ_IHARD (1<<1) #define FS_DQ_BSOFT (1<<2) #define FS_DQ_BHARD (1<<3) #define FS_DQ_RTBSOFT (1<<4) #define FS_DQ_RTBHARD (1<<5) #define FS_DQ_LIMIT_MASK (FS_DQ_ISOFT | FS_DQ_IHARD | FS_DQ_BSOFT | \ FS_DQ_BHARD | FS_DQ_RTBSOFT | FS_DQ_RTBHARD) /* * These timers can only be set in super user's dquot. For others, timers are * automatically started and stopped. Superusers timer values set the limits * for the rest. In case these values are zero, the DQ_{F,B}TIMELIMIT values * defined below are used. * These values also apply only to the d_fieldmask field for Q_XSETQLIM. */ #define FS_DQ_BTIMER (1<<6) #define FS_DQ_ITIMER (1<<7) #define FS_DQ_RTBTIMER (1<<8) #define FS_DQ_TIMER_MASK (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER) /* * Warning counts are set in both super user's dquot and others. For others, * warnings are set/cleared by the administrators (or automatically by going * below the soft limit). Superusers warning values set the warning limits * for the rest. In case these values are zero, the DQ_{F,B}WARNLIMIT values * defined below are used. * These values also apply only to the d_fieldmask field for Q_XSETQLIM. */ #define FS_DQ_BWARNS (1<<9) #define FS_DQ_IWARNS (1<<10) #define FS_DQ_RTBWARNS (1<<11) #define FS_DQ_WARNS_MASK (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS) /* * Various flags related to quotactl(2). Only relevant to XFS filesystems. */ #define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */ #define XFS_QUOTA_UDQ_ENFD (1<<1) /* user quota limits enforcement */ #define XFS_QUOTA_GDQ_ACCT (1<<2) /* group quota accounting */ #define XFS_QUOTA_GDQ_ENFD (1<<3) /* group quota limits enforcement */ #define XFS_QUOTA_PDQ_ACCT (1<<4) /* project quota accounting */ #define XFS_QUOTA_PDQ_ENFD (1<<5) /* project quota limits enforcement */ #define XFS_USER_QUOTA (1<<0) /* user quota type */ #define XFS_PROJ_QUOTA (1<<1) /* project quota type */ #define XFS_GROUP_QUOTA (1<<2) /* group quota type */ /* * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system. * Provides a centralized way to get meta information about the quota subsystem. * eg. space taken up for user and group quotas, number of dquots currently * incore. */ #define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */ /* * Some basic information about 'quota files'. */ typedef struct fs_qfilestat { __u64 qfs_ino; /* inode number */ __u64 qfs_nblks; /* number of BBs 512-byte-blks */ __u32 qfs_nextents; /* number of extents */ } fs_qfilestat_t; typedef struct fs_quota_stat { __s8 qs_version; /* version number for future changes */ __u16 qs_flags; /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */ __s8 qs_pad; /* unused */ fs_qfilestat_t qs_uquota; /* user quota storage information */ fs_qfilestat_t qs_gquota; /* group quota storage information */ __u32 qs_incoredqs; /* number of dquots incore */ __s32 qs_btimelimit; /* limit for blks timer */ __s32 qs_itimelimit; /* limit for inodes timer */ __s32 qs_rtbtimelimit;/* limit for rt blks timer */ __u16 qs_bwarnlimit; /* limit for num warnings */ __u16 qs_iwarnlimit; /* limit for num warnings */ } fs_quota_stat_t; #ifndef FS_QSTATV_VERSION1 #define FS_QSTATV_VERSION1 1 /* fs_quota_statv.qs_version */ #endif /* * Some basic information about 'quota files' for Q_XGETQSTATV command */ struct fs_qfilestatv { __u64 qfs_ino; /* inode number */ __u64 qfs_nblks; /* number of BBs 512-byte-blks */ __u32 qfs_nextents; /* number of extents */ __u32 qfs_pad; /* pad for 8-byte alignment */ }; struct fs_quota_statv { __s8 qs_version; /* version for future changes */ __u8 qs_pad1; /* pad for 16bit alignment */ __u16 qs_flags; /* FS_QUOTA_.* flags */ __u32 qs_incoredqs; /* number of dquots incore */ struct fs_qfilestatv qs_uquota; /* user quota information */ struct fs_qfilestatv qs_gquota; /* group quota information */ struct fs_qfilestatv qs_pquota; /* project quota information */ __s32 qs_btimelimit; /* limit for blks timer */ __s32 qs_itimelimit; /* limit for inodes timer */ __s32 qs_rtbtimelimit;/* limit for rt blks timer */ __u16 qs_bwarnlimit; /* limit for num warnings */ __u16 qs_iwarnlimit; /* limit for num warnings */ __u64 qs_pad2[8]; /* for future proofing */ }; #endif /* __XQM_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/install-sh0000755000000000000000000001544513063067167014514 0ustar #! /bin/bash # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # # This script emulates bsd install and also recognises # two environment variables, with the following semantics :- # # $DIST_MANIFEST - if set, the name of the file to append manifest # information in the following format: # File : f mode owner group src target # Directory: d mode owner group target # Symlink : l linkval target # # $DIST_ROOT - if set, prepend to target # # The sematics of all combinations of these two variables # are as follows: # # $DIST_MANIFEST? $DIST_ROOT? | Copy? Append Manifest? # -----------------------------+-------------------------- # not set not set | yes no # not set set | yes no # set not set | no yes # set set | yes yes # _usage() { echo "Usage: $prog [-o owner] [-g group] [-m mode] -d directory" echo "or $prog [-D] [-o owner] [-g group] [-m mode] file directory/file" echo "or $prog [-o owner] [-g group] [-m mode] file [file ...] directory" echo "or $prog -S file target (creates \"target\" symlink)" echo "or $prog -T lt_arg [-o owner] [-g group] [-m mode] libtool.lai directory" echo "" echo "The \$DIST_MANIFEST and \$DIST_ROOT environment variables affect the" echo "behaviour of this command - see comments in the script." echo "The -D flag is only available for the second usage, and causes" echo "the target directory to be created before installing the file." echo "" exit 1 } _chown () { _st=255 if [ $# -eq 3 ] ; then chown $1:$2 $3 _st=$? if [ $_st -ne 0 ] ; then if [ $REAL_UID != '0' ] ; then if [ ! -f $DIST_ROOT/.chown.quiet ] ; then echo '===============================================' echo Ownership of files under ${DIST_ROOT:-/} echo cannot be changed echo '===============================================' if [ -n "$DIST_ROOT" ] ; then touch $DIST_ROOT/.chown.quiet fi fi _st=0 fi fi fi return $_st } _manifest () { echo $* | sed -e 's/\/\//\//g' >>${DIST_MANIFEST:-/dev/null} } prog=`basename $0` HERE=`pwd` dflag=false Dflag=false Sflag=false Tflag=false DIRMODE=755 FILEMODE=644 OWNER=`id -u` GROUP=`id -g` REAL_UID=$OWNER # default is to install and don't append manifest INSTALL=true MANIFEST=: : ${DIST_ROOT:=${DESTDIR}} [ -n "$DIST_MANIFEST" -a -z "$DIST_ROOT" ] && INSTALL=false [ -n "$DIST_MANIFEST" ] && MANIFEST="_manifest" [ $# -eq 0 ] && _usage if $INSTALL then CP=cp; LN=ln; MKDIR=mkdir; CHMOD=chmod; CHOWN=_chown else CP=true; LN=true; MKDIR=true; CHMOD=true; CHOWN=true fi [ -n "$DIST_ROOT" -a $REAL_UID -ne 0 ] && CHOWN=true while getopts "Dcm:d:S:o:g:T:" c $* do case $c in c) ;; g) GROUP=$OPTARG ;; o) OWNER=$OPTARG ;; m) DIRMODE=`expr $OPTARG` FILEMODE=$DIRMODE ;; D) Dflag=true ;; S) symlink=$OPTARG Sflag=true ;; d) dir=$DIST_ROOT/$OPTARG dflag=true ;; T) lt_install=$OPTARG Tflag=true ;; *) _usage ;; esac done shift `expr $OPTIND - 1` status=0 if $dflag then # # first usage # $MKDIR -p $dir status=$? if [ $status -eq 0 ] then $CHMOD $DIRMODE $dir status=$? fi if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST d $DIRMODE $OWNER $GROUP ${dir#$DIST_ROOT} elif $Sflag then # # fourth usage (symlink) # if [ $# -ne 1 ] then _usage else target=$DIST_ROOT/$1 fi $LN -s -f $symlink $target status=$? $MANIFEST l $symlink ${target#$DIST_ROOT} elif $Tflag then # # -T (install libs built by libtool) # if [ $# -ne 2 ] then _usage else libtool_lai=$1 # source the libtool variables if [ ! -f $libtool_lai ] then echo "$prog: Unable to find libtool library file $libtool_lai" exit 2 fi . ./$libtool_lai target=$DIST_ROOT/$2 fi case $lt_install in so_dot_version) # Loop until we find libfoo.so.x.y.z, then break out. for solib in $library_names do # does it have enough parts? libfoo.so.x.y.z == 5 cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq 5 ] then install_name=$target/$solib $CP $solib $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$solib ${install_name#$DIST_ROOT} break fi done ;; so_*) case $lt_install in so_dot_current) # ln -s libfoo.so.x.y.z to libfoo.so.x from_parts=5 # libfoo.so.x.y.z to_parts=3 # libfoo.so.x ;; so_base) # ln -s libfoo.so.x to libfoo.so from_parts=3 # libfoo.so.x to_parts=2 # libfoo.so ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac # Loop until we find the names, then break out. for solib in $library_names do # does it have enough parts? cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq $from_parts ] then from_name=$solib elif [ $cnt -eq $to_parts ] then to_name=$solib fi if [ -n "$from_name" ] && [ -n "$to_name" ] then install_name=$target/$to_name $LN -s -f $from_name $install_name status=$? $MANIFEST l $from_name ${install_name#$DIST_ROOT} break fi done ;; old_lib) install_name=$target/$old_library $CP $old_library $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$old_library ${install_name#$DIST_ROOT} ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac case $lt_install in old_lib|so_dot_version) if [ $status -eq 0 ] then $CHMOD $FILEMODE $install_name $CHOWN $OWNER $GROUP $install_name fi ;; esac else list="" dir="" if [ $# -eq 2 ] then # # second usage # f=$1 dir=$DIST_ROOT/$2 if $Dflag then mkdir -p `dirname $dir` fi $CP $f $dir status=$? if [ $status -eq 0 ] then if [ -f $dir/$f ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f else $CHMOD $FILEMODE $dir status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$dir ${dir#$DIST_ROOT} fi fi else # # third usage # n=1 while [ $# -gt 0 ] do if [ $# -gt 1 ] then list="$list $1" else dir=$DIST_ROOT/$1 fi shift done # echo DIR=$dir list=\"$list\" for f in $list do $CP $f $dir status=$? if [ $status -eq 0 ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f fi [ $status -ne 0 ] && break done fi fi exit $status xfsprogs-4.9.0+nmu1ubuntu2/io/0000755000000000000000000000000013265564513013107 5ustar xfsprogs-4.9.0+nmu1ubuntu2/io/Makefile0000644000000000000000000000440213063067173014543 0ustar # # Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_io LSRCFILES = xfs_bmap.sh xfs_freeze.sh xfs_mkfile.sh HFILES = init.h io.h CFILES = init.c \ attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c link.c \ mmap.c open.c parent.c pread.c prealloc.c pwrite.c seek.c shutdown.c \ sync.c truncate.c reflink.c cowextsize.c LLDLIBS = $(LIBXCMD) $(LIBHANDLE) $(LIBPTHREAD) LTDEPENDENCIES = $(LIBXCMD) $(LIBHANDLE) LLDFLAGS = -static-libtool-libs ifeq ($(HAVE_FADVISE),yes) CFILES += fadvise.c LCFLAGS += -DHAVE_FADVISE else LSRCFILES += fadvise.c endif ifeq ($(HAVE_MADVISE),yes) CFILES += madvise.c LCFLAGS += -DHAVE_MADVISE else LSRCFILES += madvise.c endif ifeq ($(HAVE_MINCORE),yes) CFILES += mincore.c LCFLAGS += -DHAVE_MINCORE else LSRCFILES += mincore.c endif ifeq ($(HAVE_SENDFILE),yes) CFILES += sendfile.c LCFLAGS += -DHAVE_SENDFILE else LSRCFILES += sendfile.c endif ifeq ($(HAVE_FIEMAP),yes) CFILES += fiemap.c LCFLAGS += -DHAVE_FIEMAP else LSRCFILES += fiemap.c endif ifeq ($(PKG_PLATFORM),irix) LSRCFILES += inject.c resblks.c else CFILES += inject.c resblks.c LCFLAGS += -DHAVE_INJECT -DHAVE_RESBLKS endif ifeq ($(HAVE_COPY_FILE_RANGE),yes) CFILES += copy_file_range.c LCFLAGS += -DHAVE_COPY_FILE_RANGE endif ifeq ($(HAVE_SYNC_FILE_RANGE),yes) CFILES += sync_file_range.c LCFLAGS += -DHAVE_SYNC_FILE_RANGE endif ifeq ($(HAVE_SYNCFS),yes) LCFLAGS += -DHAVE_SYNCFS endif ifeq ($(ENABLE_READLINE),yes) LLDLIBS += $(LIBREADLINE) $(LIBTERMCAP) endif ifeq ($(ENABLE_EDITLINE),yes) LLDLIBS += $(LIBEDITLINE) $(LIBTERMCAP) endif ifeq ($(HAVE_FALLOCATE),yes) LCFLAGS += -DHAVE_FALLOCATE endif # Also implies PWRITEV ifeq ($(HAVE_PREADV),yes) LCFLAGS += -DHAVE_PREADV -DHAVE_PWRITEV endif ifeq ($(HAVE_READDIR),yes) CFILES += readdir.c LCFLAGS += -DHAVE_READDIR endif ifeq ($(HAVE_MREMAP),yes) LCFLAGS += -DHAVE_MREMAP endif default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 xfs_bmap.sh $(PKG_SBIN_DIR)/xfs_bmap $(LTINSTALL) -m 755 xfs_freeze.sh $(PKG_SBIN_DIR)/xfs_freeze $(LTINSTALL) -m 755 xfs_mkfile.sh $(PKG_SBIN_DIR)/xfs_mkfile install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/io/attr.c0000644000000000000000000002346413136024635014227 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t chattr_cmd; static cmdinfo_t lsattr_cmd; static unsigned int orflags; static unsigned int andflags; unsigned int recurse_all; unsigned int recurse_dir; static struct xflags { uint flag; char *shortname; char *longname; } xflags[] = { { FS_XFLAG_REALTIME, "r", "realtime" }, { FS_XFLAG_PREALLOC, "p", "prealloc" }, { FS_XFLAG_IMMUTABLE, "i", "immutable" }, { FS_XFLAG_APPEND, "a", "append-only" }, { FS_XFLAG_SYNC, "s", "sync" }, { FS_XFLAG_NOATIME, "A", "no-atime" }, { FS_XFLAG_NODUMP, "d", "no-dump" }, { FS_XFLAG_RTINHERIT, "t", "rt-inherit" }, { FS_XFLAG_PROJINHERIT, "P", "proj-inherit" }, { FS_XFLAG_NOSYMLINKS, "n", "nosymlinks" }, { FS_XFLAG_EXTSIZE, "e", "extsize" }, { FS_XFLAG_EXTSZINHERIT, "E", "extsz-inherit" }, { FS_XFLAG_NODEFRAG, "f", "no-defrag" }, { FS_XFLAG_FILESTREAM, "S", "filestream" }, { FS_XFLAG_DAX, "x", "dax" }, { FS_XFLAG_COWEXTSIZE, "C", "cowextsize" }, { 0, NULL, NULL } }; #define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSxC" static void lsattr_help(void) { printf(_( "\n" " displays the set of extended inode flags associated with the current file\n" "\n" " Each individual flag is displayed as a single character, in this order:\n" " r -- file data is stored in the realtime section\n" " p -- file has preallocated extents (cannot be changed using chattr)\n" " i -- immutable, file cannot be modified\n" " a -- append-only, file can only be appended to\n" " s -- all updates are synchronous\n" " A -- the access time is not updated for this inode\n" " d -- do not include this file in a dump of the filesystem\n" " t -- child created in this directory has realtime bit set by default\n" " P -- child created in this directory has parents project ID by default\n" " n -- symbolic links cannot be created in this directory\n" " e -- for non-realtime files, observe the inode extent size value\n" " E -- children created in this directory inherit the extent size value\n" " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" " x -- Use direct access (DAX) for data in this file\n" " C -- for files with shared blocks, observe the inode CoW extent size value\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, but only list attributes on directories\n" " -a -- show all flags which can be set alongside those which are set\n" " -v -- verbose mode; show long names of flags, not single characters\n" "\n")); } static void chattr_help(void) { printf(_( "\n" " modifies the set of extended inode flags associated with the current file\n" "\n" " Examples:\n" " 'chattr +a' - sets the append-only flag\n" " 'chattr -a' - clears the append-only flag\n" "\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, only modifying attributes on directories\n" " +/-r -- set/clear the realtime flag\n" " +/-i -- set/clear the immutable flag\n" " +/-a -- set/clear the append-only flag\n" " +/-s -- set/clear the sync flag\n" " +/-A -- set/clear the no-atime flag\n" " +/-d -- set/clear the no-dump flag\n" " +/-t -- set/clear the realtime inheritance flag\n" " +/-P -- set/clear the project ID inheritance flag\n" " +/-n -- set/clear the no-symbolic-links flag\n" " +/-e -- set/clear the extent-size flag\n" " +/-E -- set/clear the extent-size inheritance flag\n" " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " +/-x -- set/clear the direct access (DAX) flag\n" " +/-C -- set/clear the CoW extent-size flag\n" " Note1: user must have certain capabilities to modify immutable/append-only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" " Note3: the realtime flag can only be set if the filesystem has a realtime\n" " section, and the (regular) file must be empty when the flag is set.\n" "\n")); } void printxattr( uint flags, int verbose, int dofname, const char *fname, int dobraces, int doeol) { struct xflags *p; int first = 1; if (dobraces) fputs("[", stdout); for (p = xflags; p->flag; p++) { if (flags & p->flag) { if (verbose) { if (first) first = 0; else fputs(", ", stdout); fputs(p->longname, stdout); } else { fputs(p->shortname, stdout); } } else if (!verbose) { fputs("-", stdout); } } if (dobraces) fputs("]", stdout); if (dofname) printf(" %s ", fname); if (doeol) fputs("\n", stdout); } static int lsattr_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { struct fsxattr fsx; int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; if ((fd = open(path, O_RDONLY)) == -1) fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); else if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) fprintf(stderr, _("%s: cannot get flags on %s: %s\n"), progname, path, strerror(errno)); else printxattr(fsx.fsx_xflags, 0, 1, path, 0, 1); if (fd != -1) close(fd); return 0; } static int lsattr_f( int argc, char **argv) { struct fsxattr fsx; char *name = file->name; int c, aflag = 0, vflag = 0; recurse_all = recurse_dir = 0; while ((c = getopt(argc, argv, "DRav")) != EOF) { switch (c) { case 'D': recurse_all = 0; recurse_dir = 1; break; case 'R': recurse_all = 1; recurse_dir = 0; break; case 'a': aflag = 1; vflag = 0; break; case 'v': aflag = 0; vflag = 1; break; default: return command_usage(&lsattr_cmd); } } if (recurse_all || recurse_dir) { nftw(name, lsattr_callback, 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); } else if ((xfsctl(name, file->fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { fprintf(stderr, _("%s: cannot get flags on %s: %s\n"), progname, name, strerror(errno)); } else { printxattr(fsx.fsx_xflags, vflag, !aflag, name, vflag, !aflag); if (aflag) { fputs("/", stdout); printxattr(-1, 0, 1, name, 0, 1); } } return 0; } static int chattr_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { struct fsxattr attr; int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; if ((fd = open(path, O_RDONLY)) == -1) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &attr) < 0) { fprintf(stderr, _("%s: cannot get flags on %s: %s\n"), progname, path, strerror(errno)); } else { attr.fsx_xflags |= orflags; attr.fsx_xflags &= ~andflags; if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &attr) < 0) fprintf(stderr, _("%s: cannot set flags on %s: %s\n"), progname, path, strerror(errno)); } if (fd != -1) close(fd); return 0; } static int chattr_f( int argc, char **argv) { struct fsxattr attr; struct xflags *p; unsigned int i = 0; char *c, *name = file->name; orflags = andflags = 0; recurse_all = recurse_dir = 0; while (++i < argc) { if (argv[i][0] == '-' && argv[i][1] == 'R') { recurse_all = 1; } else if (argv[i][0] == '-' && argv[i][1] == 'D') { recurse_dir = 1; } else if (argv[i][0] == '+') { for (c = &argv[i][1]; *c; c++) { for (p = xflags; p->flag; p++) { if (strncmp(p->shortname, c, 1) == 0) { orflags |= p->flag; break; } } if (!p->flag) { fprintf(stderr, _("%s: unknown flag\n"), progname); return 0; } } } else if (argv[i][0] == '-') { for (c = &argv[i][1]; *c; c++) { for (p = xflags; p->flag; p++) { if (strncmp(p->shortname, c, 1) == 0) { andflags |= p->flag; break; } } if (!p->flag) { fprintf(stderr, _("%s: unknown flag\n"), progname); return 0; } } } else { fprintf(stderr, _("%s: bad chattr command, not +/-X\n"), progname); return 0; } } if (recurse_all || recurse_dir) { nftw(name, chattr_callback, 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); } else if (xfsctl(name, file->fd, FS_IOC_FSGETXATTR, &attr) < 0) { fprintf(stderr, _("%s: cannot get flags on %s: %s\n"), progname, name, strerror(errno)); } else { attr.fsx_xflags |= orflags; attr.fsx_xflags &= ~andflags; if (xfsctl(name, file->fd, FS_IOC_FSSETXATTR, &attr) < 0) fprintf(stderr, _("%s: cannot set flags on %s: %s\n"), progname, name, strerror(errno)); } return 0; } void attr_init(void) { chattr_cmd.name = "chattr"; chattr_cmd.cfunc = chattr_f; chattr_cmd.args = _("[-R|-D] [+/-"CHATTR_XFLAG_LIST"]"); chattr_cmd.argmin = 1; chattr_cmd.argmax = -1; chattr_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; chattr_cmd.oneline = _("change extended inode flags on the currently open file"); chattr_cmd.help = chattr_help; lsattr_cmd.name = "lsattr"; lsattr_cmd.cfunc = lsattr_f; lsattr_cmd.args = _("[-R|-D|-a|-v]"); lsattr_cmd.argmin = 0; lsattr_cmd.argmax = 1; lsattr_cmd.flags = CMD_NOMAP_OK; lsattr_cmd.oneline = _("list extended inode flags set on the currently open file"); lsattr_cmd.help = lsattr_help; add_command(&chattr_cmd); add_command(&lsattr_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/bmap.c0000644000000000000000000003240413063067173014171 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "command.h" #include "init.h" #include "io.h" static cmdinfo_t bmap_cmd; static void bmap_help(void) { printf(_( "\n" " prints the block mapping for an XFS file's data or attribute forks" "\n" " Example:\n" " 'bmap -vp' - tabular format verbose map, including unwritten extents\n" "\n" " bmap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -c -- prints the copy-on-write fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" " -e -- print delayed allocation extents.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are unwritten.)\n" " -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" " Note: the bmap for non-regular files can be obtained provided the file\n" " was opened appropriately (in particular, must be opened read-only).\n" "\n")); } static int numlen( off64_t val) { off64_t tmp; int len; for (len = 0, tmp = val; tmp > 0; tmp = tmp/10) len++; return (len == 0 ? 1 : len); } int bmap_f( int argc, char **argv) { struct fsxattr fsx; struct getbmapx *map; struct xfs_fsop_geom fsgeo; int map_size; int loop = 0; int flg = 0; int aflag = 0; int cflag = 0; int lflag = 0; int nflag = 0; int pflag = 0; int vflag = 0; int is_rt = 0; int bmv_iflags = 0; /* flags for XFS_IOC_GETBMAPX */ int i = 0; int c; int egcnt; while ((c = getopt(argc, argv, "acdeln:pv")) != EOF) { switch (c) { case 'a': /* Attribute fork. */ bmv_iflags |= BMV_IF_ATTRFORK; aflag = 1; break; case 'c': /* CoW fork. */ bmv_iflags |= BMV_IF_COWFORK | BMV_IF_DELALLOC; cflag = 1; break; case 'e': bmv_iflags |= BMV_IF_DELALLOC; break; case 'l': /* list number of blocks with each extent */ lflag = 1; break; case 'n': /* number of extents specified */ nflag = atoi(optarg); break; case 'd': /* do not recall possibly offline DMAPI files */ bmv_iflags |= BMV_IF_NO_DMAPI_READ; break; case 'p': /* report unwritten preallocated blocks */ pflag = 1; bmv_iflags |= BMV_IF_PREALLOC; break; case 'v': /* Verbose output */ vflag++; break; default: return command_usage(&bmap_cmd); } } if (aflag || cflag) bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ); if (vflag) { c = xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo); if (c < 0) { fprintf(stderr, _("%s: can't get geometry [\"%s\"]: %s\n"), progname, file->name, strerror(errno)); exitcode = 1; return 0; } c = xfsctl(file->name, file->fd, FS_IOC_FSGETXATTR, &fsx); if (c < 0) { fprintf(stderr, _("%s: cannot read attrs on \"%s\": %s\n"), progname, file->name, strerror(errno)); exitcode = 1; return 0; } if (fsx.fsx_xflags == FS_XFLAG_REALTIME) { /* * ag info not applicable to rt, continue * without ag output. */ is_rt = 1; } } map_size = nflag ? nflag+2 : 32; /* initial guess - 32 */ map = malloc(map_size*sizeof(*map)); if (map == NULL) { fprintf(stderr, _("%s: malloc of %d bytes failed.\n"), progname, (int)(map_size * sizeof(*map))); exitcode = 1; return 0; } /* Try the xfsctl(XFS_IOC_GETBMAPX) for the number of extents specified * by nflag, or the initial guess number of extents (32). * * If there are more extents than we guessed, use xfsctl * (FS_IOC_FSGETXATTR[A]) to get the extent count, realloc some more * space based on this count, and try again. * * If the initial FGETBMAPX attempt returns EINVAL, this may mean * that we tried the FGETBMAPX on a zero length file. If we get * EINVAL, check the length with fstat() and return "no extents" * if the length == 0. * * Why not do the xfsctl(FS_IOC_FSGETXATTR[A]) first? Two reasons: * (1) The extent count may be wrong for a file with delayed * allocation blocks. The XFS_IOC_GETBMAPX forces the real * allocation and fixes up the extent count. * (2) For XFS_IOC_GETBMAP[X] on a DMAPI file that has been moved * offline by a DMAPI application (e.g., DMF) the * FS_IOC_FSGETXATTR only reflects the extents actually online. * Doing XFS_IOC_GETBMAPX call first forces that data blocks online * and then everything proceeds normally (see PV #545725). * * If you don't want this behavior on a DMAPI offline file, * try the "-d" option which sets the BMV_IF_NO_DMAPI_READ * iflag for XFS_IOC_GETBMAPX. */ do { /* loop a miximum of two times */ memset(map, 0, sizeof(*map)); /* zero header */ map->bmv_length = -1; map->bmv_count = map_size; map->bmv_iflags = bmv_iflags; i = xfsctl(file->name, file->fd, XFS_IOC_GETBMAPX, map); if (i < 0) { if ( errno == EINVAL && !aflag && filesize() == 0) { break; } else { fprintf(stderr, _("%s: xfsctl(XFS_IOC_GETBMAPX)" " iflags=0x%x [\"%s\"]: %s\n"), progname, map->bmv_iflags, file->name, strerror(errno)); free(map); exitcode = 1; return 0; } } if (nflag) break; if (map->bmv_entries < map->bmv_count-1) break; /* Get number of extents from xfsctl FS_IOC_FSGETXATTR[A] * syscall. */ i = xfsctl(file->name, file->fd, aflag ? XFS_IOC_FSGETXATTRA : FS_IOC_FSGETXATTR, &fsx); if (i < 0) { fprintf(stderr, "%s: xfsctl(FS_IOC_FSGETXATTR%s) " "[\"%s\"]: %s\n", progname, aflag ? "A" : "", file->name, strerror(errno)); free(map); exitcode = 1; return 0; } if (2 * fsx.fsx_nextents > map_size) { map_size = 2 * fsx.fsx_nextents + 1; map = realloc(map, map_size*sizeof(*map)); if (map == NULL) { fprintf(stderr, _("%s: cannot realloc %d bytes\n"), progname, (int)(map_size*sizeof(*map))); exitcode = 1; return 0; } } } while (++loop < 2); if (!nflag) { if (map->bmv_entries <= 0) { printf(_("%s: no extents\n"), file->name); free(map); return 0; } } egcnt = nflag ? min(nflag, map->bmv_entries) : map->bmv_entries; printf("%s:\n", file->name); if (!vflag) { for (i = 0; i < egcnt; i++) { printf("\t%d: [%lld..%lld]: ", i, (long long) map[i + 1].bmv_offset, (long long)(map[i + 1].bmv_offset + map[i + 1].bmv_length - 1LL)); if (map[i + 1].bmv_block == -1) printf(_("hole")); else if (map[i + 1].bmv_block == -2) printf(_("delalloc")); else { printf("%lld..%lld", (long long) map[i + 1].bmv_block, (long long)(map[i + 1].bmv_block + map[i + 1].bmv_length - 1LL)); } if (lflag) printf(_(" %lld blocks\n"), (long long)map[i+1].bmv_length); else printf("\n"); } } else { /* * Verbose mode displays: * extent: [startoffset..endoffset]: startblock..endblock \ * ag# (agoffset..agendoffset) totalbbs */ #define MINRANGE_WIDTH 16 #define MINAG_WIDTH 2 #define MINTOT_WIDTH 5 #define NFLG 6 /* count of flags */ #define FLG_NULL 0000000 /* Null flag */ #define FLG_SHARED 0100000 /* shared extent */ #define FLG_PRE 0010000 /* Unwritten extent */ #define FLG_BSU 0001000 /* Not on begin of stripe unit */ #define FLG_ESU 0000100 /* Not on end of stripe unit */ #define FLG_BSW 0000010 /* Not on begin of stripe width */ #define FLG_ESW 0000001 /* Not on end of stripe width */ int agno; off64_t agoff, bbperag; int foff_w, boff_w, aoff_w, tot_w, agno_w; char rbuf[32], bbuf[32], abuf[32]; int sunit, swidth; foff_w = boff_w = aoff_w = MINRANGE_WIDTH; tot_w = MINTOT_WIDTH; if (is_rt) sunit = swidth = bbperag = 0; else { bbperag = (off64_t)fsgeo.agblocks * (off64_t)fsgeo.blocksize / BBSIZE; sunit = (fsgeo.sunit * fsgeo.blocksize) / BBSIZE; swidth = (fsgeo.swidth * fsgeo.blocksize) / BBSIZE; } flg = sunit | pflag; /* * Go through the extents and figure out the width * needed for all columns. */ for (i = 0; i < egcnt; i++) { snprintf(rbuf, sizeof(rbuf), "[%lld..%lld]:", (long long) map[i + 1].bmv_offset, (long long)(map[i + 1].bmv_offset + map[i + 1].bmv_length - 1LL)); if (map[i + 1].bmv_oflags & BMV_OF_PREALLOC) flg = 1; if (map[i + 1].bmv_block == -1) { foff_w = max(foff_w, strlen(rbuf)); tot_w = max(tot_w, numlen(map[i+1].bmv_length)); } else { snprintf(bbuf, sizeof(bbuf), "%lld..%lld", (long long) map[i + 1].bmv_block, (long long)(map[i + 1].bmv_block + map[i + 1].bmv_length - 1LL)); boff_w = max(boff_w, strlen(bbuf)); if (!is_rt) { agno = map[i + 1].bmv_block / bbperag; agoff = map[i + 1].bmv_block - (agno * bbperag); snprintf(abuf, sizeof(abuf), "(%lld..%lld)", (long long)agoff, (long long)(agoff + map[i + 1].bmv_length - 1LL)); aoff_w = max(aoff_w, strlen(abuf)); } else aoff_w = 0; foff_w = max(foff_w, strlen(rbuf)); tot_w = max(tot_w, numlen(map[i+1].bmv_length)); } } agno_w = is_rt ? 0 : max(MINAG_WIDTH, numlen(fsgeo.agcount)); printf("%4s: %-*s %-*s %*s %-*s %*s%s\n", _("EXT"), foff_w, _("FILE-OFFSET"), boff_w, is_rt ? _("RT-BLOCK-RANGE") : _("BLOCK-RANGE"), agno_w, is_rt ? "" : _("AG"), aoff_w, is_rt ? "" : _("AG-OFFSET"), tot_w, _("TOTAL"), flg ? _(" FLAGS") : ""); for (i = 0; i < egcnt; i++) { flg = FLG_NULL; if (map[i + 1].bmv_oflags & BMV_OF_PREALLOC) { flg |= FLG_PRE; } if (map[i + 1].bmv_oflags & BMV_OF_SHARED) flg |= FLG_SHARED; if (map[i + 1].bmv_oflags & BMV_OF_DELALLOC) map[i + 1].bmv_block = -2; /* * If striping enabled, determine if extent starts/ends * on a stripe unit boundary. */ if (sunit) { if (map[i + 1].bmv_block % sunit != 0) { flg |= FLG_BSU; } if (((map[i + 1].bmv_block + map[i + 1].bmv_length ) % sunit ) != 0) { flg |= FLG_ESU; } if (map[i + 1].bmv_block % swidth != 0) { flg |= FLG_BSW; } if (((map[i + 1].bmv_block + map[i + 1].bmv_length ) % swidth ) != 0) { flg |= FLG_ESW; } } snprintf(rbuf, sizeof(rbuf), "[%lld..%lld]:", (long long) map[i + 1].bmv_offset, (long long)(map[i + 1].bmv_offset + map[i + 1].bmv_length - 1LL)); if (map[i + 1].bmv_block == -1) { printf("%4d: %-*s %-*s %*s %-*s %*lld\n", i, foff_w, rbuf, boff_w, _("hole"), agno_w, "", aoff_w, "", tot_w, (long long)map[i+1].bmv_length); } else if (map[i + 1].bmv_block == -2) { printf("%4d: %-*s %-*s %*s %-*s %*lld\n", i, foff_w, rbuf, boff_w, _("delalloc"), agno_w, "", aoff_w, "", tot_w, (long long)map[i+1].bmv_length); } else { snprintf(bbuf, sizeof(bbuf), "%lld..%lld", (long long) map[i + 1].bmv_block, (long long)(map[i + 1].bmv_block + map[i + 1].bmv_length - 1LL)); printf("%4d: %-*s %-*s", i, foff_w, rbuf, boff_w, bbuf); if (!is_rt) { agno = map[i + 1].bmv_block / bbperag; agoff = map[i + 1].bmv_block - (agno * bbperag); snprintf(abuf, sizeof(abuf), "(%lld..%lld)", (long long)agoff, (long long)(agoff + map[i + 1].bmv_length - 1LL)); printf(" %*d %-*s", agno_w, agno, aoff_w, abuf); } else printf(" "); printf(" %*lld", tot_w, (long long)map[i+1].bmv_length); if (flg == FLG_NULL && !pflag) { printf("\n"); } else { printf(" %-*.*o\n", NFLG, NFLG, flg); } } } if ((flg || pflag) && vflag > 1) { printf(_(" FLAG Values:\n")); printf(_(" %*.*o Shared extent\n"), NFLG+1, NFLG+1, FLG_SHARED); printf(_(" %*.*o Unwritten preallocated extent\n"), NFLG+1, NFLG+1, FLG_PRE); printf(_(" %*.*o Doesn't begin on stripe unit\n"), NFLG+1, NFLG+1, FLG_BSU); printf(_(" %*.*o Doesn't end on stripe unit\n"), NFLG+1, NFLG+1, FLG_ESU); printf(_(" %*.*o Doesn't begin on stripe width\n"), NFLG+1, NFLG+1, FLG_BSW); printf(_(" %*.*o Doesn't end on stripe width\n"), NFLG+1, NFLG+1, FLG_ESW); } } free(map); return 0; } void bmap_init(void) { bmap_cmd.name = "bmap"; bmap_cmd.cfunc = bmap_f; bmap_cmd.argmin = 0; bmap_cmd.argmax = -1; bmap_cmd.flags = CMD_NOMAP_OK; bmap_cmd.args = _("[-adlpv] [-n nx]"); bmap_cmd.oneline = _("print block mapping for an XFS file"); bmap_cmd.help = bmap_help; add_command(&bmap_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/copy_file_range.c0000644000000000000000000000656013265564513016407 0ustar /* * Copyright (c) 2016 Netapp, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t copy_range_cmd; static void copy_range_help(void) { printf(_("\n\ Copies a range of bytes from a file into the open file, overwriting any data\n\ already there.\n\ \n\ Example:\n\ 'copy_range -s 100 -d 200 -l 300 some_file' - copies 300 bytes from some_file\n\ at offset 100 into the open\n\ file at offset 200\n\ 'copy_range some_file' - copies all bytes from some_file into the open file\n\ at position 0\n\ ")); } static loff_t copy_file_range_cmd(int fd, loff_t *src, loff_t *dst, size_t len) { loff_t ret; do { ret = syscall(__NR_copy_file_range, fd, src, file->fd, dst, len, 0); if (ret == -1) return errno; len -= ret; } while (len > 0); return 0; } static off64_t copy_src_filesize(int fd) { struct stat st; if (fstat(fd, &st) < 0) { perror("fstat"); return -1; }; return st.st_size; } static int copy_dst_truncate(void) { int ret = ftruncate(file->fd, 0); if (ret < 0) perror("ftruncate"); return ret; } static int copy_range_f(int argc, char **argv) { loff_t src = 0; loff_t dst = 0; size_t len = 0; char *sp; int opt; int ret; int fd; while ((opt = getopt(argc, argv, "s:d:l:")) != -1) { switch (opt) { case 's': src = strtoull(optarg, &sp, 10); if (!sp || sp == optarg) { printf(_("invalid source offset -- %s\n"), sp); return 0; } break; case 'd': dst = strtoull(optarg, &sp, 10); if (!sp || sp == optarg) { printf(_("invalid destination offset -- %s\n"), sp); return 0; } break; case 'l': len = strtoull(optarg, &sp, 10); if (!sp || sp == optarg) { printf(_("invalid length -- %s\n"), sp); return 0; } break; } } if (optind != argc - 1) return command_usage(©_range_cmd); fd = openfile(argv[optind], NULL, IO_READONLY, 0); if (fd < 0) return 0; if (src == 0 && dst == 0 && len == 0) { len = copy_src_filesize(fd); copy_dst_truncate(); } ret = copy_file_range_cmd(fd, &src, &dst, len); close(fd); return ret; } void copy_range_init(void) { copy_range_cmd.name = "copy_range"; copy_range_cmd.cfunc = copy_range_f; copy_range_cmd.argmin = 1; copy_range_cmd.argmax = 7; copy_range_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; copy_range_cmd.args = _("[-s src_off] [-d dst_off] [-l len] src_file"); copy_range_cmd.oneline = _("Copy a range of data between two files"); copy_range_cmd.help = copy_range_help; add_command(©_range_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/cowextsize.c0000644000000000000000000001112513033541503015442 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ /* * If configure didn't find a struct fsxattr with fsx_cowextsize, * disable the only other source (so far) of struct fsxattr. Thus, * build with the internal definition of struct fsxattr, which has * fsx_cowextsize. */ #include "platform_defs.h" #include "command.h" #include "init.h" #include "io.h" #include "input.h" #include "path.h" static cmdinfo_t cowextsize_cmd; static long cowextsize; static void cowextsize_help(void) { printf(_( "\n" " report or modify preferred CoW extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying cowextsize on directories\n" "\n")); } static int get_cowextsize(const char *path, int fd) { struct fsxattr fsx; if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) { printf("%s: XFS_IOC_FSGETXATTR %s: %s\n", progname, path, strerror(errno)); return 0; } printf("[%u] %s\n", fsx.fsx_cowextsize, path); return 0; } static int set_cowextsize(const char *path, int fd, long extsz) { struct fsxattr fsx; struct stat64 stat; if (fstat64(fd, &stat) < 0) { perror("fstat64"); return 0; } if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) { printf("%s: XFS_IOC_FSGETXATTR %s: %s\n", progname, path, strerror(errno)); return 0; } if (S_ISREG(stat.st_mode) || S_ISDIR(stat.st_mode)) { fsx.fsx_xflags |= FS_XFLAG_COWEXTSIZE; } else { printf(_("invalid target file type - file %s\n"), path); return 0; } fsx.fsx_cowextsize = extsz; if ((xfsctl(path, fd, XFS_IOC_FSSETXATTR, &fsx)) < 0) { printf("%s: XFS_IOC_FSSETXATTR %s: %s\n", progname, path, strerror(errno)); return 0; } return 0; } static int get_cowextsize_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; fd = open(path, O_RDONLY); if (fd < 0) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else { get_cowextsize(path, fd); close(fd); } return 0; } static int set_cowextsize_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; fd = open(path, O_RDONLY); if (fd < 0) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else { set_cowextsize(path, fd, cowextsize); close(fd); } return 0; } static int cowextsize_f( int argc, char **argv) { size_t blocksize, sectsize; int c; recurse_all = recurse_dir = 0; init_cvtnum(&blocksize, §size); while ((c = getopt(argc, argv, "DR")) != EOF) { switch (c) { case 'D': recurse_all = 0; recurse_dir = 1; break; case 'R': recurse_all = 1; recurse_dir = 0; break; default: return command_usage(&cowextsize_cmd); } } if (optind < argc) { cowextsize = (long)cvtnum(blocksize, sectsize, argv[optind]); if (cowextsize < 0) { printf(_("non-numeric cowextsize argument -- %s\n"), argv[optind]); return 0; } } else { cowextsize = -1; } if (recurse_all || recurse_dir) nftw(file->name, (cowextsize >= 0) ? set_cowextsize_callback : get_cowextsize_callback, 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); else if (cowextsize >= 0) set_cowextsize(file->name, file->fd, cowextsize); else get_cowextsize(file->name, file->fd); return 0; } void cowextsize_init(void) { cowextsize_cmd.name = "cowextsize"; cowextsize_cmd.cfunc = cowextsize_f; cowextsize_cmd.args = _("[-D | -R] [cowextsize]"); cowextsize_cmd.argmin = 0; cowextsize_cmd.argmax = -1; cowextsize_cmd.flags = CMD_NOMAP_OK; cowextsize_cmd.oneline = _("get/set preferred CoW extent size (in bytes) for the open file"); cowextsize_cmd.help = cowextsize_help; add_command(&cowextsize_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/fadvise.c0000644000000000000000000000710713063067173014675 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t fadvise_cmd; static void fadvise_help(void) { printf(_( "\n" " advise the page cache about expected I/O patterns on the current file\n" "\n" " Modifies kernel page cache behaviour when operating on the current file.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_FADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_FADV_DONTNEED) [*]\n" " -n -- data will be accessed once (POSIX_FADV_NOREUSE) [*]\n" " -r -- expect random page references (POSIX_FADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_FADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_FADV_WILLNEED) [*]\n" " Notes: these interfaces are not supported in Linux kernels before 2.6.\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED and NOREUSE are equivalent, and force the maximum readahead.\n" "\n")); } static int fadvise_f( int argc, char **argv) { off64_t offset = 0, length = 0; int c, range = 0, advise = POSIX_FADV_NORMAL; while ((c = getopt(argc, argv, "dnrsw")) != EOF) { switch (c) { case 'd': /* Don't need these pages */ advise = POSIX_FADV_DONTNEED; range = 1; break; case 'n': /* Data will be accessed once */ advise = POSIX_FADV_NOREUSE; range = 1; break; case 'r': /* Expect random page references */ advise = POSIX_FADV_RANDOM; range = 0; break; case 's': /* Expect sequential page references */ advise = POSIX_FADV_SEQUENTIAL; range = 0; break; case 'w': /* Will need these pages */ advise = POSIX_FADV_WILLNEED; range = 1; break; default: return command_usage(&fadvise_cmd); } } if (range) { size_t blocksize, sectsize; if (optind != argc - 2) return command_usage(&fadvise_cmd); init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; length = cvtnum(blocksize, sectsize, argv[optind]); if (length < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } } else if (optind != argc) { return command_usage(&fadvise_cmd); } if (posix_fadvise(file->fd, offset, length, advise) < 0) { perror("fadvise"); return 0; } return 0; } void fadvise_init(void) { fadvise_cmd.name = "fadvise"; fadvise_cmd.cfunc = fadvise_f; fadvise_cmd.argmin = 0; fadvise_cmd.argmax = -1; fadvise_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fadvise_cmd.args = _("[-dnrsw] [off len]"); fadvise_cmd.oneline = _("advisory commands for sections of a file"); fadvise_cmd.help = fadvise_help; add_command(&fadvise_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/fiemap.c0000644000000000000000000002113313063067173014510 0ustar /* * Copyright (c) 2010 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "command.h" #include #include "init.h" #include "io.h" static cmdinfo_t fiemap_cmd; static void fiemap_help(void) { printf(_( "\n" " prints the block mapping for a file's data or attribute forks" "\n" " Example:\n" " 'fiemap -v' - tabular format verbose map\n" "\n" " fiemap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -v -- Verbose information\n" "\n")); } static int numlen( __u64 val, int base) { __u64 tmp; int len; for (len = 0, tmp = val; tmp > 0; tmp = tmp/base) len++; return (len == 0 ? 1 : len); } static void print_verbose( struct fiemap_extent *extent, int blocksize, int foff_w, int boff_w, int tot_w, int flg_w, int max_extents, int *cur_extent, __u64 *last_logical) { __u64 lstart; __u64 llast; __u64 len; __u64 block; char lbuf[48]; char bbuf[48]; char flgbuf[16]; llast = *last_logical / blocksize; lstart = extent->fe_logical / blocksize; len = extent->fe_length / blocksize; block = extent->fe_physical / blocksize; memset(lbuf, 0, sizeof(lbuf)); memset(bbuf, 0, sizeof(bbuf)); if (*cur_extent == 0) { printf("%4s: %-*s %-*s %*s %*s\n", _("EXT"), foff_w, _("FILE-OFFSET"), boff_w, _("BLOCK-RANGE"), tot_w, _("TOTAL"), flg_w, _("FLAGS")); } if (lstart != llast) { snprintf(lbuf, sizeof(lbuf), "[%llu..%llu]:", llast, lstart - 1ULL); printf("%4d: %-*s %-*s %*llu\n", *cur_extent, foff_w, lbuf, boff_w, _("hole"), tot_w, lstart - llast); (*cur_extent)++; memset(lbuf, 0, sizeof(lbuf)); } if ((*cur_extent + 1) == max_extents) return; snprintf(lbuf, sizeof(lbuf), "[%llu..%llu]:", lstart, lstart + len - 1ULL); snprintf(bbuf, sizeof(bbuf), "%llu..%llu", block, block + len - 1ULL); snprintf(flgbuf, sizeof(flgbuf), "0x%x", extent->fe_flags); printf("%4d: %-*s %-*s %*llu %*s\n", *cur_extent, foff_w, lbuf, boff_w, bbuf, tot_w, len, flg_w, flgbuf); (*cur_extent)++; *last_logical = extent->fe_logical + extent->fe_length; } static void print_plain( struct fiemap_extent *extent, int lflag, int blocksize, int max_extents, int *cur_extent, __u64 *last_logical) { __u64 lstart; __u64 llast; __u64 block; __u64 len; llast = *last_logical / blocksize; lstart = extent->fe_logical / blocksize; len = extent->fe_length / blocksize; block = extent->fe_physical / blocksize; if (lstart != llast) { printf("\t%d: [%llu..%llu]: hole", *cur_extent, llast, lstart - 1ULL); if (lflag) printf(_(" %llu blocks\n"), lstart - llast); else printf("\n"); (*cur_extent)++; } if ((*cur_extent + 1) == max_extents) return; printf("\t%d: [%llu..%llu]: %llu..%llu", *cur_extent, lstart, lstart + len - 1ULL, block, block + len - 1ULL); if (lflag) printf(_(" %llu blocks\n"), len); else printf("\n"); (*cur_extent)++; *last_logical = extent->fe_logical + extent->fe_length; } /* * Calculate the proper extent table format based on first * set of extents */ static void calc_print_format( struct fiemap *fiemap, __u64 blocksize, int *foff_w, int *boff_w, int *tot_w, int *flg_w) { int i; char lbuf[32]; char bbuf[32]; __u64 logical; __u64 block; __u64 len; struct fiemap_extent *extent; for (i = 0; i < fiemap->fm_mapped_extents; i++) { extent = &fiemap->fm_extents[i]; logical = extent->fe_logical / blocksize; len = extent->fe_length / blocksize; block = extent->fe_physical / blocksize; snprintf(lbuf, sizeof(lbuf), "[%llu..%llu]", logical, logical + len - 1); snprintf(bbuf, sizeof(bbuf), "%llu..%llu", block, block + len - 1); *foff_w = max(*foff_w, strlen(lbuf)); *boff_w = max(*boff_w, strlen(bbuf)); *tot_w = max(*tot_w, numlen(len, 10)); *flg_w = max(*flg_w, numlen(extent->fe_flags, 16)); if (extent->fe_flags & FIEMAP_EXTENT_LAST) break; } } int fiemap_f( int argc, char **argv) { struct fiemap *fiemap; int max_extents = 0; int num_extents = 32; int last = 0; int lflag = 0; int vflag = 0; int fiemap_flags = FIEMAP_FLAG_SYNC; int c; int i; int map_size; int ret; int cur_extent = 0; int foff_w = 16; /* 16 just for a good minimum range */ int boff_w = 16; int tot_w = 5; /* 5 since its just one number */ int flg_w = 5; __u64 blocksize = 512; __u64 last_logical = 0; struct stat st; while ((c = getopt(argc, argv, "aln:v")) != EOF) { switch (c) { case 'a': fiemap_flags |= FIEMAP_FLAG_XATTR; break; case 'l': lflag = 1; break; case 'n': max_extents = atoi(optarg); break; case 'v': vflag++; break; default: return command_usage(&fiemap_cmd); } } if (max_extents) num_extents = min(num_extents, max_extents); map_size = sizeof(struct fiemap) + (num_extents * sizeof(struct fiemap_extent)); fiemap = malloc(map_size); if (!fiemap) { fprintf(stderr, _("%s: malloc of %d bytes failed.\n"), progname, map_size); exitcode = 1; return 0; } printf("%s:\n", file->name); while (!last && ((cur_extent + 1) != max_extents)) { if (max_extents) num_extents = min(num_extents, max_extents - (cur_extent + 1)); memset(fiemap, 0, map_size); fiemap->fm_flags = fiemap_flags; fiemap->fm_start = last_logical; fiemap->fm_length = -1LL; fiemap->fm_extent_count = num_extents; ret = ioctl(file->fd, FS_IOC_FIEMAP, (unsigned long)fiemap); if (ret < 0) { fprintf(stderr, "%s: ioctl(FS_IOC_FIEMAP) [\"%s\"]: " "%s\n", progname, file->name, strerror(errno)); free(fiemap); exitcode = 1; return 0; } /* No more extents to map, exit */ if (!fiemap->fm_mapped_extents) break; for (i = 0; i < fiemap->fm_mapped_extents; i++) { struct fiemap_extent *extent; extent = &fiemap->fm_extents[i]; if (vflag) { if (cur_extent == 0) { calc_print_format(fiemap, blocksize, &foff_w, &boff_w, &tot_w, &flg_w); } print_verbose(extent, blocksize, foff_w, boff_w, tot_w, flg_w, max_extents, &cur_extent, &last_logical); } else print_plain(extent, lflag, blocksize, max_extents, &cur_extent, &last_logical); if (extent->fe_flags & FIEMAP_EXTENT_LAST) { last = 1; break; } if ((cur_extent + 1) == max_extents) break; } } if ((cur_extent + 1) == max_extents) goto out; memset(&st, 0, sizeof(st)); if (fstat(file->fd, &st)) { fprintf(stderr, "%s: fstat failed: %s\n", progname, strerror(errno)); free(fiemap); exitcode = 1; return 0; } if (cur_extent && last_logical < st.st_size) { char lbuf[32]; snprintf(lbuf, sizeof(lbuf), "[%llu..%llu]:", last_logical / blocksize, (st.st_size / blocksize) - 1); if (vflag) { printf("%4d: %-*s %-*s %*llu\n", cur_extent, foff_w, lbuf, boff_w, _("hole"), tot_w, (st.st_size - last_logical) / blocksize); } else { printf("\t%d: %s %s", cur_extent, lbuf, _("hole")); if (lflag) printf(_(" %llu blocks\n"), (st.st_size - last_logical) / blocksize); else printf("\n"); } } out: free(fiemap); return 0; } void fiemap_init(void) { fiemap_cmd.name = "fiemap"; fiemap_cmd.cfunc = fiemap_f; fiemap_cmd.argmin = 0; fiemap_cmd.argmax = -1; fiemap_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fiemap_cmd.args = _("[-alv] [-n nx]"); fiemap_cmd.oneline = _("print block mapping for a file"); fiemap_cmd.help = fiemap_help; add_command(&fiemap_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/file.c0000644000000000000000000000516013063067173014170 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include #include "init.h" #include "io.h" static cmdinfo_t file_cmd; static cmdinfo_t print_cmd; fileio_t *filetable; int filecount; fileio_t *file; static void print_fileio( fileio_t *file, int index, int braces) { printf(_("%c%03d%c %-14s (%s,%s,%s,%s%s%s%s%s)\n"), braces? '[' : ' ', index, braces? ']' : ' ', file->name, file->flags & IO_FOREIGN ? _("foreign") : _("xfs"), file->flags & IO_OSYNC ? _("sync") : _("non-sync"), file->flags & IO_DIRECT ? _("direct") : _("non-direct"), file->flags & IO_READONLY ? _("read-only") : _("read-write"), file->flags & IO_REALTIME ? _(",real-time") : "", file->flags & IO_APPEND ? _(",append-only") : "", file->flags & IO_NONBLOCK ? _(",non-block") : "", file->flags & IO_TMPFILE ? _(",tmpfile") : ""); } int filelist_f(void) { int i; for (i = 0; i < filecount; i++) print_fileio(&filetable[i], i, &filetable[i] == file); return 0; } static int print_f( int argc, char **argv) { filelist_f(); maplist_f(); return 0; } static int file_f( int argc, char **argv) { int i; if (argc <= 1) return filelist_f(); i = atoi(argv[1]); if (i < 0 || i >= filecount) { printf(_("value %d is out of range (0-%d)\n"), i, filecount-1); } else { file = &filetable[i]; filelist_f(); } return 0; } void file_init(void) { file_cmd.name = "file"; file_cmd.altname = "f"; file_cmd.args = _("[N]"); file_cmd.cfunc = file_f; file_cmd.argmin = 0; file_cmd.argmax = 1; file_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; file_cmd.oneline = _("set the current file"); print_cmd.name = "print"; print_cmd.altname = "p"; print_cmd.cfunc = print_f; print_cmd.argmin = 0; print_cmd.argmax = 0; print_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK | CMD_FLAG_GLOBAL; print_cmd.oneline = _("list current open files and memory mappings"); add_command(&file_cmd); add_command(&print_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/freeze.c0000644000000000000000000000364013063067173014532 0ustar /* * Copyright (c) 2001-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t freeze_cmd; static cmdinfo_t thaw_cmd; int freeze_f( int argc, char **argv) { int level = 1; if (xfsctl(file->name, file->fd, XFS_IOC_FREEZE, &level) < 0) { fprintf(stderr, _("%s: cannot freeze filesystem at %s: %s\n"), progname, file->name, strerror(errno)); exitcode = 1; return 0; } return 0; } int thaw_f( int argc, char **argv) { int level = 1; if (xfsctl(file->name, file->fd, XFS_IOC_THAW, &level) < 0) { fprintf(stderr, _("%s: cannot unfreeze filesystem mounted at %s: %s\n"), progname, file->name, strerror(errno)); exitcode = 1; return 0; } return 0; } void freeze_init(void) { freeze_cmd.name = "freeze"; freeze_cmd.cfunc = freeze_f; freeze_cmd.argmin = 0; freeze_cmd.argmax = 0; freeze_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; freeze_cmd.oneline = _("freeze filesystem of current file"); thaw_cmd.name = "thaw"; thaw_cmd.cfunc = thaw_f; thaw_cmd.argmin = 0; thaw_cmd.argmax = 0; thaw_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; thaw_cmd.oneline = _("unfreeze filesystem of current file"); if (expert) { add_command(&freeze_cmd); add_command(&thaw_cmd); } } xfsprogs-4.9.0+nmu1ubuntu2/io/fsync.c0000644000000000000000000000322013063067173014366 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "command.h" #include "init.h" #include "io.h" static cmdinfo_t fsync_cmd; static cmdinfo_t fdatasync_cmd; static int fsync_f( int argc, char **argv) { if (fsync(file->fd) < 0) { perror("fsync"); return 0; } return 0; } static int fdatasync_f( int argc, char **argv) { if (fdatasync(file->fd) < 0) { perror("fdatasync"); return 0; } return 0; } void fsync_init(void) { fsync_cmd.name = "fsync"; fsync_cmd.altname = "s"; fsync_cmd.cfunc = fsync_f; fsync_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fsync_cmd.oneline = _("calls fsync(2) to flush all in-core file state to disk"); fdatasync_cmd.name = "fdatasync"; fdatasync_cmd.altname = "ds"; fdatasync_cmd.cfunc = fdatasync_f; fdatasync_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fdatasync_cmd.oneline = _("calls fdatasync(2) to flush the files in-core data to disk"); add_command(&fsync_cmd); add_command(&fdatasync_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/getrusage.c0000644000000000000000000000675113063067173015246 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include #include #include "init.h" static cmdinfo_t getrusage_cmd; /* * Report process resource utilisation. Formatting options: * "Shell" format: 0.000u 0.000s 0:00.00 0.0% 0+0k 0+0io 0pf+0w * Verbose format: * 0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k * 0inputs+0outputs (0major+0minor)pagefaults 0swaps * Comma Separated Value format: 0.000,0.000,00:00:00.00,0.0,0,0,0,0,0,0 */ static int getrusage_f( int argc, char **argv) { struct timeval wallclk, timenow; struct rusage rusage; double usrtime, systime, elapsed, pct_cpu; char ts[64]; int Cflag, vflag; int c; Cflag = vflag = 0; while ((c = getopt(argc, argv, "Cv")) != EOF) { switch (c) { case 'C': Cflag = 1; break; case 'v': vflag = 1; break; default: return command_usage(&getrusage_cmd); } } if (optind != argc) return command_usage(&getrusage_cmd); if (getrusage(RUSAGE_SELF, &rusage) < 0) { perror("getrusage"); return 0; } gettimeofday(&timenow, NULL); wallclk = tsub(timenow, stopwatch); elapsed = (double)wallclk.tv_sec + ((double)wallclk.tv_usec / 1000000.0); usrtime = (double)rusage.ru_utime.tv_sec + ((double)rusage.ru_utime.tv_usec / 1000000.0); systime = (double)rusage.ru_stime.tv_sec + ((double)rusage.ru_stime.tv_usec / 1000000.0); if (elapsed < usrtime + systime) pct_cpu = 100.0; else pct_cpu = ((usrtime + systime) / elapsed) * 100; c = Cflag ? VERBOSE_FIXED_TIME : TERSE_FIXED_TIME; timestr(&wallclk, ts, sizeof(ts), c); if (Cflag) printf("%.3f,%.3f,%s,%.1f,%ld,%ld,%ld,%ld,%ld,%ld,%ld\n", usrtime, systime, ts, pct_cpu, rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap, rusage.ru_inblock, rusage.ru_oublock, rusage.ru_nvcsw, rusage.ru_nivcsw); else if (vflag) printf("%.2fuser %.2fsystem %selapsed %.0f%%CPU " "(%ldavgtext+%ldavgdata %ldmaxresident)k\n" "%ldinputs+%ldoutputs " "(%ldmajor+%ldminor)pagefaults %ldswaps\n", usrtime, systime, ts, pct_cpu, rusage.ru_ixrss, rusage.ru_idrss, rusage.ru_maxrss, rusage.ru_inblock, rusage.ru_oublock, rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap); else printf("%.3fu %.3fs %s %.1f%%\t" "%ld+%ldk %ld+%ldio %ldpf+%ldw\n", usrtime, systime, ts, pct_cpu, rusage.ru_maxrss, rusage.ru_ixrss, rusage.ru_inblock, rusage.ru_oublock, rusage.ru_majflt, rusage.ru_nswap); return 0; } void getrusage_init(void) { getrusage_cmd.name = "getrusage"; getrusage_cmd.altname = "g"; getrusage_cmd.argmin = 0; getrusage_cmd.argmax = -1; getrusage_cmd.cfunc = getrusage_f; getrusage_cmd.flags = CMD_NOFILE_OK | CMD_NOMAP_OK | CMD_FOREIGN_OK; getrusage_cmd.oneline = _("report process resource usage"); if (expert) add_command(&getrusage_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/imap.c0000644000000000000000000000353213063067173014200 0ustar /* * Copyright (c) 2001-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t imap_cmd; int imap_f(int argc, char **argv) { int count; int nent; int i; __u64 last = 0; xfs_inogrp_t *t; xfs_fsop_bulkreq_t bulkreq; if (argc != 2) nent = 1; else nent = atoi(argv[1]); t = malloc(nent * sizeof(*t)); if (!t) return 0; bulkreq.lastip = &last; bulkreq.icount = nent; bulkreq.ubuffer = (void *)t; bulkreq.ocount = &count; while (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS, &bulkreq) == 0) { if (count == 0) goto out_free; for (i = 0; i < count; i++) { printf(_("ino %10llu count %2d mask %016llx\n"), (unsigned long long)t[i].xi_startino, t[i].xi_alloccount, (unsigned long long)t[i].xi_allocmask); } } perror("xfsctl(XFS_IOC_FSINUMBERS)"); exitcode = 1; out_free: free(t); return 0; } void imap_init(void) { imap_cmd.name = "imap"; imap_cmd.cfunc = imap_f; imap_cmd.argmin = 0; imap_cmd.argmax = 1; imap_cmd.args = _("[nentries]"); imap_cmd.flags = CMD_NOMAP_OK; imap_cmd.oneline = _("inode map for filesystem of current file"); if (expert) add_command(&imap_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/init.c0000644000000000000000000001134613063067173014217 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "platform_defs.h" #include "command.h" #include "input.h" #include "init.h" #include "io.h" char *progname; int exitcode; int expert; int idlethread; size_t pagesize; struct timeval stopwatch; void usage(void) { fprintf(stderr, _("Usage: %s [-adfinrRstVx] [-m mode] [-p prog] [-c cmd]... file\n"), progname); exit(1); } void init_cvtnum( size_t *blocksize, size_t *sectsize) { if (!file || (file->flags & IO_FOREIGN)) { *blocksize = 4096; *sectsize = 512; } else { *blocksize = file->geom.blocksize; *sectsize = file->geom.sectsize; } } static void init_commands(void) { attr_init(); bmap_init(); copy_range_init(); fadvise_init(); file_init(); flink_init(); freeze_init(); fsync_init(); getrusage_init(); help_init(); imap_init(); inject_init(); seek_init(); madvise_init(); mincore_init(); mmap_init(); open_init(); parent_init(); pread_init(); prealloc_init(); fiemap_init(); pwrite_init(); quit_init(); readdir_init(); resblks_init(); sendfile_init(); shutdown_init(); sync_init(); sync_range_init(); truncate_init(); reflink_init(); cowextsize_init(); } static int init_args_command( int index) { if (index >= filecount) return 0; file = &filetable[index++]; return index; } static int init_check_command( const cmdinfo_t *ct) { if (ct->flags & CMD_FLAG_GLOBAL) return 1; if (!file && !(ct->flags & CMD_NOFILE_OK)) { fprintf(stderr, _("no files are open, try 'help open'\n")); return 0; } if (!mapping && !(ct->flags & CMD_NOMAP_OK)) { fprintf(stderr, _("no mapped regions, try 'help mmap'\n")); return 0; } if (file && !(ct->flags & CMD_FOREIGN_OK) && (file->flags & IO_FOREIGN)) { fprintf(stderr, _("foreign file active, %s command is for XFS filesystems only\n"), ct->name); return 0; } return 1; } void init( int argc, char **argv) { int c, flags = 0; char *sp; mode_t mode = 0600; xfs_fsop_geom_t geometry = { 0 }; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); pagesize = getpagesize(); gettimeofday(&stopwatch, NULL); while ((c = getopt(argc, argv, "ac:dFfim:p:nrRstTVx")) != EOF) { switch (c) { case 'a': flags |= IO_APPEND; break; case 'c': add_user_command(optarg); break; case 'd': flags |= IO_DIRECT; break; case 'F': /* Ignored / deprecated now, handled automatically */ break; case 'f': flags |= IO_CREAT; break; case 'i': idlethread = 1; break; case 'm': mode = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { fprintf(stderr, _("non-numeric mode -- %s\n"), optarg); exit(1); } break; case 'n': flags |= IO_NONBLOCK; break; case 'p': progname = optarg; break; case 'r': flags |= IO_READONLY; break; case 's': flags |= IO_OSYNC; break; case 't': flags |= IO_TRUNC; break; case 'R': flags |= IO_REALTIME; break; case 'T': flags |= IO_TMPFILE; break; case 'x': expert = 1; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); default: usage(); } } while (optind < argc) { if ((c = openfile(argv[optind], &geometry, flags, mode)) < 0) exit(1); if (!platform_test_xfs_fd(c)) flags |= IO_FOREIGN; if (addfile(argv[optind], c, &geometry, flags) < 0) exit(1); optind++; } init_commands(); add_args_command(init_args_command); add_check_command(init_check_command); } /* * The purpose of this idle thread is to test io from a multi threaded process. * With single threaded process, the file table is not shared and file structs * are not reference counted. Spawning an idle thread can help detecting file * struct reference leaks. */ void * idle_loop(void *arg) { for (;;) pause(); } void start_idle_thread() { pthread_t t; if (pthread_create(&t, NULL, idle_loop, NULL)) { fprintf(stderr, "Error creating idle thread\n"); exit(1); } } int main( int argc, char **argv) { init(argc, argv); if (idlethread) start_idle_thread(); command_loop(); return exitcode; } xfsprogs-4.9.0+nmu1ubuntu2/io/init.h0000644000000000000000000000210213063067173014212 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define CMD_NOFILE_OK (1<<0) /* command doesn't need an open file */ #define CMD_NOMAP_OK (1<<1) /* command doesn't need a mapped region */ #define CMD_FOREIGN_OK CMD_FLAG_FOREIGN_OK extern char *progname; extern int exitcode; extern int expert; extern size_t pagesize; extern struct timeval stopwatch; extern void init_cvtnum(size_t *blocksize, size_t *sectsize); xfsprogs-4.9.0+nmu1ubuntu2/io/inject.c0000644000000000000000000001277213063067173014534 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t inject_cmd; static int error_tag(char *name) { static struct { int tag; char *name; } *e, eflags[] = { #define XFS_ERRTAG_NOERROR 0 { XFS_ERRTAG_NOERROR, "noerror" }, #define XFS_ERRTAG_IFLUSH_1 1 { XFS_ERRTAG_IFLUSH_1, "iflush1" }, #define XFS_ERRTAG_IFLUSH_2 2 { XFS_ERRTAG_IFLUSH_2, "iflush2" }, #define XFS_ERRTAG_IFLUSH_3 3 { XFS_ERRTAG_IFLUSH_3, "iflush3" }, #define XFS_ERRTAG_IFLUSH_4 4 { XFS_ERRTAG_IFLUSH_4, "iflush4" }, #define XFS_ERRTAG_IFLUSH_5 5 { XFS_ERRTAG_IFLUSH_5, "iflush5" }, #define XFS_ERRTAG_IFLUSH_6 6 { XFS_ERRTAG_IFLUSH_6, "iflush6" }, #define XFS_ERRTAG_DA_READ_BUF 7 { XFS_ERRTAG_DA_READ_BUF, "dareadbuf" }, #define XFS_ERRTAG_BTREE_CHECK_LBLOCK 8 { XFS_ERRTAG_BTREE_CHECK_LBLOCK, "btree_chk_lblk" }, #define XFS_ERRTAG_BTREE_CHECK_SBLOCK 9 { XFS_ERRTAG_BTREE_CHECK_SBLOCK, "btree_chk_sblk" }, #define XFS_ERRTAG_ALLOC_READ_AGF 10 { XFS_ERRTAG_ALLOC_READ_AGF, "readagf" }, #define XFS_ERRTAG_IALLOC_READ_AGI 11 { XFS_ERRTAG_IALLOC_READ_AGI, "readagi" }, #define XFS_ERRTAG_ITOBP_INOTOBP 12 { XFS_ERRTAG_ITOBP_INOTOBP, "itobp" }, #define XFS_ERRTAG_IUNLINK 13 { XFS_ERRTAG_IUNLINK, "iunlink" }, #define XFS_ERRTAG_IUNLINK_REMOVE 14 { XFS_ERRTAG_IUNLINK_REMOVE, "iunlinkrm" }, #define XFS_ERRTAG_DIR_INO_VALIDATE 15 { XFS_ERRTAG_DIR_INO_VALIDATE, "dirinovalid" }, #define XFS_ERRTAG_BULKSTAT_READ_CHUNK 16 { XFS_ERRTAG_BULKSTAT_READ_CHUNK, "bulkstat" }, #define XFS_ERRTAG_IODONE_IOERR 17 { XFS_ERRTAG_IODONE_IOERR, "logiodone" }, #define XFS_ERRTAG_STRATREAD_IOERR 18 { XFS_ERRTAG_STRATREAD_IOERR, "stratread" }, #define XFS_ERRTAG_STRATCMPL_IOERR 19 { XFS_ERRTAG_STRATCMPL_IOERR, "stratcmpl" }, #define XFS_ERRTAG_DIOWRITE_IOERR 20 { XFS_ERRTAG_DIOWRITE_IOERR, "diowrite" }, #define XFS_ERRTAG_BMAPIFORMAT 21 { XFS_ERRTAG_BMAPIFORMAT, "bmapifmt" }, #define XFS_ERRTAG_FREE_EXTENT 22 { XFS_ERRTAG_FREE_EXTENT, "free_extent" }, #define XFS_ERRTAG_RMAP_FINISH_ONE 23 { XFS_ERRTAG_RMAP_FINISH_ONE, "rmap_finish_one" }, #define XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE 24 { XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE, "refcount_continue_update" }, #define XFS_ERRTAG_REFCOUNT_FINISH_ONE 25 { XFS_ERRTAG_REFCOUNT_FINISH_ONE, "refcount_finish_one" }, #define XFS_ERRTAG_BMAP_FINISH_ONE 26 { XFS_ERRTAG_BMAP_FINISH_ONE, "bmap_finish_one" }, #define XFS_ERRTAG_AG_RESV_CRITICAL 27 { XFS_ERRTAG_AG_RESV_CRITICAL, "ag_resv_critical" }, #define XFS_ERRTAG_MAX 28 { XFS_ERRTAG_MAX, NULL } }; int count; /* Search for a name */ if (name) { for (e = eflags; e->name; e++) if (strcmp(name, e->name) == 0) return e->tag; return -1; } /* Dump all the names */ fputs("tags: [ ", stdout); for (count = 0, e = eflags; e->name; e++, count++) { if (count) { fputs(", ", stdout); if (!(count % 5)) fputs("\n\t", stdout); } fputs(e->name, stdout); } fputs(" ]\n", stdout); return 0; } static void inject_help(void) { printf(_( "\n" " inject errors into the filesystem of the currently open file\n" "\n" " Example:\n" " 'inject readagf' - cause errors on allocation group freespace reads\n" "\n" " Causes the kernel to generate and react to errors within XFS, provided\n" " the XFS kernel code has been built with debugging features enabled.\n" " With no arguments, displays the list of error injection tags.\n" "\n")); } static int inject_f( int argc, char **argv) { xfs_error_injection_t error; int command = XFS_IOC_ERROR_INJECTION; if (argc == 1) return error_tag(NULL); while (--argc > 0) { error.fd = file->fd; if ((error.errtag = error_tag(argv[argc])) < 0) { fprintf(stderr, _("no such tag -- %s\n"), argv[1]); continue; } if (error.errtag == XFS_ERRTAG_NOERROR) command = XFS_IOC_ERROR_CLEARALL; if ((xfsctl(file->name, file->fd, command, &error)) < 0) { perror("XFS_IOC_ERROR_INJECTION"); continue; } } return 0; } void inject_init(void) { inject_cmd.name = "inject"; inject_cmd.cfunc = inject_f; inject_cmd.argmin = 0; inject_cmd.argmax = -1; inject_cmd.flags = CMD_NOMAP_OK; inject_cmd.args = _("[tag ...]"); inject_cmd.oneline = _("inject errors into a filesystem"); inject_cmd.help = inject_help; if (expert) add_command(&inject_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/io.h0000644000000000000000000001070113063067173013662 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" /* * Read/write patterns (default is always "forward") */ #define IO_RANDOM ( 0) #define IO_FORWARD ( 1) #define IO_BACKWARD (-1) /* * File descriptor options */ #define IO_READONLY (1<<0) #define IO_DIRECT (1<<1) #define IO_REALTIME (1<<2) #define IO_APPEND (1<<3) #define IO_OSYNC (1<<4) #define IO_CREAT (1<<5) #define IO_TRUNC (1<<6) #define IO_FOREIGN (1<<7) #define IO_NONBLOCK (1<<8) #define IO_TMPFILE (1<<9) /* * Regular file I/O control */ typedef struct fileio { int fd; /* open file descriptor */ int flags; /* flags describing file state */ char *name; /* file name at time of open */ xfs_fsop_geom_t geom; /* XFS filesystem geometry */ } fileio_t; extern fileio_t *filetable; /* open file table */ extern int filecount; /* number of open files */ extern fileio_t *file; /* active file in file table */ extern int filelist_f(void); /* * Memory mapped file regions */ typedef struct mmap_region { void *addr; /* address of start of mapping */ size_t length; /* length of mapping */ off64_t offset; /* start offset into backing file */ int prot; /* protection mode of the mapping */ char *name; /* name of backing file */ } mmap_region_t; extern mmap_region_t *maptable; /* mmap'd region array */ extern int mapcount; /* #entries in the mapping table */ extern mmap_region_t *mapping; /* active mapping table entry */ extern int maplist_f(void); extern void *check_mapping_range(mmap_region_t *, off64_t, size_t, int); /* * Various xfs_io helper routines/globals */ extern off64_t filesize(void); extern int openfile(char *, xfs_fsop_geom_t *, int, mode_t); extern int addfile(char *, int , xfs_fsop_geom_t *, int); extern void printxattr(uint, int, int, const char *, int, int); extern unsigned int recurse_all; extern unsigned int recurse_dir; extern void *buffer; extern size_t buffersize; extern int vectors; extern struct iovec *iov; extern int alloc_buffer(size_t, int, unsigned int); extern int read_buffer(int, off64_t, long long, long long *, int, int); extern void dump_buffer(off64_t, ssize_t); extern void attr_init(void); extern void bmap_init(void); extern void file_init(void); extern void flink_init(void); extern void freeze_init(void); extern void fsync_init(void); extern void getrusage_init(void); extern void help_init(void); extern void imap_init(void); extern void inject_init(void); extern void mmap_init(void); extern void open_init(void); extern void parent_init(void); extern void pread_init(void); extern void prealloc_init(void); extern void pwrite_init(void); extern void quit_init(void); extern void seek_init(void); extern void shutdown_init(void); extern void sync_init(void); extern void truncate_init(void); #ifdef HAVE_FADVISE extern void fadvise_init(void); #else #define fadvise_init() do { } while (0) #endif #ifdef HAVE_RESBLKS extern void resblks_init(void); #else #define resblks_init() do { } while (0) #endif #ifdef HAVE_SENDFILE extern void sendfile_init(void); #else #define sendfile_init() do { } while (0) #endif #ifdef HAVE_MADVISE extern void madvise_init(void); #else #define madvise_init() do { } while (0) #endif #ifdef HAVE_MINCORE extern void mincore_init(void); #else #define mincore_init() do { } while (0) #endif #ifdef HAVE_FIEMAP extern void fiemap_init(void); #else #define fiemap_init() do { } while (0) #endif #ifdef HAVE_COPY_FILE_RANGE extern void copy_range_init(void); #else #define copy_range_init() do { } while (0) #endif #ifdef HAVE_SYNC_FILE_RANGE extern void sync_range_init(void); #else #define sync_range_init() do { } while (0) #endif #ifdef HAVE_READDIR extern void readdir_init(void); #else #define readdir_init() do { } while (0) #endif extern void reflink_init(void); extern void cowextsize_init(void); xfsprogs-4.9.0+nmu1ubuntu2/io/link.c0000644000000000000000000000303713063067173014207 0ustar /* * Copyright (c) 2014 Christoph Hellwig. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" #ifndef AT_EMPTY_PATH #define AT_EMPTY_PATH 0x1000 #endif static cmdinfo_t flink_cmd; static void flink_help(void) { printf(_( "\n" "link the open file descriptor to the supplied filename\n" "\n" "\n")); } static int flink_f( int argc, char **argv) { if (argc != 2) return command_usage(&flink_cmd); if (linkat(file->fd, "", AT_FDCWD, argv[1], AT_EMPTY_PATH) < 0) { perror("flink"); return 0; } return 0; } void flink_init(void) { flink_cmd.name = "flink"; flink_cmd.cfunc = flink_f; flink_cmd.argmin = 1; flink_cmd.argmax = 1; flink_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; flink_cmd.args = _("filename"); flink_cmd.oneline = _("link the open file descriptor to the supplied filename"); flink_cmd.help = flink_help; add_command(&flink_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/madvise.c0000644000000000000000000000701713063067173014704 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include #include "init.h" #include "io.h" static cmdinfo_t madvise_cmd; static void madvise_help(void) { printf(_( "\n" " advise the page cache about access patterns expected for a mapping\n" "\n" " Modifies page cache behavior when operating on the current mapping.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_MADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_MADV_DONTNEED) [*]\n" " -r -- expect random page references (POSIX_MADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_MADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_MADV_WILLNEED) [*]\n" " Notes:\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED forces the maximum readahead.\n" "\n")); } int madvise_f( int argc, char **argv) { off64_t offset, llength; size_t length; void *start; int advise = MADV_NORMAL, c; size_t blocksize, sectsize; while ((c = getopt(argc, argv, "drsw")) != EOF) { switch (c) { case 'd': /* Don't need these pages */ advise = MADV_DONTNEED; break; case 'r': /* Expect random page references */ advise = MADV_RANDOM; break; case 's': /* Expect sequential page references */ advise = MADV_SEQUENTIAL; break; case 'w': /* Will need these pages */ advise = MADV_WILLNEED; break; default: return command_usage(&madvise_cmd); } } if (optind == argc) { offset = mapping->offset; length = mapping->length; } else if (optind == argc - 2) { init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; llength = cvtnum(blocksize, sectsize, argv[optind]); if (llength < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } else if (llength > (size_t)llength) { printf(_("length argument too large -- %lld\n"), (long long)llength); return 0; } else length = (size_t)llength; } else { return command_usage(&madvise_cmd); } start = check_mapping_range(mapping, offset, length, 1); if (!start) return 0; if (madvise(start, length, advise) < 0) { perror("madvise"); return 0; } return 0; } void madvise_init(void) { madvise_cmd.name = "madvise"; madvise_cmd.altname = "ma"; madvise_cmd.cfunc = madvise_f; madvise_cmd.argmin = 0; madvise_cmd.argmax = -1; madvise_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; madvise_cmd.args = _("[-drsw] [off len]"); madvise_cmd.oneline = _("give advice about use of memory"); madvise_cmd.help = madvise_help; add_command(&madvise_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/mincore.c0000644000000000000000000000621313063067173014705 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include #include "init.h" #include "io.h" static cmdinfo_t mincore_cmd; int mincore_f( int argc, char **argv) { off64_t offset, llength; size_t length; size_t blocksize, sectsize; void *start; void *current, *previous; unsigned char *vec; int i; if (argc == 1) { offset = mapping->offset; length = mapping->length; } else if (argc == 3) { init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[1]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[1]); return 0; } llength = cvtnum(blocksize, sectsize, argv[2]); if (llength < 0) { printf(_("non-numeric length argument -- %s\n"), argv[2]); return 0; } else if (llength > (size_t)llength) { printf(_("length argument too large -- %lld\n"), (long long)llength); return 0; } else length = (size_t)llength; } else { return command_usage(&mincore_cmd); } start = check_mapping_range(mapping, offset, length, 1); if (!start) return 0; vec = calloc(length/pagesize, sizeof(unsigned char)); if (!vec) { perror("calloc"); return 0; } if (mincore(start, length, vec) < 0) { perror("mincore"); free(vec); return 0; } previous = NULL; current = start; for (i = 0; i < length/pagesize; i++, current += pagesize) { if (vec[i]) { if (!previous) { /* print start address */ printf("0x%lx - ", (unsigned long)current); previous = start + (i * pagesize); } } else if (previous) { /* print end and page count */ printf(_("0x%lx %lu pages (%llu : %lu)\n"), (unsigned long)current, (unsigned long)(current - previous) / pagesize, (unsigned long long)offset + (unsigned long long)(previous - start), (unsigned long)(current - previous)); previous = NULL; } } if (previous) printf(_("0x%lx %lu pages (%llu : %lu)\n"), (unsigned long)current, (unsigned long)(current - previous) / pagesize, (unsigned long long)offset + (unsigned long long)(previous - start), (unsigned long)(current - previous)); free(vec); return 0; } void mincore_init(void) { mincore_cmd.name = "mincore"; mincore_cmd.altname = "mi"; mincore_cmd.cfunc = mincore_f; mincore_cmd.argmin = 0; mincore_cmd.argmax = 2; mincore_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; mincore_cmd.args = _("[off len]"); mincore_cmd.oneline = _("find mapping pages that are memory resident"); add_command(&mincore_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/mmap.c0000644000000000000000000004316613063067173014213 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include #include #include "init.h" #include "io.h" static cmdinfo_t mmap_cmd; static cmdinfo_t mread_cmd; static cmdinfo_t msync_cmd; static cmdinfo_t munmap_cmd; static cmdinfo_t mwrite_cmd; #ifdef HAVE_MREMAP static cmdinfo_t mremap_cmd; #endif /* HAVE_MREMAP */ mmap_region_t *maptable; int mapcount; mmap_region_t *mapping; static void print_mapping( mmap_region_t *map, int index, int braces) { unsigned char buffer[8] = { 0 }; int i; static struct { int prot; int mode; } *p, pflags[] = { { PROT_READ, 'r' }, { PROT_WRITE, 'w' }, { PROT_EXEC, 'x' }, { PROT_NONE, 0 } }; for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++) buffer[i] = (map->prot & p->prot) ? p->mode : '-'; printf("%c%03d%c 0x%lx - 0x%lx %s %14s (%lld : %ld)\n", braces? '[' : ' ', index, braces? ']' : ' ', (unsigned long)map->addr, (unsigned long)((char *)map->addr + map->length), buffer, map->name ? map->name : "???", (long long)map->offset, (long)map->length); } void * check_mapping_range( mmap_region_t *map, off64_t offset, size_t length, int pagealign) { off64_t relative; if (offset < mapping->offset) { printf(_("offset (%lld) is before start of mapping (%lld)\n"), (long long)offset, (long long)mapping->offset); return NULL; } relative = offset - mapping->offset; if (relative > mapping->length) { printf(_("offset (%lld) is beyond end of mapping (%lld)\n"), (long long)relative, (long long)mapping->offset); return NULL; } if ((relative + length) > (mapping->offset + mapping->length)) { printf(_("range (%lld:%lld) is beyond mapping (%lld:%ld)\n"), (long long)offset, (long long)relative, (long long)mapping->offset, (long)mapping->length); return NULL; } if (pagealign && (long)((char *)mapping->addr + relative) % pagesize) { printf(_("offset address (%p) is not page aligned\n"), (char *)mapping->addr + relative); return NULL; } return (char *)mapping->addr + relative; } int maplist_f(void) { int i; for (i = 0; i < mapcount; i++) print_mapping(&maptable[i], i, &maptable[i] == mapping); return 0; } static int mapset_f( int argc, char **argv) { int i; ASSERT(argc == 2); i = atoi(argv[1]); if (i < 0 || i >= mapcount) { printf("value %d is out of range (0-%d)\n", i, mapcount); } else { mapping = &maptable[i]; maplist_f(); } return 0; } static void mmap_help(void) { printf(_( "\n" " maps a range within the current file into memory\n" "\n" " Example:\n" " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" "\n" " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" " With no arguments, mmap shows the current mappings. The current mapping\n" " can be set by using the single argument form (mapping number or address).\n" " If two arguments are specified (a range), a new mapping is created and the\n" " following options are available:\n" " -r -- map with PROT_READ protection\n" " -w -- map with PROT_WRITE protection\n" " -x -- map with PROT_EXEC protection\n" " -s -- first do mmap(size)/munmap(size), try to reserve some free space\n" " If no protection mode is specified, all are used by default.\n" "\n")); } static int mmap_f( int argc, char **argv) { off64_t offset; ssize_t length = 0, length2 = 0; void *address = NULL; char *filename; size_t blocksize, sectsize; int c, prot = 0; if (argc == 1) { if (mapping) return maplist_f(); fprintf(stderr, file ? _("no mapped regions, try 'help mmap'\n") : _("no files are open, try 'help open'\n")); return 0; } else if (argc == 2) { if (mapping) return mapset_f(argc, argv); fprintf(stderr, file ? _("no mapped regions, try 'help mmap'\n") : _("no files are open, try 'help open'\n")); return 0; } else if (!file) { fprintf(stderr, _("no files are open, try 'help open'\n")); return 0; } init_cvtnum(&blocksize, §size); while ((c = getopt(argc, argv, "rwxs:")) != EOF) { switch (c) { case 'r': prot |= PROT_READ; break; case 'w': prot |= PROT_WRITE; break; case 'x': prot |= PROT_EXEC; break; case 's': length2 = cvtnum(blocksize, sectsize, optarg); break; default: return command_usage(&mmap_cmd); } } if (!prot) prot = PROT_READ | PROT_WRITE | PROT_EXEC; if (optind != argc - 2) return command_usage(&mmap_cmd); offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; length = cvtnum(blocksize, sectsize, argv[optind]); if (length < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } filename = strdup(file->name); if (!filename) { perror("strdup"); return 0; } /* * mmap and munmap memory area of length2 region is helpful to * make a region of extendible free memory. It's generally used * for later mremap operation(no MREMAP_MAYMOVE flag). But there * isn't guarantee that the memory after length (up to length2) * will stay free. */ if (length2 > length) { address = mmap(NULL, length2, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); munmap(address, length2); } address = mmap(address, length, prot, MAP_SHARED, file->fd, offset); if (address == MAP_FAILED) { perror("mmap"); free(filename); return 0; } /* Extend the control array of mmap'd regions */ maptable = (mmap_region_t *)realloc(maptable, /* growing */ ++mapcount * sizeof(mmap_region_t)); if (!maptable) { perror("realloc"); mapcount = 0; munmap(address, length); free(filename); return 0; } /* Finally, make this the new active mapping */ mapping = &maptable[mapcount - 1]; mapping->addr = address; mapping->length = length; mapping->offset = offset; mapping->name = filename; mapping->prot = prot; return 0; } static void msync_help(void) { printf(_( "\n" " flushes a range of bytes in the current memory mapping\n" "\n" " Writes all modified copies of pages over the specified range (or entire\n" " mapping if no range specified) to their backing storage locations. Also,\n" " optionally invalidates so that subsequent references to the pages will be\n" " obtained from their backing storage locations (instead of cached copies).\n" " -a -- perform asynchronous writes (MS_ASYNC)\n" " -i -- invalidate mapped pages (MS_INVALIDATE)\n" " -s -- perform synchronous writes (MS_SYNC)\n" "\n")); } int msync_f( int argc, char **argv) { off64_t offset; ssize_t length; void *start; int c, flags = 0; size_t blocksize, sectsize; while ((c = getopt(argc, argv, "ais")) != EOF) { switch (c) { case 'a': flags |= MS_ASYNC; break; case 'i': flags |= MS_INVALIDATE; break; case 's': flags |= MS_SYNC; break; default: return command_usage(&msync_cmd); } } if (optind == argc) { offset = mapping->offset; length = mapping->length; } else if (optind == argc - 2) { init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; length = cvtnum(blocksize, sectsize, argv[optind]); if (length < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } } else { return command_usage(&msync_cmd); } start = check_mapping_range(mapping, offset, length, 1); if (!start) return 0; if (msync(start, length, flags) < 0) perror("msync"); return 0; } static void mread_help(void) { printf(_( "\n" " reads a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n" "\n" " Accesses a range of the current memory mapping, optionally dumping it to\n" " the standard output stream (with -v option) for subsequent inspection.\n" " -f -- verbose mode, dump bytes with offsets relative to start of file.\n" " -r -- reverse order; start accessing from the end of range, moving backward\n" " -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n" " The accesses are performed sequentially from the start offset by default.\n" " Notes:\n" " References to whole pages following the end of the backing file results\n" " in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n" " on various filesystem conditions, including quota exceeded errors, and\n" " for physical device errors (such as unreadable disk blocks). No attempt\n" " has been made to catch signals at this stage...\n" "\n")); } int mread_f( int argc, char **argv) { off64_t offset, tmp, dumpoffset, printoffset; ssize_t length; size_t dumplen, cnt = 0; char *bp; void *start; int dump = 0, rflag = 0, c; size_t blocksize, sectsize; while ((c = getopt(argc, argv, "frv")) != EOF) { switch (c) { case 'f': dump = 2; /* file offset dump */ break; case 'r': rflag = 1; /* read in reverse */ break; case 'v': dump = 1; /* mapping offset dump */ break; default: return command_usage(&mread_cmd); } } if (optind == argc) { offset = mapping->offset; length = mapping->length; } else if (optind == argc - 2) { init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; length = cvtnum(blocksize, sectsize, argv[optind]); if (length < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } } else { return command_usage(&mread_cmd); } start = check_mapping_range(mapping, offset, length, 0); if (!start) return 0; dumpoffset = offset - mapping->offset; if (dump == 2) printoffset = offset; else printoffset = dumpoffset; if (alloc_buffer(pagesize, 0, 0) < 0) return 0; bp = (char *)buffer; dumplen = length % pagesize; if (!dumplen) dumplen = pagesize; if (rflag) { for (tmp = length - 1, c = 0; tmp >= 0; tmp--, c = 1) { *bp = *(((char *)mapping->addr) + dumpoffset + tmp); cnt++; if (c && cnt == dumplen) { if (dump) { dump_buffer(printoffset, dumplen); printoffset += dumplen; } bp = (char *)buffer; dumplen = pagesize; cnt = 0; } else { bp++; } } } else { for (tmp = 0, c = 0; tmp < length; tmp++, c = 1) { *bp = *(((char *)mapping->addr) + dumpoffset + tmp); cnt++; if (c && cnt == dumplen) { if (dump) dump_buffer(printoffset + tmp - (dumplen - 1), dumplen); bp = (char *)buffer; dumplen = pagesize; cnt = 0; } else { bp++; } } } return 0; } int munmap_f( int argc, char **argv) { ssize_t length; unsigned int offset; if (munmap(mapping->addr, mapping->length) < 0) { perror("munmap"); return 0; } free(mapping->name); /* Shuffle the mapping table entries down over the removed entry */ offset = mapping - &maptable[0]; length = mapcount * sizeof(mmap_region_t); length -= (offset + 1) * sizeof(mmap_region_t); if (length) memmove(mapping, mapping + 1, length); /* Resize the memory allocated for the table, possibly freeing */ if (--mapcount) { maptable = (mmap_region_t *)realloc(maptable, /* shrinking */ mapcount * sizeof(mmap_region_t)); if (offset == mapcount) offset--; mapping = maptable + offset; } else { free(maptable); mapping = maptable = NULL; } maplist_f(); return 0; } static void mwrite_help(void) { printf(_( "\n" " dirties a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n" "\n" " Stores a byte into memory for a range within a mapping.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -S -- use an alternate seed character\n" " -r -- reverse order; start storing from the end of range, moving backward\n" " The stores are performed sequentially from the start offset by default.\n" "\n")); } int mwrite_f( int argc, char **argv) { off64_t offset, tmp; ssize_t length; void *start; char *sp; int seed = 'X'; int rflag = 0; int c; size_t blocksize, sectsize; while ((c = getopt(argc, argv, "rS:")) != EOF) { switch (c) { case 'r': rflag = 1; break; case 'S': seed = (int)strtol(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric seed -- %s\n"), optarg); return 0; } break; default: return command_usage(&mwrite_cmd); } } if (optind == argc) { offset = mapping->offset; length = mapping->length; } else if (optind == argc - 2) { init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; length = cvtnum(blocksize, sectsize, argv[optind]); if (length < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } } else { return command_usage(&mwrite_cmd); } start = check_mapping_range(mapping, offset, length, 0); if (!start) return 0; offset -= mapping->offset; if (rflag) { for (tmp = offset + length -1; tmp >= offset; tmp--) ((char *)mapping->addr)[tmp] = seed; } else { for (tmp = offset; tmp < offset + length; tmp++) ((char *)mapping->addr)[tmp] = seed; } return 0; } #ifdef HAVE_MREMAP static void mremap_help(void) { printf(_( "\n" " resizes the current memory mapping\n" "\n" " Examples:\n" " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" "\n" " Resizes the mappping, growing or shrinking from the current size.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -f -- use MREMAP_FIXED flag to mremap on new_address\n" " -m -- use the MREMAP_MAYMOVE flag\n" "\n")); } int mremap_f( int argc, char **argv) { ssize_t new_length; void *new_addr = NULL; int flags = 0; int c; size_t blocksize, sectsize; init_cvtnum(&blocksize, §size); while ((c = getopt(argc, argv, "f:m")) != EOF) { switch (c) { case 'f': flags = MREMAP_FIXED|MREMAP_MAYMOVE; new_addr = (void *)cvtnum(blocksize, sectsize, optarg); break; case 'm': flags = MREMAP_MAYMOVE; break; default: return command_usage(&mremap_cmd); } } if (optind != argc - 1) return command_usage(&mremap_cmd); new_length = cvtnum(blocksize, sectsize, argv[optind]); if (new_length < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } if (!new_addr) new_addr = mremap(mapping->addr, mapping->length, new_length, flags); else new_addr = mremap(mapping->addr, mapping->length, new_length, flags, new_addr); if (new_addr == MAP_FAILED) perror("mremap"); else { mapping->addr = new_addr; mapping->length = new_length; } return 0; } #endif /* HAVE_MREMAP */ void mmap_init(void) { mmap_cmd.name = "mmap"; mmap_cmd.altname = "mm"; mmap_cmd.cfunc = mmap_f; mmap_cmd.argmin = 0; mmap_cmd.argmax = -1; mmap_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK; mmap_cmd.args = _("[N] | [-rwx] [-s size] [off len]"); mmap_cmd.oneline = _("mmap a range in the current file, show mappings"); mmap_cmd.help = mmap_help; mread_cmd.name = "mread"; mread_cmd.altname = "mr"; mread_cmd.cfunc = mread_f; mread_cmd.argmin = 0; mread_cmd.argmax = -1; mread_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; mread_cmd.args = _("[-r] [off len]"); mread_cmd.oneline = _("reads data from a region in the current memory mapping"); mread_cmd.help = mread_help; msync_cmd.name = "msync"; msync_cmd.altname = "ms"; msync_cmd.cfunc = msync_f; msync_cmd.argmin = 0; msync_cmd.argmax = -1; msync_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; msync_cmd.args = _("[-ais] [off len]"); msync_cmd.oneline = _("flush a region in the current memory mapping"); msync_cmd.help = msync_help; munmap_cmd.name = "munmap"; munmap_cmd.altname = "mu"; munmap_cmd.cfunc = munmap_f; munmap_cmd.argmin = 0; munmap_cmd.argmax = 0; munmap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; munmap_cmd.oneline = _("unmaps the current memory mapping"); mwrite_cmd.name = "mwrite"; mwrite_cmd.altname = "mw"; mwrite_cmd.cfunc = mwrite_f; mwrite_cmd.argmin = 0; mwrite_cmd.argmax = -1; mwrite_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; mwrite_cmd.args = _("[-r] [-S seed] [off len]"); mwrite_cmd.oneline = _("writes data into a region in the current memory mapping"); mwrite_cmd.help = mwrite_help; #ifdef HAVE_MREMAP mremap_cmd.name = "mremap"; mremap_cmd.altname = "mrm"; mremap_cmd.cfunc = mremap_f; mremap_cmd.argmin = 1; mremap_cmd.argmax = 3; mremap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; mremap_cmd.args = _("[-m|-f ] newsize"); mremap_cmd.oneline = _("alters the size of the current memory mapping"); mremap_cmd.help = mremap_help; #endif /* HAVE_MREMAP */ add_command(&mmap_cmd); add_command(&mread_cmd); add_command(&msync_cmd); add_command(&munmap_cmd); add_command(&mwrite_cmd); #ifdef HAVE_MREMAP add_command(&mremap_cmd); #endif /* HAVE_MREMAP */ } xfsprogs-4.9.0+nmu1ubuntu2/io/open.c0000644000000000000000000005506713063067173014225 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" #include "libxfs.h" #ifndef __O_TMPFILE #if defined __alpha__ #define __O_TMPFILE 0100000000 #elif defined(__hppa__) #define __O_TMPFILE 040000000 #elif defined(__sparc__) #define __O_TMPFILE 0x2000000 #else #define __O_TMPFILE 020000000 #endif #endif /* __O_TMPFILE */ #ifndef O_TMPFILE #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) #endif static cmdinfo_t open_cmd; static cmdinfo_t stat_cmd; static cmdinfo_t close_cmd; static cmdinfo_t statfs_cmd; static cmdinfo_t chproj_cmd; static cmdinfo_t lsproj_cmd; static cmdinfo_t extsize_cmd; static cmdinfo_t inode_cmd; static prid_t prid; static long extsize; off64_t filesize(void) { struct stat st; if (fstat(file->fd, &st) < 0) { perror("fstat"); return -1; } return st.st_size; } static char * filetype(mode_t mode) { switch (mode & S_IFMT) { case S_IFSOCK: return _("socket"); case S_IFDIR: return _("directory"); case S_IFCHR: return _("char device"); case S_IFBLK: return _("block device"); case S_IFREG: return _("regular file"); case S_IFLNK: return _("symbolic link"); case S_IFIFO: return _("fifo"); } return NULL; } static int stat_f( int argc, char **argv) { struct dioattr dio; struct fsxattr fsx, fsxa; struct stat st; int verbose = (argc == 2 && !strcmp(argv[1], "-v")); printf(_("fd.path = \"%s\"\n"), file->name); printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"), file->flags & IO_OSYNC ? _("sync") : _("non-sync"), file->flags & IO_DIRECT ? _("direct") : _("non-direct"), file->flags & IO_READONLY ? _("read-only") : _("read-write"), file->flags & IO_REALTIME ? _(",real-time") : "", file->flags & IO_APPEND ? _(",append-only") : "", file->flags & IO_NONBLOCK ? _(",non-block") : "", file->flags & IO_TMPFILE ? _(",tmpfile") : ""); if (fstat(file->fd, &st) < 0) { perror("fstat"); } else { printf(_("stat.ino = %lld\n"), (long long)st.st_ino); printf(_("stat.type = %s\n"), filetype(st.st_mode)); printf(_("stat.size = %lld\n"), (long long)st.st_size); printf(_("stat.blocks = %lld\n"), (long long)st.st_blocks); if (verbose) { printf(_("stat.atime = %s"), ctime(&st.st_atime)); printf(_("stat.mtime = %s"), ctime(&st.st_mtime)); printf(_("stat.ctime = %s"), ctime(&st.st_ctime)); } } if (file->flags & IO_FOREIGN) return 0; if ((xfsctl(file->name, file->fd, FS_IOC_FSGETXATTR, &fsx)) < 0 || (xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTRA, &fsxa)) < 0) { perror("FS_IOC_FSGETXATTR"); } else { printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags); printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1); printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid); printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize); printf(_("fsxattr.cowextsize = %u\n"), fsx.fsx_cowextsize); printf(_("fsxattr.nextents = %u\n"), fsx.fsx_nextents); printf(_("fsxattr.naextents = %u\n"), fsxa.fsx_nextents); } if ((xfsctl(file->name, file->fd, XFS_IOC_DIOINFO, &dio)) < 0) { perror("XFS_IOC_DIOINFO"); } else { printf(_("dioattr.mem = 0x%x\n"), dio.d_mem); printf(_("dioattr.miniosz = %u\n"), dio.d_miniosz); printf(_("dioattr.maxiosz = %u\n"), dio.d_maxiosz); } return 0; } int openfile( char *path, xfs_fsop_geom_t *geom, int flags, mode_t mode) { int fd; int oflags; oflags = flags & IO_READONLY ? O_RDONLY : O_RDWR; if (flags & IO_APPEND) oflags |= O_APPEND; if (flags & IO_CREAT) oflags |= O_CREAT; if (flags & IO_DIRECT) oflags |= O_DIRECT; if (flags & IO_OSYNC) oflags |= O_SYNC; if (flags & IO_TRUNC) oflags |= O_TRUNC; if (flags & IO_NONBLOCK) oflags |= O_NONBLOCK; if (flags & IO_TMPFILE) oflags |= O_TMPFILE; fd = open(path, oflags, mode); if (fd < 0) { if (errno == EISDIR && ((oflags & (O_RDWR|O_TMPFILE)) == O_RDWR)) { /* make it as if we asked for O_RDONLY & try again */ oflags &= ~O_RDWR; oflags |= O_RDONLY; flags |= IO_READONLY; fd = open(path, oflags, mode); if (fd < 0) { perror(path); return -1; } } else { perror(path); return -1; } } if (!geom || !platform_test_xfs_fd(fd)) return fd; if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) { perror("XFS_IOC_FSGEOMETRY"); close(fd); return -1; } if (!(flags & IO_READONLY) && (flags & IO_REALTIME)) { struct fsxattr attr; if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &attr) < 0) { perror("FS_IOC_FSGETXATTR"); close(fd); return -1; } if (!(attr.fsx_xflags & FS_XFLAG_REALTIME)) { attr.fsx_xflags |= FS_XFLAG_REALTIME; if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &attr) < 0) { perror("FS_IOC_FSSETXATTR"); close(fd); return -1; } } } return fd; } int addfile( char *name, int fd, xfs_fsop_geom_t *geometry, int flags) { char *filename; filename = strdup(name); if (!filename) { perror("strdup"); close(fd); return -1; } /* Extend the table of currently open files */ filetable = (fileio_t *)realloc(filetable, /* growing */ ++filecount * sizeof(fileio_t)); if (!filetable) { perror("realloc"); filecount = 0; free(filename); close(fd); return -1; } /* Finally, make this the new active open file */ file = &filetable[filecount - 1]; file->fd = fd; file->flags = flags; file->name = filename; file->geom = *geometry; return 0; } static void open_help(void) { printf(_( "\n" " opens a new file in the requested mode\n" "\n" " Example:\n" " 'open -cd /tmp/data' - creates/opens data file read-write for direct IO\n" "\n" " Opens a file for subsequent use by all of the other xfs_io commands.\n" " With no arguments, open uses the stat command to show the current file.\n" " -a -- open with the O_APPEND flag (append-only mode)\n" " -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n" " -f -- open with O_CREAT (create the file if it doesn't exist)\n" " -m -- permissions to use in case a new file is created (default 0600)\n" " -n -- open with O_NONBLOCK\n" " -r -- open with O_RDONLY, the default is O_RDWR\n" " -s -- open with O_SYNC\n" " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n" " -R -- mark the file as a realtime XFS file immediately after opening it\n" " -T -- open with O_TMPFILE (create a file not visible in the namespace)\n" " Note1: usually read/write direct IO requests must be blocksize aligned;\n" " some kernels, however, allow sectorsize alignment for direct IO.\n" " Note2: the bmap for non-regular files can be obtained provided the file\n" " was opened correctly (in particular, must be opened read-only).\n" "\n")); } static int open_f( int argc, char **argv) { int c, fd, flags = 0; char *sp; mode_t mode = 0600; xfs_fsop_geom_t geometry = { 0 }; if (argc == 1) { if (file) return stat_f(argc, argv); fprintf(stderr, _("no files are open, try 'help open'\n")); return 0; } while ((c = getopt(argc, argv, "FRTacdfm:nrstx")) != EOF) { switch (c) { case 'F': /* Ignored / deprecated now, handled automatically */ break; case 'a': flags |= IO_APPEND; break; case 'c': case 'f': flags |= IO_CREAT; break; case 'd': flags |= IO_DIRECT; break; case 'm': mode = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric mode -- %s\n"), optarg); return 0; } break; case 'n': flags |= IO_NONBLOCK; break; case 'r': flags |= IO_READONLY; break; case 's': flags |= IO_OSYNC; break; case 't': flags |= IO_TRUNC; break; case 'R': case 'x': /* backwards compatibility */ flags |= IO_REALTIME; break; case 'T': flags |= IO_TMPFILE; break; default: return command_usage(&open_cmd); } } if (optind != argc - 1) return command_usage(&open_cmd); if ((flags & (IO_READONLY|IO_TMPFILE)) == (IO_READONLY|IO_TMPFILE)) { fprintf(stderr, _("-T and -r options are incompatible\n")); return -1; } fd = openfile(argv[optind], &geometry, flags, mode); if (fd < 0) return 0; if (!platform_test_xfs_fd(fd)) flags |= IO_FOREIGN; addfile(argv[optind], fd, &geometry, flags); return 0; } static int close_f( int argc, char **argv) { size_t length; unsigned int offset; if (close(file->fd) < 0) { perror("close"); return 0; } free(file->name); /* Shuffle the file table entries down over the removed entry */ offset = file - &filetable[0]; length = filecount * sizeof(fileio_t); length -= (offset + 1) * sizeof(fileio_t); if (length) memmove(file, file + 1, length); /* Resize the memory allocated for the table, possibly freeing */ if (--filecount) { filetable = (fileio_t *)realloc(filetable, /* shrinking */ filecount * sizeof(fileio_t)); if (offset == filecount) offset--; file = filetable + offset; } else { free(filetable); file = filetable = NULL; } filelist_f(); return 0; } static void lsproj_help(void) { printf(_( "\n" " displays the project identifier associated with the current path\n" "\n" " Options:\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, but only list projects on directories\n" "\n")); } static int lsproj_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { prid_t projid; int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; if ((fd = open(path, O_RDONLY)) == -1) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else { if (getprojid(path, fd, &projid) == 0) printf("[%u] %s\n", (unsigned int)projid, path); close(fd); } return 0; } static int lsproj_f( int argc, char **argv) { prid_t projid; int c; recurse_all = recurse_dir = 0; while ((c = getopt(argc, argv, "DR")) != EOF) { switch (c) { case 'D': recurse_all = 0; recurse_dir = 1; break; case 'R': recurse_all = 1; recurse_dir = 0; break; default: return command_usage(&lsproj_cmd); } } if (argc != optind) return command_usage(&lsproj_cmd); if (recurse_all || recurse_dir) nftw(file->name, lsproj_callback, 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); else if (getprojid(file->name, file->fd, &projid) < 0) perror("getprojid"); else printf(_("projid = %u\n"), (unsigned int)projid); return 0; } static void chproj_help(void) { printf(_( "\n" " modifies the project identifier associated with the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying projects on directories\n" "\n")); } static int chproj_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; if ((fd = open(path, O_RDONLY)) == -1) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else { if (setprojid(path, fd, prid) < 0) perror("setprojid"); close(fd); } return 0; } static int chproj_f( int argc, char **argv) { int c; recurse_all = recurse_dir = 0; while ((c = getopt(argc, argv, "DR")) != EOF) { switch (c) { case 'D': recurse_all = 0; recurse_dir = 1; break; case 'R': recurse_all = 1; recurse_dir = 0; break; default: return command_usage(&chproj_cmd); } } if (argc != optind + 1) return command_usage(&chproj_cmd); prid = prid_from_string(argv[optind]); if (prid == -1) { printf(_("invalid project ID -- %s\n"), argv[optind]); return 0; } if (recurse_all || recurse_dir) nftw(file->name, chproj_callback, 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); else if (setprojid(file->name, file->fd, prid) < 0) perror("setprojid"); return 0; } static void extsize_help(void) { printf(_( "\n" " report or modify preferred extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying extsize on directories\n" "\n")); } static int get_extsize(const char *path, int fd) { struct fsxattr fsx; if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { printf("%s: FS_IOC_FSGETXATTR %s: %s\n", progname, path, strerror(errno)); return 0; } printf("[%u] %s\n", fsx.fsx_extsize, path); return 0; } static int set_extsize(const char *path, int fd, long extsz) { struct fsxattr fsx; struct stat stat; if (fstat(fd, &stat) < 0) { perror("fstat"); return 0; } if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { printf("%s: FS_IOC_FSGETXATTR %s: %s\n", progname, path, strerror(errno)); return 0; } if (S_ISREG(stat.st_mode)) { fsx.fsx_xflags |= FS_XFLAG_EXTSIZE; } else if (S_ISDIR(stat.st_mode)) { fsx.fsx_xflags |= FS_XFLAG_EXTSZINHERIT; } else { printf(_("invalid target file type - file %s\n"), path); return 0; } fsx.fsx_extsize = extsz; if ((xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx)) < 0) { printf("%s: FS_IOC_FSSETXATTR %s: %s\n", progname, path, strerror(errno)); return 0; } return 0; } static int get_extsize_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; if ((fd = open(path, O_RDONLY)) == -1) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else { get_extsize(path, fd); close(fd); } return 0; } static int set_extsize_callback( const char *path, const struct stat *stat, int status, struct FTW *data) { int fd; if (recurse_dir && !S_ISDIR(stat->st_mode)) return 0; if ((fd = open(path, O_RDONLY)) == -1) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else { set_extsize(path, fd, extsize); close(fd); } return 0; } static int extsize_f( int argc, char **argv) { size_t blocksize, sectsize; int c; recurse_all = recurse_dir = 0; init_cvtnum(&blocksize, §size); while ((c = getopt(argc, argv, "DR")) != EOF) { switch (c) { case 'D': recurse_all = 0; recurse_dir = 1; break; case 'R': recurse_all = 1; recurse_dir = 0; break; default: return command_usage(&extsize_cmd); } } if (optind < argc) { extsize = (long)cvtnum(blocksize, sectsize, argv[optind]); if (extsize < 0) { printf(_("non-numeric extsize argument -- %s\n"), argv[optind]); return 0; } } else { extsize = -1; } if (recurse_all || recurse_dir) nftw(file->name, (extsize >= 0) ? set_extsize_callback : get_extsize_callback, 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); else if (extsize >= 0) set_extsize(file->name, file->fd, extsize); else get_extsize(file->name, file->fd); return 0; } static int statfs_f( int argc, char **argv) { struct xfs_fsop_counts fscounts; struct xfs_fsop_geom fsgeo; struct statfs st; printf(_("fd.path = \"%s\"\n"), file->name); if (platform_fstatfs(file->fd, &st) < 0) { perror("fstatfs"); } else { printf(_("statfs.f_bsize = %lld\n"), (long long) st.f_bsize); printf(_("statfs.f_blocks = %lld\n"), (long long) st.f_blocks); #if defined(__sgi__) printf(_("statfs.f_frsize = %lld\n"), (long long) st.f_frsize); #else printf(_("statfs.f_bavail = %lld\n"), (long long) st.f_bavail); #endif printf(_("statfs.f_files = %lld\n"), (long long) st.f_files); printf(_("statfs.f_ffree = %lld\n"), (long long) st.f_ffree); } if (file->flags & IO_FOREIGN) return 0; if ((xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) { perror("XFS_IOC_FSGEOMETRY_V1"); } else { printf(_("geom.bsize = %u\n"), fsgeo.blocksize); printf(_("geom.agcount = %u\n"), fsgeo.agcount); printf(_("geom.agblocks = %u\n"), fsgeo.agblocks); printf(_("geom.datablocks = %llu\n"), (unsigned long long) fsgeo.datablocks); printf(_("geom.rtblocks = %llu\n"), (unsigned long long) fsgeo.rtblocks); printf(_("geom.rtextents = %llu\n"), (unsigned long long) fsgeo.rtextents); printf(_("geom.rtextsize = %u\n"), fsgeo.rtextsize); printf(_("geom.sunit = %u\n"), fsgeo.sunit); printf(_("geom.swidth = %u\n"), fsgeo.swidth); } if ((xfsctl(file->name, file->fd, XFS_IOC_FSCOUNTS, &fscounts)) < 0) { perror("XFS_IOC_FSCOUNTS"); } else { printf(_("counts.freedata = %llu\n"), (unsigned long long) fscounts.freedata); printf(_("counts.freertx = %llu\n"), (unsigned long long) fscounts.freertx); printf(_("counts.freeino = %llu\n"), (unsigned long long) fscounts.freeino); printf(_("counts.allocino = %llu\n"), (unsigned long long) fscounts.allocino); } return 0; } static void inode_help(void) { printf(_( "\n" "Query physical information about an inode" "\n" " Default: -- Return 1 if any inode number greater than 32 bits exists in\n" " the filesystem, or 0 if none exist\n" " num -- Return inode number [num] if in use, or 0 if not in use\n" " -n num -- Return the next used inode after [num]\n" " -v -- Verbose mode - display returned inode number's size in bits\n" "\n")); } static __u64 get_last_inode(void) { __u64 lastip = 0; __u64 lastgrp = 0; __s32 ocount = 0; __u64 last_ino; struct xfs_inogrp igroup[1024]; struct xfs_fsop_bulkreq bulkreq; bulkreq.lastip = &lastip; bulkreq.ubuffer = &igroup; bulkreq.icount = sizeof(igroup) / sizeof(struct xfs_inogrp); bulkreq.ocount = &ocount; for (;;) { if (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS, &bulkreq)) { perror("XFS_IOC_FSINUMBERS"); return 0; } /* Did we reach the last inode? */ if (ocount == 0) break; /* last inode in igroup table */ lastgrp = ocount; } lastgrp--; /* The last inode number in use */ last_ino = igroup[lastgrp].xi_startino + libxfs_highbit64(igroup[lastgrp].xi_allocmask); return last_ino; } static int inode_f( int argc, char **argv) { __s32 count = 0; __u64 result_ino = 0; __u64 userino = NULLFSINO; char *p; int c; int verbose = 0; int ret_next = 0; int cmd = 0; struct xfs_fsop_bulkreq bulkreq; struct xfs_bstat bstat; while ((c = getopt(argc, argv, "nv")) != EOF) { switch (c) { case 'v': verbose = 1; break; case 'n': ret_next = 1; break; default: return command_usage(&inode_cmd); } } /* Last arg (if present) should be an inode number */ if (optind < argc) { userino = strtoull(argv[optind], &p, 10); if ((*p != '\0')) { printf(_("%s is not a numeric inode value\n"), argv[optind]); exitcode = 1; return 0; } optind++; } /* Extra junk? */ if (optind < argc) return command_usage(&inode_cmd); /* -n option requires an inode number */ if (ret_next && userino == NULLFSINO) return command_usage(&inode_cmd); if (userino == NULLFSINO) { /* We are finding last inode in use */ result_ino = get_last_inode(); if (!result_ino) { exitcode = 1; return 0; } } else { if (ret_next) /* get next inode */ cmd = XFS_IOC_FSBULKSTAT; else /* get this inode */ cmd = XFS_IOC_FSBULKSTAT_SINGLE; bulkreq.lastip = &userino; bulkreq.icount = 1; bulkreq.ubuffer = &bstat; bulkreq.ocount = &count; if (xfsctl(file->name, file->fd, cmd, &bulkreq)) { if (!ret_next && errno == EINVAL) { /* Not in use */ result_ino = 0; } else { perror("xfsctl"); exitcode = 1; return 0; } } else if (ret_next) { /* The next inode in use, or 0 if none */ if (*bulkreq.ocount) result_ino = bstat.bs_ino; else result_ino = 0; } else { /* The inode we asked about */ result_ino = userino; } } if (verbose && result_ino) { /* Requested verbose and we have an answer */ printf("%llu:%d\n", result_ino, result_ino > XFS_MAXINUMBER_32 ? 64 : 32); } else if (userino == NULLFSINO) { /* Just checking 32 or 64 bit presence, non-verbose */ printf("%d\n", result_ino > XFS_MAXINUMBER_32 ? 1 : 0); } else { /* We asked about a specific inode, non-verbose */ printf("%llu\n", result_ino); } return 0; } void open_init(void) { open_cmd.name = "open"; open_cmd.altname = "o"; open_cmd.cfunc = open_f; open_cmd.argmin = 0; open_cmd.argmax = -1; open_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK; open_cmd.args = _("[-acdrstxT] [-m mode] [path]"); open_cmd.oneline = _("open the file specified by path"); open_cmd.help = open_help; stat_cmd.name = "stat"; stat_cmd.cfunc = stat_f; stat_cmd.argmin = 0; stat_cmd.argmax = 1; stat_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; stat_cmd.args = _("[-v]"); stat_cmd.oneline = _("statistics on the currently open file"); close_cmd.name = "close"; close_cmd.altname = "c"; close_cmd.cfunc = close_f; close_cmd.argmin = 0; close_cmd.argmax = 0; close_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; close_cmd.oneline = _("close the current open file"); statfs_cmd.name = "statfs"; statfs_cmd.cfunc = statfs_f; statfs_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; statfs_cmd.oneline = _("statistics on the filesystem of the currently open file"); chproj_cmd.name = "chproj"; chproj_cmd.cfunc = chproj_f; chproj_cmd.args = _("[-D | -R] projid"); chproj_cmd.argmin = 1; chproj_cmd.argmax = -1; chproj_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; chproj_cmd.oneline = _("change project identifier on the currently open file"); chproj_cmd.help = chproj_help; lsproj_cmd.name = "lsproj"; lsproj_cmd.cfunc = lsproj_f; lsproj_cmd.args = _("[-D | -R]"); lsproj_cmd.argmin = 0; lsproj_cmd.argmax = -1; lsproj_cmd.flags = CMD_NOMAP_OK; lsproj_cmd.oneline = _("list project identifier set on the currently open file"); lsproj_cmd.help = lsproj_help; extsize_cmd.name = "extsize"; extsize_cmd.cfunc = extsize_f; extsize_cmd.args = _("[-D | -R] [extsize]"); extsize_cmd.argmin = 0; extsize_cmd.argmax = -1; extsize_cmd.flags = CMD_NOMAP_OK; extsize_cmd.oneline = _("get/set preferred extent size (in bytes) for the open file"); extsize_cmd.help = extsize_help; inode_cmd.name = "inode"; inode_cmd.cfunc = inode_f; inode_cmd.args = _("[-nv] [num]"); inode_cmd.argmin = 0; inode_cmd.argmax = 3; inode_cmd.flags = CMD_NOMAP_OK; inode_cmd.oneline = _("Query inode number usage in the filesystem"); inode_cmd.help = inode_help; add_command(&open_cmd); add_command(&stat_cmd); add_command(&close_cmd); add_command(&statfs_cmd); add_command(&chproj_cmd); add_command(&lsproj_cmd); add_command(&extsize_cmd); add_command(&inode_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/parent.c0000644000000000000000000002464013063067173014546 0ustar /* * Copyright (c) 2005-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "path.h" #include "parent.h" #include "handle.h" #include "jdm.h" #include "init.h" #include "io.h" #define PARENTBUF_SZ 16384 #define BSTATBUF_SZ 16384 static cmdinfo_t parent_cmd; static int verbose_flag; static int err_status; static __u64 inodes_checked; static char *mntpt; /* * check out a parent entry to see if the values seem valid */ static void check_parent_entry(xfs_bstat_t *bstatp, parent_t *parent) { int sts; char fullpath[PATH_MAX]; struct stat statbuf; char *str; sprintf(fullpath, _("%s%s"), mntpt, parent->p_name); sts = lstat(fullpath, &statbuf); if (sts != 0) { fprintf(stderr, _("inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n"), (unsigned long long) bstatp->bs_ino, fullpath); if (verbose_flag) { fprintf(stderr, _("path \"%s\" does not stat for inode: %llu; err = %s\n"), fullpath, (unsigned long long) bstatp->bs_ino, strerror(errno)); } err_status++; return; } else { if (verbose_flag > 1) { printf(_("path \"%s\" found\n"), fullpath); } } if (statbuf.st_ino != bstatp->bs_ino) { fprintf(stderr, _("inode-path for inode: %llu is incorrect - wrong inode#\n"), (unsigned long long) bstatp->bs_ino); if (verbose_flag) { fprintf(stderr, _("ino mismatch for path \"%s\" %llu vs %llu\n"), fullpath, (unsigned long long)statbuf.st_ino, (unsigned long long)bstatp->bs_ino); } err_status++; return; } else if (verbose_flag > 1) { printf(_("inode number match: %llu\n"), (unsigned long long)statbuf.st_ino); } /* get parent path */ str = strrchr(fullpath, '/'); *str = '\0'; sts = stat(fullpath, &statbuf); if (sts != 0) { fprintf(stderr, _("parent path \"%s\" does not stat: %s\n"), fullpath, strerror(errno)); err_status++; return; } else { if (parent->p_ino != statbuf.st_ino) { fprintf(stderr, _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"), (unsigned long long) bstatp->bs_ino); if (verbose_flag) { fprintf(stderr, _("ino mismatch for path \"%s\" %llu vs %llu\n"), fullpath, (unsigned long long)parent->p_ino, (unsigned long long)statbuf.st_ino); } err_status++; return; } else { if (verbose_flag > 1) { printf(_("parent ino match for %llu\n"), (unsigned long long) parent->p_ino); } } } } static void check_parents(parent_t *parentbuf, size_t *parentbuf_size, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp) { int error, i; __u32 count; parent_t *entryp; do { error = jdm_parentpaths(fshandlep, statp, parentbuf, *parentbuf_size, &count); if (error == ERANGE) { *parentbuf_size *= 2; parentbuf = (parent_t *)realloc(parentbuf, *parentbuf_size); } else if (error) { fprintf(stderr, _("parentpaths failed for ino %llu: %s\n"), (unsigned long long) statp->bs_ino, strerror(errno)); err_status++; break; } } while (error == ERANGE); if (count == 0) { /* no links for inode - something wrong here */ fprintf(stderr, _("inode-path for inode: %llu is missing\n"), (unsigned long long) statp->bs_ino); err_status++; } entryp = parentbuf; for (i = 0; i < count; i++) { check_parent_entry(statp, entryp); entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen); } } static int do_bulkstat(parent_t *parentbuf, size_t *parentbuf_size, xfs_bstat_t *bstatbuf, int fsfd, jdm_fshandle_t *fshandlep) { __s32 buflenout; __u64 lastino = 0; xfs_bstat_t *p; xfs_bstat_t *endp; xfs_fsop_bulkreq_t bulkreq; struct stat mntstat; if (stat(mntpt, &mntstat)) { fprintf(stderr, _("can't stat mount point \"%s\": %s\n"), mntpt, strerror(errno)); return 1; } bulkreq.lastip = &lastino; bulkreq.icount = BSTATBUF_SZ; bulkreq.ubuffer = (void *)bstatbuf; bulkreq.ocount = &buflenout; while (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq) == 0) { if (*(bulkreq.ocount) == 0) { return 0; } for (p = bstatbuf, endp = bstatbuf + *bulkreq.ocount; p < endp; p++) { /* inode being modified, get synced data with iget */ if ( (!p->bs_nlink || !p->bs_mode) && p->bs_ino != 0 ) { if (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq) < 0) { fprintf(stderr, _("failed to get bulkstat information for inode %llu\n"), (unsigned long long) p->bs_ino); continue; } if (!p->bs_nlink || !p->bs_mode || !p->bs_ino) { fprintf(stderr, _("failed to get valid bulkstat information for inode %llu\n"), (unsigned long long) p->bs_ino); continue; } } /* skip root */ if (p->bs_ino == mntstat.st_ino) { continue; } if (verbose_flag > 1) { printf(_("checking inode %llu\n"), (unsigned long long) p->bs_ino); } /* print dotted progress */ if ((inodes_checked % 100) == 0 && verbose_flag == 1) { printf("."); fflush(stdout); } inodes_checked++; check_parents(parentbuf, parentbuf_size, fshandlep, p); } }/*while*/ fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno)); return 1; } static int parent_check(void) { int fsfd; jdm_fshandle_t *fshandlep; parent_t *parentbuf; size_t parentbuf_size = PARENTBUF_SZ; xfs_bstat_t *bstatbuf; err_status = 0; inodes_checked = 0; sync(); fsfd = file->fd; fshandlep = jdm_getfshandle(mntpt); if (fshandlep == NULL) { fprintf(stderr, _("unable to open \"%s\" for jdm: %s\n"), mntpt, strerror(errno)); return 1; } /* allocate buffers */ bstatbuf = (xfs_bstat_t *)calloc(BSTATBUF_SZ, sizeof(xfs_bstat_t)); parentbuf = (parent_t *)malloc(parentbuf_size); if (!bstatbuf || !parentbuf) { fprintf(stderr, _("unable to allocate buffers: %s\n"), strerror(errno)); err_status = 1; goto out; } if (do_bulkstat(parentbuf, &parentbuf_size, bstatbuf, fsfd, fshandlep) != 0) err_status++; if (err_status > 0) fprintf(stderr, _("num errors: %d\n"), err_status); else printf(_("succeeded checking %llu inodes\n"), (unsigned long long) inodes_checked); out: free(bstatbuf); free(parentbuf); free(fshandlep); return err_status; } static void print_parent_entry(parent_t *parent, int fullpath) { printf(_("p_ino = %llu\n"), (unsigned long long) parent->p_ino); printf(_("p_gen = %u\n"), parent->p_gen); printf(_("p_reclen = %u\n"), parent->p_reclen); if (fullpath) printf(_("p_name = \"%s%s\"\n"), mntpt, parent->p_name); else printf(_("p_name = \"%s\"\n"), parent->p_name); } static int parent_list(int fullpath) { void *handlep = NULL; size_t handlen; int error, i; int retval = 1; __u32 count; parent_t *entryp; parent_t *parentbuf = NULL; char *path = file->name; int pb_size = PARENTBUF_SZ; /* XXXX for linux libhandle version - to set libhandle fsfd cache */ { void *fshandle; size_t fshlen; if (path_to_fshandle(mntpt, &fshandle, &fshlen) != 0) { fprintf(stderr, _("%s: failed path_to_fshandle \"%s\": %s\n"), progname, path, strerror(errno)); goto error; } free_handle(fshandle, fshlen); } if (path_to_handle(path, &handlep, &handlen) != 0) { fprintf(stderr, _("%s: path_to_handle failed for \"%s\"\n"), progname, path); goto error; } do { parentbuf = (parent_t *)realloc(parentbuf, pb_size); if (!parentbuf) { fprintf(stderr, _("%s: unable to allocate parent buffer: %s\n"), progname, strerror(errno)); goto error; } if (fullpath) { error = parentpaths_by_handle(handlep, handlen, parentbuf, pb_size, &count); } else { error = parents_by_handle(handlep, handlen, parentbuf, pb_size, &count); } if (error == ERANGE) { pb_size *= 2; } else if (error) { fprintf(stderr, _("%s: %s call failed for \"%s\": %s\n"), progname, fullpath ? "parentpaths" : "parents", path, strerror(errno)); goto error; } } while (error == ERANGE); if (count == 0) { /* no links for inode - something wrong here */ fprintf(stderr, _("%s: inode-path is missing\n"), progname); goto error; } entryp = parentbuf; for (i = 0; i < count; i++) { print_parent_entry(entryp, fullpath); entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen); } retval = 0; error: free(handlep); free(parentbuf); return retval; } int parent_f(int argc, char **argv) { int c; int listpath_flag = 0; int check_flag = 0; fs_path_t *fs; static int tab_init; if (!tab_init) { tab_init = 1; fs_table_initialise(0, NULL, 0, NULL); } fs = fs_table_lookup(file->name, FS_MOUNT_POINT); if (!fs) { fprintf(stderr, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"), file->name); return 1; } mntpt = fs->fs_dir; verbose_flag = 0; while ((c = getopt(argc, argv, "cpv")) != EOF) { switch (c) { case 'c': check_flag = 1; break; case 'p': listpath_flag = 1; break; case 'v': verbose_flag++; break; default: return command_usage(&parent_cmd); } } if (!check_flag && !listpath_flag) /* default case */ exitcode = parent_list(listpath_flag); else { if (listpath_flag) exitcode = parent_list(listpath_flag); if (check_flag) exitcode = parent_check(); } return 0; } static void parent_help(void) { printf(_( "\n" " list the current file's parents and their filenames\n" "\n" " -c -- check the current file's file system for parent consistency\n" " -p -- list the current file's parents and their full paths\n" " -v -- verbose mode\n" "\n")); } void parent_init(void) { parent_cmd.name = "parent"; parent_cmd.cfunc = parent_f; parent_cmd.argmin = 0; parent_cmd.argmax = -1; parent_cmd.args = _("[-cpv]"); parent_cmd.flags = CMD_NOMAP_OK; parent_cmd.oneline = _("print or check parent inodes"); parent_cmd.help = parent_help; if (expert) add_command(&parent_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/pread.c0000644000000000000000000002467613063067173014361 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "command.h" #include "input.h" #include #include "init.h" #include "io.h" static cmdinfo_t pread_cmd; static void pread_help(void) { printf(_( "\n" " reads a range of bytes in a specified block size from the given offset\n" "\n" " Example:\n" " 'pread -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n" "\n" " Reads a segment of the currently open file, optionally dumping it to the\n" " standard output stream (with -v option) for subsequent inspection.\n" " The reads are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different pattern is requested.\n" " -B -- read backwards through the range from offset (backwards N bytes)\n" " -F -- read forwards through the range of bytes from offset (default)\n" " -v -- be verbose, dump out buffers (used when reading forwards)\n" " -R -- read at random offsets in the range of bytes\n" " -Z N -- zeed the random number generator (used when reading randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" #ifdef HAVE_PREADV " -V N -- use vectored IO with N iovecs of blocksize each (preadv)\n" #endif "\n" " When in \"random\" mode, the number of read operations will equal the\n" " number required to do a complete forward/backward scan of the range.\n" " Note that the offset within the range is chosen at random each time\n" " (an offset may be read more than once when operating in this mode).\n" "\n")); } void *buffer; size_t highwater; size_t buffersize; int vectors; struct iovec *iov; static int alloc_iovec( size_t bsize, int uflag, unsigned int seed) { int i; iov = calloc(vectors, sizeof(struct iovec)); if (!iov) return -1; buffersize = 0; for (i = 0; i < vectors; i++) { iov[i].iov_base = memalign(pagesize, bsize); if (!iov[i].iov_base) { perror("memalign"); goto unwind; } iov[i].iov_len = bsize; if (!uflag) memset(iov[i].iov_base, seed, bsize); } buffersize = bsize * vectors; return 0; unwind: for( ; i >= 0; i--) free(iov[i].iov_base); free(iov); iov = NULL; return -1; } int alloc_buffer( size_t bsize, int uflag, unsigned int seed) { if (vectors) return alloc_iovec(bsize, uflag, seed); if (bsize > highwater) { if (buffer) free(buffer); buffer = memalign(pagesize, bsize); if (!buffer) { perror("memalign"); highwater = buffersize = 0; return -1; } highwater = bsize; } buffersize = bsize; if (!uflag) memset(buffer, seed, buffersize); return 0; } void __dump_buffer( void *buf, off64_t offset, ssize_t len) { int i, j; char *p; for (i = 0, p = (char *)buf; i < len; i += 16) { char *s = p; printf("%08llx: ", (unsigned long long)offset + i); for (j = 0; j < 16 && i + j < len; j++, p++) printf("%02x ", *p); printf(" "); for (j = 0; j < 16 && i + j < len; j++, s++) { if (isalnum((int)*s)) printf("%c", *s); else printf("."); } printf("\n"); } } void dump_buffer( off64_t offset, ssize_t len) { int i, l; if (!vectors) { __dump_buffer(buffer, offset, len); return; } for (i = 0; len > 0 && i < vectors; i++) { l = min(len, iov[i].iov_len); __dump_buffer(iov[i].iov_base, offset, l); len -= l; offset += l; } } #ifdef HAVE_PREADV static int do_preadv( int fd, off64_t offset, ssize_t count, ssize_t buffer_size) { int vecs = 0; ssize_t oldlen = 0; ssize_t bytes = 0; /* trim the iovec if necessary */ if (count < buffersize) { size_t len = 0; while (len + iov[vecs].iov_len < count) { len += iov[vecs].iov_len; vecs++; } oldlen = iov[vecs].iov_len; iov[vecs].iov_len = count - len; vecs++; } else { vecs = vectors; } bytes = preadv(fd, iov, vectors, offset); /* restore trimmed iov */ if (oldlen) iov[vecs - 1].iov_len = oldlen; return bytes; } #else #define do_preadv(fd, offset, count, buffer_size) (0) #endif static int do_pread( int fd, off64_t offset, ssize_t count, ssize_t buffer_size) { if (!vectors) return pread(fd, buffer, min(count, buffer_size), offset); return do_preadv(fd, offset, count, buffer_size); } static int read_random( int fd, off64_t offset, long long count, long long *total, unsigned int seed, int eof) { off64_t end, off, range; ssize_t bytes; int ops = 0; srandom(seed); end = lseek(fd, 0, SEEK_END); offset = (eof || offset > end) ? end : offset; if ((bytes = (offset % buffersize))) offset -= bytes; offset = max(0, offset); if ((bytes = (count % buffersize))) count += bytes; count = max(buffersize, count); range = count - buffersize; *total = 0; while (count > 0) { if (range) off = ((offset + (random() % range)) / buffersize) * buffersize; else off = offset; bytes = do_pread(fd, off, buffersize, buffersize); if (bytes == 0) break; if (bytes < 0) { perror("pread"); return -1; } ops++; *total += bytes; if (bytes < buffersize) break; count -= bytes; } return ops; } static int read_backward( int fd, off64_t *offset, long long *count, long long *total, int eof) { off64_t end, off = *offset; ssize_t bytes = 0, bytes_requested; long long cnt = *count; int ops = 0; end = lseek(fd, 0, SEEK_END); off = eof ? end : min(end, lseek(fd, off, SEEK_SET)); if ((end = off - cnt) < 0) { cnt += end; /* subtraction, end is negative */ end = 0; } *total = 0; *count = cnt; *offset = off; /* Do initial unaligned read if needed */ if ((bytes_requested = (off % buffersize))) { off -= bytes_requested; bytes = do_pread(fd, off, bytes_requested, buffersize); if (bytes == 0) return ops; if (bytes < 0) { perror("pread"); return -1; } ops++; *total += bytes; if (bytes < bytes_requested) return ops; cnt -= bytes; } /* Iterate backward through the rest of the range */ while (cnt > end) { bytes_requested = min(cnt, buffersize); off -= bytes_requested; bytes = do_pread(fd, off, cnt, buffersize); if (bytes == 0) break; if (bytes < 0) { perror("pread"); return -1; } ops++; *total += bytes; if (bytes < bytes_requested) break; cnt -= bytes; } return ops; } static int read_forward( int fd, off64_t offset, long long count, long long *total, int verbose, int onlyone, int eof) { ssize_t bytes; int ops = 0; *total = 0; while (count > 0 || eof) { bytes = do_pread(fd, offset, count, buffersize); if (bytes == 0) break; if (bytes < 0) { perror("pread"); return -1; } ops++; if (verbose) dump_buffer(offset, bytes); *total += bytes; if (onlyone || bytes < min(count, buffersize)) break; offset += bytes; count -= bytes; } return ops; } int read_buffer( int fd, off64_t offset, long long count, long long *total, int verbose, int onlyone) { return read_forward(fd, offset, count, total, verbose, onlyone, 0); } static int pread_f( int argc, char **argv) { size_t bsize; off64_t offset; unsigned int zeed = 0; long long count, total, tmp; size_t fsblocksize, fssectsize; struct timeval t1, t2; char *sp; int Cflag, qflag, uflag, vflag; int eof = 0, direction = IO_FORWARD; int c; Cflag = qflag = uflag = vflag = 0; init_cvtnum(&fsblocksize, &fssectsize); bsize = fsblocksize; while ((c = getopt(argc, argv, "b:BCFRquvV:Z:")) != EOF) { switch (c) { case 'b': tmp = cvtnum(fsblocksize, fssectsize, optarg); if (tmp < 0) { printf(_("non-numeric bsize -- %s\n"), optarg); return 0; } bsize = tmp; break; case 'C': Cflag = 1; break; case 'F': direction = IO_FORWARD; break; case 'B': direction = IO_BACKWARD; break; case 'R': direction = IO_RANDOM; break; case 'q': qflag = 1; break; case 'u': uflag = 1; break; case 'v': vflag = 1; break; #ifdef HAVE_PREADV case 'V': vectors = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric vector count == %s\n"), optarg); return 0; } break; #endif case 'Z': zeed = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric seed -- %s\n"), optarg); return 0; } break; default: return command_usage(&pread_cmd); } } if (optind != argc - 2) return command_usage(&pread_cmd); offset = cvtnum(fsblocksize, fssectsize, argv[optind]); if (offset < 0 && (direction & (IO_RANDOM|IO_BACKWARD))) { eof = -1; /* read from EOF */ } else if (offset < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } optind++; count = cvtnum(fsblocksize, fssectsize, argv[optind]); if (count < 0 && (direction & (IO_RANDOM|IO_FORWARD))) { eof = -1; /* read to EOF */ } else if (count < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } if (alloc_buffer(bsize, uflag, 0xabababab) < 0) return 0; gettimeofday(&t1, NULL); switch (direction) { case IO_RANDOM: if (!zeed) /* srandom seed */ zeed = time(NULL); c = read_random(file->fd, offset, count, &total, zeed, eof); break; case IO_FORWARD: c = read_forward(file->fd, offset, count, &total, vflag, 0, eof); if (eof) count = total; break; case IO_BACKWARD: c = read_backward(file->fd, &offset, &count, &total, eof); break; default: ASSERT(0); } if (c < 0) return 0; if (qflag) return 0; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); report_io_times("read", &t2, (long long)offset, count, total, c, Cflag); return 0; } void pread_init(void) { pread_cmd.name = "pread"; pread_cmd.altname = "r"; pread_cmd.cfunc = pread_f; pread_cmd.argmin = 2; pread_cmd.argmax = -1; pread_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; pread_cmd.args = _("[-b bs] [-v] [-i N] [-FBR [-Z N]] off len"); pread_cmd.oneline = _("reads a number of bytes at a specified offset"); pread_cmd.help = pread_help; add_command(&pread_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/prealloc.c0000644000000000000000000002340213063067173015051 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if defined(HAVE_FALLOCATE) #include #endif #include "command.h" #include "input.h" #include "init.h" #include "io.h" #ifndef FALLOC_FL_PUNCH_HOLE #define FALLOC_FL_PUNCH_HOLE 0x02 #endif #ifndef FALLOC_FL_COLLAPSE_RANGE #define FALLOC_FL_COLLAPSE_RANGE 0x08 #endif #ifndef FALLOC_FL_ZERO_RANGE #define FALLOC_FL_ZERO_RANGE 0x10 #endif #ifndef FALLOC_FL_INSERT_RANGE #define FALLOC_FL_INSERT_RANGE 0x20 #endif #ifndef FALLOC_FL_UNSHARE_RANGE #define FALLOC_FL_UNSHARE_RANGE 0x40 #endif static cmdinfo_t allocsp_cmd; static cmdinfo_t freesp_cmd; static cmdinfo_t resvsp_cmd; static cmdinfo_t unresvsp_cmd; static cmdinfo_t zero_cmd; #if defined(HAVE_FALLOCATE) static cmdinfo_t falloc_cmd; static cmdinfo_t fpunch_cmd; static cmdinfo_t fcollapse_cmd; static cmdinfo_t finsert_cmd; static cmdinfo_t fzero_cmd; #endif static int offset_length( char *offset, char *length, xfs_flock64_t *segment) { size_t blocksize, sectsize; init_cvtnum(&blocksize, §size); memset(segment, 0, sizeof(*segment)); segment->l_whence = SEEK_SET; segment->l_start = cvtnum(blocksize, sectsize, offset); if (segment->l_start < 0) { printf(_("non-numeric offset argument -- %s\n"), offset); return 0; } segment->l_len = cvtnum(blocksize, sectsize, length); if (segment->l_len < 0) { printf(_("non-numeric length argument -- %s\n"), length); return 0; } return 1; } static int allocsp_f( int argc, char **argv) { xfs_flock64_t segment; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (xfsctl(file->name, file->fd, XFS_IOC_ALLOCSP64, &segment) < 0) { perror("XFS_IOC_ALLOCSP64"); return 0; } return 0; } static int freesp_f( int argc, char **argv) { xfs_flock64_t segment; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (xfsctl(file->name, file->fd, XFS_IOC_FREESP64, &segment) < 0) { perror("XFS_IOC_FREESP64"); return 0; } return 0; } static int resvsp_f( int argc, char **argv) { xfs_flock64_t segment; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (xfsctl(file->name, file->fd, XFS_IOC_RESVSP64, &segment) < 0) { perror("XFS_IOC_RESVSP64"); return 0; } return 0; } static int unresvsp_f( int argc, char **argv) { xfs_flock64_t segment; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (xfsctl(file->name, file->fd, XFS_IOC_UNRESVSP64, &segment) < 0) { perror("XFS_IOC_UNRESVSP64"); return 0; } return 0; } static int zero_f( int argc, char **argv) { xfs_flock64_t segment; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (xfsctl(file->name, file->fd, XFS_IOC_ZERO_RANGE, &segment) < 0) { perror("XFS_IOC_ZERO_RANGE"); return 0; } return 0; } #if defined (HAVE_FALLOCATE) static void falloc_help(void) { printf(_( "\n" " modifies space associated with part of a file via fallocate" "\n" " Example:\n" " 'falloc 0 1m' - fills all holes within the first megabyte\n" "\n" " falloc uses the fallocate system call to alter space allocations in the\n" " open file. The following operations are supported:\n" " All the file offsets are in units of bytes.\n" " -c -- collapses the given range.\n" " -i -- inserts a hole into the given range of the file.\n" " -k -- do not change file size.\n" " -p -- unmap the given range from the file.\n" " -u -- unshare shared extents in the given range.\n" "\n")); } static int fallocate_f( int argc, char **argv) { xfs_flock64_t segment; int mode = 0; int c; while ((c = getopt(argc, argv, "cikpu")) != EOF) { switch (c) { case 'c': mode = FALLOC_FL_COLLAPSE_RANGE; break; case 'i': mode = FALLOC_FL_INSERT_RANGE; break; case 'k': mode = FALLOC_FL_KEEP_SIZE; break; case 'p': mode = FALLOC_FL_PUNCH_HOLE; break; case 'u': mode = FALLOC_FL_UNSHARE_RANGE; break; default: command_usage(&falloc_cmd); } } if (optind != argc - 2) return command_usage(&falloc_cmd); if (!offset_length(argv[optind], argv[optind+1], &segment)) return 0; if (fallocate(file->fd, mode, segment.l_start, segment.l_len)) { perror("fallocate"); return 0; } return 0; } static int fpunch_f( int argc, char **argv) { xfs_flock64_t segment; int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (fallocate(file->fd, mode, segment.l_start, segment.l_len)) { perror("fallocate"); return 0; } return 0; } static int fcollapse_f( int argc, char **argv) { xfs_flock64_t segment; int mode = FALLOC_FL_COLLAPSE_RANGE; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (fallocate(file->fd, mode, segment.l_start, segment.l_len)) { perror("fallocate"); return 0; } return 0; } static int finsert_f( int argc, char **argv) { xfs_flock64_t segment; int mode = FALLOC_FL_INSERT_RANGE; if (!offset_length(argv[1], argv[2], &segment)) return 0; if (fallocate(file->fd, mode, segment.l_start, segment.l_len)) { perror("fallocate"); return 0; } return 0; } static int fzero_f( int argc, char **argv) { xfs_flock64_t segment; int mode = FALLOC_FL_ZERO_RANGE; int index = 1; if (strncmp(argv[index], "-k", 3) == 0) { mode |= FALLOC_FL_KEEP_SIZE; index++; } if (!offset_length(argv[index], argv[index + 1], &segment)) return 0; if (fallocate(file->fd, mode, segment.l_start, segment.l_len)) { perror("fallocate"); return 0; } return 0; } static int funshare_f( int argc, char **argv) { xfs_flock64_t segment; int mode = FALLOC_FL_UNSHARE_RANGE; int index = 1; if (!offset_length(argv[index], argv[index + 1], &segment)) return 0; if (fallocate(file->fd, mode, segment.l_start, segment.l_len)) { perror("fallocate"); return 0; } return 0; } #endif /* HAVE_FALLOCATE */ void prealloc_init(void) { allocsp_cmd.name = "allocsp"; allocsp_cmd.cfunc = allocsp_f; allocsp_cmd.argmin = 2; allocsp_cmd.argmax = 2; allocsp_cmd.flags = CMD_NOMAP_OK; allocsp_cmd.args = _("off len"); allocsp_cmd.oneline = _("allocates zeroed space for part of a file"); freesp_cmd.name = "freesp"; freesp_cmd.cfunc = freesp_f; freesp_cmd.argmin = 2; freesp_cmd.argmax = 2; freesp_cmd.flags = CMD_NOMAP_OK; freesp_cmd.args = _("off len"); freesp_cmd.oneline = _("frees space associated with part of a file"); resvsp_cmd.name = "resvsp"; resvsp_cmd.cfunc = resvsp_f; resvsp_cmd.argmin = 2; resvsp_cmd.argmax = 2; resvsp_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; resvsp_cmd.args = _("off len"); resvsp_cmd.oneline = _("reserves space associated with part of a file"); unresvsp_cmd.name = "unresvsp"; unresvsp_cmd.cfunc = unresvsp_f; unresvsp_cmd.argmin = 2; unresvsp_cmd.argmax = 2; unresvsp_cmd.args = _("off len"); unresvsp_cmd.flags = CMD_NOMAP_OK; unresvsp_cmd.oneline = _("frees reserved space associated with part of a file"); zero_cmd.name = "zero"; zero_cmd.cfunc = zero_f; zero_cmd.argmin = 2; zero_cmd.argmax = 2; zero_cmd.flags = CMD_NOMAP_OK; zero_cmd.args = _("off len"); zero_cmd.oneline = _("Converts the given range of a file to allocated zeros"); add_command(&allocsp_cmd); add_command(&freesp_cmd); add_command(&resvsp_cmd); add_command(&unresvsp_cmd); add_command(&zero_cmd); #if defined (HAVE_FALLOCATE) falloc_cmd.name = "falloc"; falloc_cmd.cfunc = fallocate_f; falloc_cmd.argmin = 2; falloc_cmd.argmax = -1; falloc_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; falloc_cmd.args = _("[-c] [-k] [-p] [-u] off len"); falloc_cmd.oneline = _("allocates space associated with part of a file via fallocate"); falloc_cmd.help = falloc_help; add_command(&falloc_cmd); fpunch_cmd.name = "fpunch"; fpunch_cmd.cfunc = fpunch_f; fpunch_cmd.argmin = 2; fpunch_cmd.argmax = 2; fpunch_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fpunch_cmd.args = _("off len"); fpunch_cmd.oneline = _("de-allocates space assocated with part of a file via fallocate"); add_command(&fpunch_cmd); fcollapse_cmd.name = "fcollapse"; fcollapse_cmd.cfunc = fcollapse_f; fcollapse_cmd.argmin = 2; fcollapse_cmd.argmax = 2; fcollapse_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fcollapse_cmd.args = _("off len"); fcollapse_cmd.oneline = _("de-allocates space and eliminates the hole by shifting extents"); add_command(&fcollapse_cmd); finsert_cmd.name = "finsert"; finsert_cmd.cfunc = finsert_f; finsert_cmd.argmin = 2; finsert_cmd.argmax = 2; finsert_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; finsert_cmd.args = _("off len"); finsert_cmd.oneline = _("creates new space for writing within file by shifting extents"); add_command(&finsert_cmd); fzero_cmd.name = "fzero"; fzero_cmd.cfunc = fzero_f; fzero_cmd.argmin = 2; fzero_cmd.argmax = 3; fzero_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fzero_cmd.args = _("[-k] off len"); fzero_cmd.oneline = _("zeroes space and eliminates holes by preallocating"); add_command(&fzero_cmd); fzero_cmd.name = "funshare"; fzero_cmd.cfunc = funshare_f; fzero_cmd.argmin = 2; fzero_cmd.argmax = 2; fzero_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; fzero_cmd.args = _("off len"); fzero_cmd.oneline = _("unshares shared blocks within the range"); add_command(&fzero_cmd); #endif /* HAVE_FALLOCATE */ } xfsprogs-4.9.0+nmu1ubuntu2/io/pwrite.c0000644000000000000000000002221413063067173014562 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t pwrite_cmd; static void pwrite_help(void) { printf(_( "\n" " writes a range of bytes (in block size increments) from the given offset\n" "\n" " Example:\n" " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Writes into a segment of the currently open file, using either a buffer\n" " filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n" " The writes are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different write pattern is requested.\n" " -S -- use an alternate seed number for filling the write buffer\n" " -i -- input file, source of data to write (used when writing forward)\n" " -d -- open the input file for direct IO\n" " -s -- skip a number of bytes at the start of the input file\n" " -w -- call fdatasync(2) at the end (included in timing results)\n" " -W -- call fsync(2) at the end (included in timing results)\n" " -B -- write backwards through the range from offset (backwards N bytes)\n" " -F -- write forwards through the range of bytes from offset (default)\n" " -R -- write at random offsets in the specified range of bytes\n" " -Z N -- zeed the random number generator (used when writing randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" #ifdef HAVE_PWRITEV " -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n" #endif "\n")); } #ifdef HAVE_PWRITEV static int do_pwritev( int fd, off64_t offset, ssize_t count, ssize_t buffer_size) { int vecs = 0; ssize_t oldlen = 0; ssize_t bytes = 0; /* trim the iovec if necessary */ if (count < buffersize) { size_t len = 0; while (len + iov[vecs].iov_len < count) { len += iov[vecs].iov_len; vecs++; } oldlen = iov[vecs].iov_len; iov[vecs].iov_len = count - len; vecs++; } else { vecs = vectors; } bytes = pwritev(fd, iov, vectors, offset); /* restore trimmed iov */ if (oldlen) iov[vecs - 1].iov_len = oldlen; return bytes; } #else #define do_pwritev(fd, offset, count, buffer_size) (0) #endif static int do_pwrite( int fd, off64_t offset, ssize_t count, ssize_t buffer_size) { if (!vectors) return pwrite(fd, buffer, min(count, buffer_size), offset); return do_pwritev(fd, offset, count, buffer_size); } static int write_random( off64_t offset, long long count, unsigned int seed, long long *total) { off64_t off, range; ssize_t bytes; int ops = 0; srandom(seed); if ((bytes = (offset % buffersize))) offset -= bytes; offset = max(0, offset); if ((bytes = (count % buffersize))) count += bytes; count = max(buffersize, count); range = count - buffersize; *total = 0; while (count > 0) { if (range) off = ((offset + (random() % range)) / buffersize) * buffersize; else off = offset; bytes = do_pwrite(file->fd, off, buffersize, buffersize); if (bytes == 0) break; if (bytes < 0) { perror("pwrite"); return -1; } ops++; *total += bytes; if (bytes < buffersize) break; count -= bytes; } return ops; } static int write_backward( off64_t offset, long long *count, long long *total) { off64_t end, off = offset; ssize_t bytes = 0, bytes_requested; long long cnt = *count; int ops = 0; if ((end = off - cnt) < 0) { cnt += end; /* subtraction, end is negative */ end = 0; } *total = 0; *count = cnt; /* Do initial unaligned write if needed */ if ((bytes_requested = (off % buffersize))) { bytes_requested = min(cnt, bytes_requested); off -= bytes_requested; bytes = do_pwrite(file->fd, off, bytes_requested, buffersize); if (bytes == 0) return ops; if (bytes < 0) { perror("pwrite"); return -1; } ops++; *total += bytes; if (bytes < bytes_requested) return ops; cnt -= bytes; } /* Iterate backward through the rest of the range */ while (cnt > end) { bytes_requested = min(cnt, buffersize); off -= bytes_requested; bytes = do_pwrite(file->fd, off, cnt, buffersize); if (bytes == 0) break; if (bytes < 0) { perror("pwrite"); return -1; } ops++; *total += bytes; if (bytes < bytes_requested) break; cnt -= bytes; } return ops; } static int write_buffer( off64_t offset, long long count, size_t bs, int fd, off64_t skip, long long *total) { ssize_t bytes; long long bar = min(bs, count); int ops = 0; *total = 0; while (count >= 0) { if (fd > 0) { /* input file given, read buffer first */ if (read_buffer(fd, skip + *total, bs, &bar, 0, 1) < 0) break; } bytes = do_pwrite(file->fd, offset, count, bar); if (bytes == 0) break; if (bytes < 0) { perror("pwrite"); return -1; } ops++; *total += bytes; if (bytes < min(count, bar)) break; offset += bytes; count -= bytes; if (count == 0) break; } return ops; } static int pwrite_f( int argc, char **argv) { size_t bsize; off64_t offset, skip = 0; long long count, total, tmp; unsigned int zeed = 0, seed = 0xcdcdcdcd; size_t fsblocksize, fssectsize; struct timeval t1, t2; char *sp, *infile = NULL; int Cflag, qflag, uflag, dflag, wflag, Wflag; int direction = IO_FORWARD; int c, fd = -1; Cflag = qflag = uflag = dflag = wflag = Wflag = 0; init_cvtnum(&fsblocksize, &fssectsize); bsize = fsblocksize; while ((c = getopt(argc, argv, "b:BCdf:Fi:qRs:S:uV:wWZ:")) != EOF) { switch (c) { case 'b': tmp = cvtnum(fsblocksize, fssectsize, optarg); if (tmp < 0) { printf(_("non-numeric bsize -- %s\n"), optarg); return 0; } bsize = tmp; break; case 'C': Cflag = 1; break; case 'F': direction = IO_FORWARD; break; case 'B': direction = IO_BACKWARD; break; case 'R': direction = IO_RANDOM; break; case 'd': dflag = 1; break; case 'f': case 'i': infile = optarg; break; case 's': skip = cvtnum(fsblocksize, fssectsize, optarg); if (skip < 0) { printf(_("non-numeric skip -- %s\n"), optarg); return 0; } break; case 'S': seed = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric seed -- %s\n"), optarg); return 0; } break; case 'q': qflag = 1; break; case 'u': uflag = 1; break; case 'V': vectors = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric vector count == %s\n"), optarg); return 0; } break; case 'w': wflag = 1; break; case 'W': Wflag = 1; break; case 'Z': zeed = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric seed -- %s\n"), optarg); return 0; } break; default: return command_usage(&pwrite_cmd); } } if (((skip || dflag) && !infile) || (optind != argc - 2)) return command_usage(&pwrite_cmd); if (infile && direction != IO_FORWARD) return command_usage(&pwrite_cmd); offset = cvtnum(fsblocksize, fssectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; count = cvtnum(fsblocksize, fssectsize, argv[optind]); if (count < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } if (alloc_buffer(bsize, uflag, seed) < 0) return 0; c = IO_READONLY | (dflag ? IO_DIRECT : 0); if (infile && ((fd = openfile(infile, NULL, c, 0)) < 0)) return 0; gettimeofday(&t1, NULL); switch (direction) { case IO_RANDOM: if (!zeed) /* srandom seed */ zeed = time(NULL); c = write_random(offset, count, zeed, &total); break; case IO_FORWARD: c = write_buffer(offset, count, bsize, fd, skip, &total); break; case IO_BACKWARD: c = write_backward(offset, &count, &total); break; default: total = 0; ASSERT(0); } if (c < 0) goto done; if (Wflag) fsync(file->fd); if (wflag) fdatasync(file->fd); if (qflag) goto done; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); report_io_times("wrote", &t2, (long long)offset, count, total, c, Cflag); done: if (infile) close(fd); return 0; } void pwrite_init(void) { pwrite_cmd.name = "pwrite"; pwrite_cmd.altname = "w"; pwrite_cmd.cfunc = pwrite_f; pwrite_cmd.argmin = 2; pwrite_cmd.argmax = -1; pwrite_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; pwrite_cmd.args = _("[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] [-FBR [-Z N]] [-V N] off len"); pwrite_cmd.oneline = _("writes a number of bytes at a specified offset"); pwrite_cmd.help = pwrite_help; add_command(&pwrite_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/readdir.c0000644000000000000000000001003613063067173014661 0ustar /* * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" #include #include static struct cmdinfo readdir_cmd; const char *d_type_str(unsigned int type) { const char *str; switch (type) { case DT_UNKNOWN: str = "DT_UNKNOWN"; break; case DT_FIFO: str = "DT_FIFO"; break; case DT_CHR: str = "DT_CHR"; break; case DT_DIR: str = "DT_DIR"; break; case DT_BLK: str = "DT_BLK"; break; case DT_REG: str = "DT_REG"; break; case DT_LNK: str = "DT_LNK"; break; case DT_SOCK: str = "DT_SOCK"; break; case DT_WHT: str = "DT_WHT"; break; default: str = "ERROR!"; break; } return str; } static void dump_dirent( long long offset, struct dirent *dirent) { printf("%08llx: d_ino: 0x%08lx", offset, dirent->d_ino); #ifdef _DIRENT_HAVE_D_OFF printf(" d_off: 0x%08lx", dirent->d_off); #endif #ifdef _DIRENT_HAVE_D_RECLEN printf(" d_reclen: 0x%x", dirent->d_reclen); #endif #ifdef _DIRENT_HAVE_D_TYPE printf(" d_type: %s", d_type_str(dirent->d_type)); #endif printf(" d_name: %s\n", dirent->d_name); } static int read_directory( DIR *dir, long long offset, unsigned long long length, int dump, unsigned long long *total) { struct dirent *dirent; int count = 0; seekdir(dir, offset); *total = 0; while (*total < length) { dirent = readdir(dir); if (!dirent) break; #ifdef _DIRENT_HAVE_D_RECLEN *total += dirent->d_reclen; #else *total += dirent->d_namlen + sizeof(*dirent); #endif count++; if (dump) { dump_dirent(offset, dirent); #ifdef _DIRENT_HAVE_D_OFF offset = dirent->d_off; #else /* Some platforms don't have dirent->d_off, but because * it is used only for dumping the value, it should be * safe to only set it to zero in such case. */ offset = 0; #endif } } return count; } static int readdir_f( int argc, char **argv) { int cnt; unsigned long long total; int c; size_t fsblocksize, fssectsize; struct timeval t1, t2; char s1[64], s2[64], ts[64]; long long offset = -1; unsigned long long length = -1; /* max length limit */ int verbose = 0; DIR *dir; int dfd; init_cvtnum(&fsblocksize, &fssectsize); while ((c = getopt(argc, argv, "l:o:v")) != EOF) { switch (c) { case 'l': length = cvtnum(fsblocksize, fssectsize, optarg); break; case 'o': offset = cvtnum(fsblocksize, fssectsize, optarg); break; case 'v': verbose = 1; break; default: return command_usage(&readdir_cmd); } } dfd = dup(file->fd); if (dfd < 0) return -1; dir = fdopendir(dfd); if (!dir) { close(dfd); return -1; } if (offset == -1) { rewinddir(dir); offset = telldir(dir); } gettimeofday(&t1, NULL); cnt = read_directory(dir, offset, length, verbose, &total); gettimeofday(&t2, NULL); closedir(dir); close(dfd); t2 = tsub(t2, t1); timestr(&t2, ts, sizeof(ts), 0); cvtstr(total, s1, sizeof(s1)); cvtstr(tdiv(total, t2), s2, sizeof(s2)); printf(_("read %llu bytes from offset %lld\n"), total, offset); printf(_("%s, %d ops, %s (%s/sec and %.4f ops/sec)\n"), s1, cnt, ts, s2, tdiv(cnt, t2)); return 0; } void readdir_init(void) { readdir_cmd.name = "readdir"; readdir_cmd.cfunc = readdir_f; readdir_cmd.argmax = 5; readdir_cmd.flags = CMD_NOMAP_OK|CMD_FOREIGN_OK; readdir_cmd.args = _("[-v][-o offset][-l length]"); readdir_cmd.oneline = _("read directory entries"); add_command(&readdir_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/reflink.c0000644000000000000000000002025113063067173014701 0ustar /* * Copyright (c) 2015 Oracle, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t dedupe_cmd; static cmdinfo_t reflink_cmd; static void dedupe_help(void) { printf(_("\n\ Links a range of bytes (in block size increments) from a file into a range\n\ of bytes in the open file. The contents of both file ranges must match.\n\ \n\ Example:\n\ 'dedupe some_file 0 4096 32768' - links 32768 bytes from some_file at\n\ offset 0 to into the open file at\n\ position 4096\n\ \n\ Reflink a range of blocks from a given input file to the open file. Both\n\ files share the same range of physical disk blocks; a write to the shared\n\ range of either file should result in the write landing in a new block and\n\ that range of the file being remapped (i.e. copy-on-write). Both files\n\ must reside on the same filesystem, and the contents of both ranges must\n\ match.\n\ ")); } static uint64_t dedupe_ioctl( int fd, uint64_t soffset, uint64_t doffset, uint64_t len, int *ops) { struct xfs_extent_data *args; struct xfs_extent_data_info *info; int error; uint64_t deduped = 0; args = calloc(1, sizeof(struct xfs_extent_data) + sizeof(struct xfs_extent_data_info)); if (!args) goto done; info = (struct xfs_extent_data_info *)(args + 1); args->logical_offset = soffset; args->length = len; args->dest_count = 1; info->fd = file->fd; info->logical_offset = doffset; while (args->length > 0 || !*ops) { error = ioctl(fd, XFS_IOC_FILE_EXTENT_SAME, args); if (error) { perror("XFS_IOC_FILE_EXTENT_SAME"); goto done; } if (info->status < 0) { fprintf(stderr, "dedupe: %s\n", _(strerror(-info->status))); goto done; } if (info->status == XFS_EXTENT_DATA_DIFFERS) { fprintf(stderr, "dedupe: %s\n", _("Extents did not match.")); goto done; } if (args->length != 0 && (info->bytes_deduped == 0 || info->bytes_deduped > args->length)) break; (*ops)++; args->logical_offset += info->bytes_deduped; info->logical_offset += info->bytes_deduped; if (args->length >= info->bytes_deduped) args->length -= info->bytes_deduped; deduped += info->bytes_deduped; } done: free(args); return deduped; } static int dedupe_f( int argc, char **argv) { off64_t soffset, doffset; long long count, total; char *infile; int condensed, quiet_flag; size_t fsblocksize, fssectsize; struct timeval t1, t2; int c, ops = 0, fd = -1; condensed = quiet_flag = 0; init_cvtnum(&fsblocksize, &fssectsize); while ((c = getopt(argc, argv, "Cq")) != EOF) { switch (c) { case 'C': condensed = 1; break; case 'q': quiet_flag = 1; break; default: return command_usage(&dedupe_cmd); } } if (optind != argc - 4) return command_usage(&dedupe_cmd); infile = argv[optind]; optind++; soffset = cvtnum(fsblocksize, fssectsize, argv[optind]); if (soffset < 0) { printf(_("non-numeric src offset argument -- %s\n"), argv[optind]); return 0; } optind++; doffset = cvtnum(fsblocksize, fssectsize, argv[optind]); if (doffset < 0) { printf(_("non-numeric dest offset argument -- %s\n"), argv[optind]); return 0; } optind++; count = cvtnum(fsblocksize, fssectsize, argv[optind]); if (count < 0) { printf(_("non-positive length argument -- %s\n"), argv[optind]); return 0; } fd = openfile(infile, NULL, IO_READONLY, 0); if (fd < 0) return 0; gettimeofday(&t1, NULL); total = dedupe_ioctl(fd, soffset, doffset, count, &ops); if (ops == 0 || quiet_flag) goto done; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); report_io_times("deduped", &t2, (long long)doffset, count, total, ops, condensed); done: close(fd); return 0; } static void reflink_help(void) { printf(_("\n\ Links a range of bytes (in block size increments) from a file into a range\n\ of bytes in the open file. The two extent ranges need not contain identical\n\ data.\n\ \n\ Example:\n\ 'reflink some_file 0 4096 32768' - links 32768 bytes from some_file at\n\ offset 0 to into the open file at\n\ position 4096\n\ 'reflink some_file' - links all bytes from some_file into the open file\n\ at position 0\n\ \n\ Reflink a range of blocks from a given input file to the open file. Both\n\ files share the same range of physical disk blocks; a write to the shared\n\ range of either file should result in the write landing in a new block and\n\ that range of the file being remapped (i.e. copy-on-write). Both files\n\ must reside on the same filesystem.\n\ ")); } static uint64_t reflink_ioctl( int fd, uint64_t soffset, uint64_t doffset, uint64_t len, int *ops) { struct xfs_clone_args args; int error; if (soffset == 0 && doffset == 0 && len == 0) { error = ioctl(file->fd, XFS_IOC_CLONE, fd); if (error) perror("XFS_IOC_CLONE"); } else { args.src_fd = fd; args.src_offset = soffset; args.src_length = len; args.dest_offset = doffset; error = ioctl(file->fd, XFS_IOC_CLONE_RANGE, &args); if (error) perror("XFS_IOC_CLONE_RANGE"); } if (!error) (*ops)++; return error ? 0 : len; } static int reflink_f( int argc, char **argv) { off64_t soffset, doffset; long long count = 0, total; char *infile = NULL; int condensed, quiet_flag; size_t fsblocksize, fssectsize; struct timeval t1, t2; int c, ops = 0, fd = -1; condensed = quiet_flag = 0; doffset = soffset = 0; init_cvtnum(&fsblocksize, &fssectsize); while ((c = getopt(argc, argv, "Cq")) != EOF) { switch (c) { case 'C': condensed = 1; break; case 'q': quiet_flag = 1; break; default: return command_usage(&reflink_cmd); } } if (optind != argc - 4 && optind != argc - 1) return command_usage(&reflink_cmd); infile = argv[optind]; optind++; if (optind == argc) goto clone_all; soffset = cvtnum(fsblocksize, fssectsize, argv[optind]); if (soffset < 0) { printf(_("non-numeric src offset argument -- %s\n"), argv[optind]); return 0; } optind++; doffset = cvtnum(fsblocksize, fssectsize, argv[optind]); if (doffset < 0) { printf(_("non-numeric dest offset argument -- %s\n"), argv[optind]); return 0; } optind++; count = cvtnum(fsblocksize, fssectsize, argv[optind]); if (count < 0) { printf(_("non-positive length argument -- %s\n"), argv[optind]); return 0; } clone_all: fd = openfile(infile, NULL, IO_READONLY, 0); if (fd < 0) return 0; gettimeofday(&t1, NULL); total = reflink_ioctl(fd, soffset, doffset, count, &ops); if (ops == 0 || quiet_flag) goto done; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); report_io_times("linked", &t2, (long long)doffset, count, total, ops, condensed); done: close(fd); return 0; } void reflink_init(void) { reflink_cmd.name = "reflink"; reflink_cmd.altname = "rl"; reflink_cmd.cfunc = reflink_f; reflink_cmd.argmin = 4; reflink_cmd.argmax = -1; reflink_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; reflink_cmd.args = _("infile src_off dst_off len"); reflink_cmd.oneline = _("reflinks a number of bytes at a specified offset"); reflink_cmd.help = reflink_help; add_command(&reflink_cmd); dedupe_cmd.name = "dedupe"; dedupe_cmd.altname = "dd"; dedupe_cmd.cfunc = dedupe_f; dedupe_cmd.argmin = 4; dedupe_cmd.argmax = -1; dedupe_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; dedupe_cmd.args = _("infile src_off dst_off len"); dedupe_cmd.oneline = _("dedupes a number of bytes at a specified offset"); dedupe_cmd.help = dedupe_help; add_command(&dedupe_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/resblks.c0000644000000000000000000000361513063067173014721 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t resblks_cmd; static int resblks_f(int argc, char **argv); static int resblks_f( int argc, char **argv) { xfs_fsop_resblks_t res; long long blks; if (argc == 2) { blks = cvtnum(file->geom.blocksize, file->geom.sectsize, argv[1]); if (blks < 0) { printf(_("non-numeric argument -- %s\n"), argv[1]); return 0; } res.resblks = blks; if (xfsctl(file->name, file->fd, XFS_IOC_SET_RESBLKS, &res) < 0) { perror("XFS_IOC_SET_RESBLKS"); return 0; } } else if (xfsctl(file->name, file->fd, XFS_IOC_GET_RESBLKS, &res) < 0) { perror("XFS_IOC_GET_RESBLKS"); return 0; } printf(_("reserved blocks = %llu\n"), (unsigned long long) res.resblks); printf(_("available reserved blocks = %llu\n"), (unsigned long long) res.resblks_avail); return 0; } void resblks_init(void) { resblks_cmd.name = "resblks"; resblks_cmd.cfunc = resblks_f; resblks_cmd.argmin = 0; resblks_cmd.argmax = 1; resblks_cmd.flags = CMD_NOMAP_OK; resblks_cmd.args = _("[blocks]"); resblks_cmd.oneline = _("get and/or set count of reserved filesystem blocks"); if (expert) add_command(&resblks_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/seek.c0000644000000000000000000001330013063067173014173 0ustar /* * Copyright (c) 2013 SGI * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include #include #include "init.h" #include "io.h" static cmdinfo_t seek_cmd; static void seek_help(void) { printf(_( "\n" " returns the next hole and/or data offset at or after the requested offset\n" "\n" " Example:\n" " 'seek -d 512' - offset of data at or following offset 512\n" " 'seek -a -r 0' - offsets of all data and hole in entire file\n" "\n" " Returns the offset of the next data and/or hole. There is an implied hole\n" " at the end of file. If the specified offset is past end of file, or there\n" " is no data past the specified offset, EOF is returned.\n" " -a -- return the next data and hole starting at the specified offset.\n" " -d -- return the next data starting at the specified offset.\n" " -h -- return the next hole starting at the specified offset.\n" " -r -- return all remaining type(s) starting at the specified offset.\n" " -s -- also print the starting offset.\n" "\n")); } #ifndef HAVE_SEEK_DATA #define SEEK_DATA 3 /* seek to the next data */ #define SEEK_HOLE 4 /* seek to the next hole */ #endif /* values for flag variable */ #define SEEK_DFLAG (1 << 0) #define SEEK_HFLAG (1 << 1) #define SEEK_RFLAG (1 << 2) /* indexes into the seekinfo array */ #define DATA 0 #define HOLE 1 struct seekinfo { char *name; /* display item name */ int seektype; /* data or hole */ int mask; /* compared for print and looping */ } seekinfo[] = { {"DATA", SEEK_DATA, SEEK_DFLAG}, {"HOLE", SEEK_HOLE, SEEK_HFLAG} }; /* print item type and offset. catch special cases of eof and error */ void seek_output( int startflag, char *type, off64_t start, off64_t offset) { if (offset == -1) { if (errno == ENXIO) { if (startflag) printf("%s %lld EOF\n", type, (long long)start); else printf("%s EOF\n", type); } else { printf("ERR %lld ", (long long)start); fflush(stdout); /* so the printf preceded the perror */ perror(""); } } else { if (startflag) printf("%s %lld %lld\n", type, (long long)start, (long long)offset); else printf("%s %lld\n", type, (long long)offset); } } static int seek_f( int argc, char **argv) { off64_t offset, start; size_t fsblocksize, fssectsize; int c; int current; /* specify data or hole */ int flag; int startflag; flag = startflag = 0; init_cvtnum(&fsblocksize, &fssectsize); while ((c = getopt(argc, argv, "adhrs")) != EOF) { switch (c) { case 'a': flag |= (SEEK_HFLAG | SEEK_DFLAG); break; case 'd': flag |= SEEK_DFLAG; break; case 'h': flag |= SEEK_HFLAG; break; case 'r': flag |= SEEK_RFLAG; break; case 's': startflag = 1; break; default: return command_usage(&seek_cmd); } } if (!(flag & (SEEK_DFLAG | SEEK_HFLAG)) || optind != argc - 1) return command_usage(&seek_cmd); start = offset = cvtnum(fsblocksize, fssectsize, argv[optind]); if (offset < 0) return command_usage(&seek_cmd); /* * check to see if the offset is a data or hole entry and * decide if we want to display that type of entry. */ if (flag & SEEK_HFLAG) { offset = lseek(file->fd, start, SEEK_HOLE); if ((start == offset) || !(flag & SEEK_DFLAG)) { /* * this offset is a hole or are only displaying holes. * if this offset is for data and we are displaying * data, then we will fall through below to * initialize the data search. */ current = HOLE; goto found_hole; } } /* The offset is not a hole, or we are looking just for data */ current = DATA; offset = lseek(file->fd, start, SEEK_DATA); found_hole: /* * At this point we know which type and the offset of the starting * item. "current" alternates between data / hole entries in * assending order - this alternation is needed even if only one * type is to be displayed. * * An error or EOF will terminate the display, otherwise "flag" * determines if there are more items to be displayed. */ if (startflag) printf("Whence Start Result\n"); else printf("Whence Result\n"); for (c = 0; flag; c++) { if (offset == -1) { /* print error or eof if the only entry */ if (errno != ENXIO || c == 0 ) seek_output(startflag, seekinfo[current].name, start, offset); return 0; /* stop on error or EOF */ } if (flag & seekinfo[current].mask) seek_output(startflag, seekinfo[current].name, start, offset); /* * When displaying only a single data and/or hole item, mask * off the item as it is displayed. The loop will end when all * requested items have been displayed. */ if (!(flag & SEEK_RFLAG)) flag &= ~seekinfo[current].mask; current ^= 1; /* alternate between data and hole */ start = offset; offset = lseek(file->fd, start, seekinfo[current].seektype); } return 0; } void seek_init(void) { seek_cmd.name = "seek"; seek_cmd.cfunc = seek_f; seek_cmd.argmin = 2; seek_cmd.argmax = 5; seek_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; seek_cmd.args = _("-a | -d | -h [-r] off"); seek_cmd.oneline = _("locate the next data and/or hole"); seek_cmd.help = seek_help; add_command(&seek_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/sendfile.c0000644000000000000000000000767413063067173015056 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include #include "init.h" #include "io.h" static cmdinfo_t sendfile_cmd; static void sendfile_help(void) { printf(_( "\n" " transfer a range of bytes from the given offset between files\n" "\n" " Example:\n" " 'send -f 2 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Copies data between one file descriptor and another. Because this copying\n" " is done within the kernel, sendfile does not need to transfer data to and\n" " from user space.\n" " -f -- specifies an input file from which to source data to write\n" " -i -- specifies an input file name from which to source data to write.\n" " An offset and length in the source file can be optionally specified.\n" "\n")); } static int send_buffer( off64_t offset, size_t count, int fd, long long *total) { off64_t off = offset; ssize_t bytes, bytes_remaining = count; int ops = 0; *total = 0; while (count > 0) { bytes = sendfile(file->fd, fd, &off, bytes_remaining); if (bytes == 0) break; if (bytes < 0) { perror("sendfile"); return -1; } ops++; *total += bytes; if (bytes >= bytes_remaining) break; bytes_remaining -= bytes; } return ops; } static int sendfile_f( int argc, char **argv) { off64_t offset = 0; long long count, total; size_t blocksize, sectsize; struct timeval t1, t2; char *infile = NULL; int Cflag, qflag; int c, fd = -1; Cflag = qflag = 0; init_cvtnum(&blocksize, §size); while ((c = getopt(argc, argv, "Cf:i:q")) != EOF) { switch (c) { case 'C': Cflag = 1; break; case 'q': qflag = 1; break; case 'f': fd = atoi(argv[1]); if (fd < 0 || fd >= filecount) { printf(_("value %d is out of range (0-%d)\n"), fd, filecount-1); return 0; } break; case 'i': infile = optarg; break; default: return command_usage(&sendfile_cmd); } } if (infile && fd != -1) return command_usage(&sendfile_cmd); if (!infile) fd = filetable[fd].fd; else if ((fd = openfile(infile, NULL, IO_READONLY, 0)) < 0) return 0; if (optind == argc - 2) { offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); goto done; } optind++; count = cvtnum(blocksize, sectsize, argv[optind]); if (count < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); goto done; } } else { struct stat stat; if (fstat(fd, &stat) < 0) { perror("fstat"); goto done; } count = stat.st_size; } gettimeofday(&t1, NULL); c = send_buffer(offset, count, fd, &total); if (c < 0) goto done; if (qflag) goto done; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); report_io_times("sent", &t2, (long long)offset, count, total, c, Cflag); done: if (infile) close(fd); return 0; } void sendfile_init(void) { sendfile_cmd.name = "sendfile"; sendfile_cmd.altname = "send"; sendfile_cmd.cfunc = sendfile_f; sendfile_cmd.argmin = 2; sendfile_cmd.argmax = -1; sendfile_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; sendfile_cmd.args = _("-i infile | -f N [off len]"); sendfile_cmd.oneline = _("Transfer data directly between file descriptors"); sendfile_cmd.help = sendfile_help; add_command(&sendfile_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/shutdown.c0000644000000000000000000000307313063067173015125 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t shutdown_cmd; static int shutdown_f( int argc, char **argv) { int c, flag = XFS_FSOP_GOING_FLAGS_NOLOGFLUSH; while ((c = getopt(argc, argv, "fv")) != -1) { switch (c) { case 'f': flag = XFS_FSOP_GOING_FLAGS_LOGFLUSH; break; default: return command_usage(&shutdown_cmd); } } if ((xfsctl(file->name, file->fd, XFS_IOC_GOINGDOWN, &flag)) < 0) { perror("XFS_IOC_GOINGDOWN"); return 0; } return 0; } void shutdown_init(void) { shutdown_cmd.name = "shutdown"; shutdown_cmd.cfunc = shutdown_f; shutdown_cmd.argmin = 0; shutdown_cmd.argmax = 1; shutdown_cmd.flags = CMD_NOMAP_OK; shutdown_cmd.args = _("[-f]"); shutdown_cmd.oneline = _("shuts down the filesystem where the current file resides"); if (expert) add_command(&shutdown_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/sync.c0000644000000000000000000000307213063067173014225 0ustar /* * Copyright (c) 2014 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "command.h" #include "init.h" #include "io.h" static cmdinfo_t sync_cmd; static int sync_f( int argc, char **argv) { /* sync can't fail */ sync(); return 0; } #ifdef HAVE_SYNCFS static cmdinfo_t syncfs_cmd; static int syncfs_f( int argc, char **argv) { /* syncfs can't fail */ syncfs(file->fd); return 0; } #endif void sync_init(void) { sync_cmd.name = "sync"; sync_cmd.cfunc = sync_f; sync_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK; sync_cmd.oneline = _("calls sync(2) to flush all in-core filesystem state to disk"); add_command(&sync_cmd); #ifdef HAVE_SYNCFS syncfs_cmd.name = "syncfs"; syncfs_cmd.cfunc = syncfs_f; syncfs_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; syncfs_cmd.oneline = _("calls syncfs(2) to flush all in-core filesystem state to disk"); add_command(&syncfs_cmd); #endif } xfsprogs-4.9.0+nmu1ubuntu2/io/sync_file_range.c0000644000000000000000000000531113063067173016376 0ustar /* * Copyright (c) 2012 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t sync_range_cmd; static void sync_range_help(void) { printf(_( "\n" " Trigger specific writeback commands on a range of the current file\n" "\n" " With no options, the SYNC_FILE_RANGE_WRITE is implied.\n" " -a -- wait for IO to finish after writing (SYNC_FILE_RANGE_WAIT_AFTER).\n" " -b -- wait for IO to finish before writing (SYNC_FILE_RANGE_WAIT_BEFORE).\n" " -w -- write dirty data in range (SYNC_FILE_RANGE_WRITE).\n" "\n")); } static int sync_range_f( int argc, char **argv) { off64_t offset = 0, length = 0; int c, sync_mode = 0; size_t blocksize, sectsize; while ((c = getopt(argc, argv, "abw")) != EOF) { switch (c) { case 'a': sync_mode = SYNC_FILE_RANGE_WAIT_AFTER; break; case 'b': sync_mode = SYNC_FILE_RANGE_WAIT_BEFORE; break; case 'w': sync_mode = SYNC_FILE_RANGE_WRITE; break; default: return command_usage(&sync_range_cmd); } } /* default to just starting writeback on the range */ if (!sync_mode) sync_mode = SYNC_FILE_RANGE_WRITE; if (optind != argc - 2) return command_usage(&sync_range_cmd); init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[optind]); if (offset < 0) { printf(_("non-numeric offset argument -- %s\n"), argv[optind]); return 0; } optind++; length = cvtnum(blocksize, sectsize, argv[optind]); if (length < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } if (sync_file_range(file->fd, offset, length, sync_mode) < 0) { perror("sync_file_range"); return 0; } return 0; } void sync_range_init(void) { sync_range_cmd.name = "sync_range"; sync_range_cmd.cfunc = sync_range_f; sync_range_cmd.argmin = 2; sync_range_cmd.argmax = -1; sync_range_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; sync_range_cmd.args = _("[-abw] off len"); sync_range_cmd.oneline = _("Control writeback on a range of a file"); sync_range_cmd.help = sync_range_help; add_command(&sync_range_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/truncate.c0000644000000000000000000000305013063067173015072 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "io.h" static cmdinfo_t truncate_cmd; static int truncate_f( int argc, char **argv) { off64_t offset; size_t blocksize, sectsize; init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[1]); if (offset < 0) { printf(_("non-numeric truncate argument -- %s\n"), argv[1]); return 0; } if (ftruncate(file->fd, offset) < 0) { perror("ftruncate"); return 0; } return 0; } void truncate_init(void) { truncate_cmd.name = "truncate"; truncate_cmd.altname = "t"; truncate_cmd.cfunc = truncate_f; truncate_cmd.argmin = 1; truncate_cmd.argmax = 1; truncate_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; truncate_cmd.args = _("off"); truncate_cmd.oneline = _("truncates the current file at the given offset"); add_command(&truncate_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/io/xfs_bmap.sh0000755000000000000000000000117613063067173015246 0ustar #!/bin/sh -f # # Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. # OPTS="" VERSION=false USAGE="Usage: xfs_bmap [-adlpvV] [-n nx] file..." DIRNAME=`dirname $0` while getopts "adln:pvV" c do case $c in a) OPTS=$OPTS" -a";; d) OPTS=$OPTS" -d";; l) OPTS=$OPTS" -l";; n) OPTS=$OPTS" -n "$OPTARG;; p) OPTS=$OPTS" -p";; v) OPTS=$OPTS" -v";; V) VERSION=true;; \?) echo $USAGE 1>&2 exit 2 ;; esac done $VERSION && $DIRNAME/xfs_io -p xfs_bmap -V shift `expr $OPTIND - 1` while [ "$1" != "" ] do $DIRNAME/xfs_io -r -p xfs_bmap -c "bmap $OPTS" "$1" status=$? [ $status -ne 0 ] && exit $status shift done exit 0 xfsprogs-4.9.0+nmu1ubuntu2/io/xfs_freeze.sh0000644000000000000000000000137713063067173015607 0ustar #!/bin/sh -f # # Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. # OPTS="" USAGE="Usage: xfs_freeze [-V] [-f | -u] " DIRNAME=`dirname $0` VERSION=false FREEZE=false THAW=false while getopts "fuV" c do case $c in f) FREEZE=true;; u) THAW=true;; V) VERSION=true;; \?) echo $USAGE 1>&2 exit 2 ;; esac done if $VERSION ; then $DIRNAME/xfs_io -p xfs_freeze -V exit 0 fi shift `expr $OPTIND - 1` if [ "$1" = "" ]; then echo $USAGE 1>&2 exit 2 fi if $FREEZE ; then $DIRNAME/xfs_io -F -r -p xfs_freeze -x -c "freeze" "$1" status=$? [ $status -ne 0 ] && exit $status elif $THAW ; then $DIRNAME/xfs_io -F -r -p xfs_freeze -x -c "thaw" "$1" status=$? [ $status -ne 0 ] && exit $status else echo $USAGE 1>&2 exit 2 fi exit 0 xfsprogs-4.9.0+nmu1ubuntu2/io/xfs_mkfile.sh0000755000000000000000000000175713063067173015603 0ustar #!/bin/sh -f # # Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. # OPTS="" NOBYTES=false PREALLOC=false VERBOSE=false VERSION=false XFS_IO=`dirname $0`"/xfs_io -p xfs_mkfile" USAGE="Usage: xfs_mkfile [-npvV] size file..." while getopts "npvV" c do case $c in n) NOBYTES=true;; p) PREALLOC=true;; v) VERBOSE=true;; V) VERSION=true;; \?) echo $USAGE 1>&2 exit 2 ;; esac done $VERSION && $XFS_IO -V shift `expr $OPTIND - 1` [ "$1" != "" ] || exit 0 SIZE="$1" ERRORS=0 shift while [ "$1" != "" ] do if $VERBOSE ; then $PREALLOC && echo "$1 $SIZE bytes pre-allocated" $PREALLOC || echo "$1 $SIZE bytes" fi if $NOBYTES ; then $XFS_IO -ft -c "truncate $SIZE" -- "$1" elif $PREALLOC ; then $XFS_IO -ftd -c "resvsp 0 $SIZE" \ -c "pwrite -q -S0 -b256k 0 $SIZE" \ -c "truncate $SIZE" -- "$1" else $XFS_IO -ftd -c "pwrite -q -S0 -b256k 0 $SIZE" \ -c "truncate $SIZE" -- "$1" fi [ $? -eq 0 ] || ERRORS=`expr $ERRORS + 1` shift done exit $ERRORS xfsprogs-4.9.0+nmu1ubuntu2/libhandle/0000755000000000000000000000000013063067174014417 5ustar xfsprogs-4.9.0+nmu1ubuntu2/libhandle/Makefile0000644000000000000000000000100413063067170016046 0ustar # # Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTLIBRARY = libhandle.la LT_CURRENT = 1 LT_REVISION = 3 LT_AGE = 0 ifeq ($(PKG_PLATFORM),darwin) LTLDFLAGS += -Wl,libhandle.sym else LTLDFLAGS += -Wl,--version-script,libhandle.sym endif CFILES = handle.c jdm.c LSRCFILES = libhandle.sym default: ltdepend $(LTLIBRARY) include $(BUILDRULES) install: default $(INSTALL_LTLIB) install-dev: default $(INSTALL_LTLIB_DEV) -include .ltdep xfsprogs-4.9.0+nmu1ubuntu2/libhandle/handle.c0000644000000000000000000002245713063067170016024 0ustar /* * Copyright (c) 1995, 2001-2003, 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "platform_defs.h" #include "xfs.h" #include "handle.h" #include "parent.h" /* just pick a value we know is more than big enough */ #define MAXHANSIZ 64 /* * The actual content of a handle is supposed to be opaque here. * But, to do handle_to_fshandle, we need to know what it is. Sigh. * However we can get by with knowing only that the first 8 bytes of * a file handle are the file system ID, and that a file system handle * consists of only those 8 bytes. */ #define FSIDSIZE 8 typedef union { int fd; char *path; } comarg_t; static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*); static int handle_to_fsfd(void *, char **); static char *path_to_fspath(char *path); /* * Filesystem Handle -> Open File Descriptor Cache * * Maps filesystem handles to a corresponding open file descriptor for that * filesystem. We need this because we're doing handle operations via xfsctl * and we need to remember the open file descriptor for each filesystem. */ struct fdhash { int fsfd; char fsh[FSIDSIZE]; struct fdhash *fnxt; char fspath[MAXPATHLEN]; }; static struct fdhash *fdhash_head = NULL; int path_to_fshandle( char *path, /* input, path to convert */ void **fshanp, /* output, pointer to data */ size_t *fshlen) /* output, size of returned data */ { int result; int fd; comarg_t obj; struct fdhash *fdhp; char *tmppath; char *fspath; fspath = path_to_fspath(path); if (fspath == NULL) return -1; fd = open(fspath, O_RDONLY); if (fd < 0) return -1; obj.path = path; result = obj_to_handle(fspath, fd, XFS_IOC_PATH_TO_FSHANDLE, obj, fshanp, fshlen); if (result < 0) { close(fd); return result; } if (handle_to_fsfd(*fshanp, &tmppath) >= 0) { /* this filesystem is already in the cache */ close(fd); } else { /* new filesystem. add it to the cache */ fdhp = malloc(sizeof(struct fdhash)); if (fdhp == NULL) { free(*fshanp); close(fd); errno = ENOMEM; return -1; } fdhp->fsfd = fd; strncpy(fdhp->fspath, fspath, sizeof(fdhp->fspath)); memcpy(fdhp->fsh, *fshanp, FSIDSIZE); fdhp->fnxt = fdhash_head; fdhash_head = fdhp; } return result; } int path_to_handle( char *path, /* input, path to convert */ void **hanp, /* output, pointer to data */ size_t *hlen) /* output, size of returned data */ { int fd; int result; comarg_t obj; char *fspath; fspath = path_to_fspath(path); if (fspath == NULL) return -1; fd = open(fspath, O_RDONLY); if (fd < 0) return -1; obj.path = path; result = obj_to_handle(fspath, fd, XFS_IOC_PATH_TO_HANDLE, obj, hanp, hlen); close(fd); return result; } /* Given a path, return a suitable "fspath" for use in obtaining * an fd for xfsctl calls. For regular files and directories the * input path is sufficient. For other types the parent directory * is used to avoid issues with opening dangling symlinks and * potentially blocking in an open on a named pipe. Also * symlinks to files on other filesystems would be a problem, * since an fd would be obtained for the wrong fs. */ static char * path_to_fspath(char *path) { static char dirpath[MAXPATHLEN]; struct stat statbuf; if (lstat(path, &statbuf) != 0) return NULL; if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) return path; strncpy(dirpath, path, MAXPATHLEN); dirpath[MAXPATHLEN-1] = '\0'; return dirname(dirpath); } int fd_to_handle ( int fd, /* input, file descriptor */ void **hanp, /* output, pointer to data */ size_t *hlen) /* output, size of returned data */ { comarg_t obj; obj.fd = fd; return obj_to_handle(NULL, fd, XFS_IOC_FD_TO_HANDLE, obj, hanp, hlen); } int handle_to_fshandle( void *hanp, size_t hlen, void **fshanp, size_t *fshlen) { if (hlen < FSIDSIZE) { errno = EINVAL; return -1; } *fshanp = malloc(FSIDSIZE); if (*fshanp == NULL) { errno = ENOMEM; return -1; } *fshlen = FSIDSIZE; memcpy(*fshanp, hanp, FSIDSIZE); return 0; } static int handle_to_fsfd(void *hanp, char **path) { struct fdhash *fdhp; /* * Look in cache for matching fsid field in the handle * (which is at the start of the handle). * When found return the file descriptor and path that * we have in the cache. */ for (fdhp = fdhash_head; fdhp != NULL; fdhp = fdhp->fnxt) { if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0) { *path = fdhp->fspath; return fdhp->fsfd; } } errno = EBADF; return -1; } static int obj_to_handle( char *fspath, int fsfd, unsigned int opcode, comarg_t obj, void **hanp, size_t *hlen) { char hbuf [MAXHANSIZ]; int ret; __uint32_t handlen; xfs_fsop_handlereq_t hreq; if (opcode == XFS_IOC_FD_TO_HANDLE) { hreq.fd = obj.fd; hreq.path = NULL; } else { hreq.fd = 0; hreq.path = obj.path; } hreq.oflags = O_LARGEFILE; hreq.ihandle = NULL; hreq.ihandlen = 0; hreq.ohandle = hbuf; hreq.ohandlen = &handlen; ret = xfsctl(fspath, fsfd, opcode, &hreq); if (ret) return ret; *hanp = malloc(handlen); if (*hanp == NULL) { errno = ENOMEM; return -1; } memcpy(*hanp, hbuf, handlen); *hlen = handlen; return 0; } int open_by_fshandle( void *fshanp, size_t fshlen, int rw) { int fsfd; char *path; xfs_fsop_handlereq_t hreq; if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0) return -1; hreq.fd = 0; hreq.path = NULL; hreq.oflags = rw | O_LARGEFILE; hreq.ihandle = fshanp; hreq.ihandlen = fshlen; hreq.ohandle = NULL; hreq.ohandlen = NULL; return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq); } int open_by_handle( void *hanp, size_t hlen, int rw) { int fsfd; char *path; xfs_fsop_handlereq_t hreq; if ((fsfd = handle_to_fsfd(hanp, &path)) < 0) return -1; hreq.fd = 0; hreq.path = NULL; hreq.oflags = rw | O_LARGEFILE; hreq.ihandle = hanp; hreq.ihandlen = hlen; hreq.ohandle = NULL; hreq.ohandlen = NULL; return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq); } int readlink_by_handle( void *hanp, size_t hlen, void *buf, size_t bufsiz) { int fd; __u32 buflen = (__u32)bufsiz; char *path; xfs_fsop_handlereq_t hreq; if ((fd = handle_to_fsfd(hanp, &path)) < 0) return -1; hreq.fd = 0; hreq.path = NULL; hreq.oflags = O_LARGEFILE; hreq.ihandle = hanp; hreq.ihandlen = hlen; hreq.ohandle = buf; hreq.ohandlen = &buflen; return xfsctl(path, fd, XFS_IOC_READLINK_BY_HANDLE, &hreq); } /*ARGSUSED4*/ int attr_multi_by_handle( void *hanp, size_t hlen, void *buf, int rtrvcnt, int flags) { int fd; char *path; xfs_fsop_attrmulti_handlereq_t amhreq; if ((fd = handle_to_fsfd(hanp, &path)) < 0) return -1; amhreq.hreq.fd = 0; amhreq.hreq.path = NULL; amhreq.hreq.oflags = O_LARGEFILE; amhreq.hreq.ihandle = hanp; amhreq.hreq.ihandlen = hlen; amhreq.hreq.ohandle = NULL; amhreq.hreq.ohandlen = NULL; amhreq.opcount = rtrvcnt; amhreq.ops = buf; return xfsctl(path, fd, XFS_IOC_ATTRMULTI_BY_HANDLE, &amhreq); } int attr_list_by_handle( void *hanp, size_t hlen, void *buf, size_t bufsize, int flags, struct attrlist_cursor *cursor) { int error, fd; char *path; xfs_fsop_attrlist_handlereq_t alhreq; if ((fd = handle_to_fsfd(hanp, &path)) < 0) return -1; alhreq.hreq.fd = 0; alhreq.hreq.path = NULL; alhreq.hreq.oflags = O_LARGEFILE; alhreq.hreq.ihandle = hanp; alhreq.hreq.ihandlen = hlen; alhreq.hreq.ohandle = NULL; alhreq.hreq.ohandlen = NULL; memcpy(&alhreq.pos, cursor, sizeof(alhreq.pos)); alhreq.flags = flags; alhreq.buffer = buf; alhreq.buflen = bufsize; /* prevent needless EINVAL from the kernel */ if (alhreq.buflen > XFS_XATTR_LIST_MAX) alhreq.buflen = XFS_XATTR_LIST_MAX; error = xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq); memcpy(cursor, &alhreq.pos, sizeof(alhreq.pos)); return error; } int parents_by_handle( void *hanp, size_t hlen, parent_t *buf, size_t bufsiz, unsigned int *count) { errno = EOPNOTSUPP; return -1; } int parentpaths_by_handle( void *hanp, size_t hlen, parent_t *buf, size_t bufsiz, unsigned int *count) { errno = EOPNOTSUPP; return -1; } int fssetdm_by_handle( void *hanp, size_t hlen, struct fsdmidata *fsdmidata) { int fd; char *path; xfs_fsop_setdm_handlereq_t dmhreq; if ((fd = handle_to_fsfd(hanp, &path)) < 0) return -1; dmhreq.hreq.fd = 0; dmhreq.hreq.path = NULL; dmhreq.hreq.oflags = O_LARGEFILE; dmhreq.hreq.ihandle = hanp; dmhreq.hreq.ihandlen = hlen; dmhreq.hreq.ohandle = NULL; dmhreq.hreq.ohandlen = NULL; dmhreq.data = fsdmidata; return xfsctl(path, fd, XFS_IOC_FSSETDM_BY_HANDLE, &dmhreq); } /*ARGSUSED1*/ void free_handle( void *hanp, size_t hlen) { free(hanp); } xfsprogs-4.9.0+nmu1ubuntu2/libhandle/jdm.c0000644000000000000000000001161213063067170015332 0ustar /* * Copyright (c) 1995, 2001-2002, 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "xfs.h" #include "handle.h" #include "jdm.h" #include "parent.h" /* internal fshandle - typecast to a void for external use */ #define FSHANDLE_SZ 8 typedef struct fshandle { char fsh_space[FSHANDLE_SZ]; } fshandle_t; /* private file handle - for use by open_by_fshandle */ #define FILEHANDLE_SZ 24 #define FILEHANDLE_SZ_FOLLOWING 14 #define FILEHANDLE_SZ_PAD 2 typedef struct filehandle { fshandle_t fh_fshandle; /* handle of fs containing this inode */ int16_t fh_sz_following; /* bytes in handle after this member */ char fh_pad[FILEHANDLE_SZ_PAD]; /* padding, must be zeroed */ __uint32_t fh_gen; /* generation count */ xfs_ino_t fh_ino; /* 64 bit ino */ } filehandle_t; static void jdm_fill_filehandle( filehandle_t *handlep, fshandle_t *fshandlep, xfs_bstat_t *statp ) { handlep->fh_fshandle = *fshandlep; handlep->fh_sz_following = FILEHANDLE_SZ_FOLLOWING; memset(handlep->fh_pad, 0, FILEHANDLE_SZ_PAD); handlep->fh_gen = statp->bs_gen; handlep->fh_ino = statp->bs_ino; } jdm_fshandle_t * jdm_getfshandle( char *mntpnt ) { fshandle_t *fshandlep; size_t fshandlesz; char resolved[MAXPATHLEN]; /* sanity checks */ ASSERT( sizeof( fshandle_t ) == FSHANDLE_SZ ); ASSERT( sizeof( filehandle_t ) == FILEHANDLE_SZ ); ASSERT( sizeof( filehandle_t ) - offsetofmember( filehandle_t, fh_pad ) == FILEHANDLE_SZ_FOLLOWING ); ASSERT( sizeofmember( filehandle_t, fh_pad ) == FILEHANDLE_SZ_PAD ); ASSERT( FILEHANDLE_SZ_PAD == sizeof( int16_t )); fshandlep = NULL; /* for lint */ fshandlesz = sizeof( *fshandlep ); if (!realpath( mntpnt, resolved )) return NULL; if (path_to_fshandle( resolved, ( void ** )&fshandlep, &fshandlesz )) return NULL; assert( fshandlesz == sizeof( *fshandlep )); return ( jdm_fshandle_t * )fshandlep; } /* externally visible functions */ void jdm_new_filehandle( jdm_filehandle_t **handlep, size_t *hlen, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp) { /* allocate and fill filehandle */ *hlen = sizeof(filehandle_t); *handlep = (filehandle_t *) malloc(*hlen); if (*handlep) jdm_fill_filehandle(*handlep, (fshandle_t *) fshandlep, statp); } /* ARGSUSED */ void jdm_delete_filehandle( jdm_filehandle_t *handlep, size_t hlen ) { free(handlep); } intgen_t jdm_open( jdm_fshandle_t *fshp, xfs_bstat_t *statp, intgen_t oflags ) { fshandle_t *fshandlep = ( fshandle_t * )fshp; filehandle_t filehandle; intgen_t fd; jdm_fill_filehandle( &filehandle, fshandlep, statp ); fd = open_by_fshandle( ( void * )&filehandle, sizeof( filehandle ), oflags ); return fd; } intgen_t jdm_readlink( jdm_fshandle_t *fshp, xfs_bstat_t *statp, char *bufp, size_t bufsz ) { fshandle_t *fshandlep = ( fshandle_t * )fshp; filehandle_t filehandle; intgen_t rval; jdm_fill_filehandle( &filehandle, fshandlep, statp ); rval = readlink_by_handle( ( void * )&filehandle, sizeof( filehandle ), ( void * )bufp, bufsz ); return rval; } int jdm_attr_multi( jdm_fshandle_t *fshp, xfs_bstat_t *statp, char *bufp, int rtrvcnt, int flags) { fshandle_t *fshandlep = ( fshandle_t * )fshp; filehandle_t filehandle; int rval; jdm_fill_filehandle( &filehandle, fshandlep, statp ); rval = attr_multi_by_handle ( ( void * )&filehandle, sizeof( filehandle ), (void *) bufp, rtrvcnt, flags); return rval; } int jdm_attr_list( jdm_fshandle_t *fshp, xfs_bstat_t *statp, char *bufp, size_t bufsz, int flags, struct attrlist_cursor *cursor) { fshandle_t *fshandlep = ( fshandle_t * )fshp; filehandle_t filehandle; int rval; /* prevent needless EINVAL from the kernel */ if (bufsz > XFS_XATTR_LIST_MAX) bufsz = XFS_XATTR_LIST_MAX; jdm_fill_filehandle( &filehandle, fshandlep, statp ); rval = attr_list_by_handle (( void * )&filehandle, sizeof( filehandle ), bufp, bufsz, flags, cursor); return rval; } int jdm_parents( jdm_fshandle_t *fshp, xfs_bstat_t *statp, parent_t *bufp, size_t bufsz, unsigned int *count) { errno = EOPNOTSUPP; return -1; } int jdm_parentpaths( jdm_fshandle_t *fshp, xfs_bstat_t *statp, parent_t *bufp, size_t bufsz, unsigned int *count) { errno = EOPNOTSUPP; return -1; } xfsprogs-4.9.0+nmu1ubuntu2/libhandle/libhandle.sym0000644000000000000000000000147313063067170017074 0ustar /* * The symbol versioning ensures that a new application requiring symbol foo() * can't run with old libhandle.so not providing foo() - the global SONAME * version info can't enforce this since we never change the SONAME. * * Older versions of libhandle (<= 1.0.3) do not to use symbol versioning -- * all the original symbols are in LIBHANDLE_1.0.3 now. */ LIBHANDLE_1.0.3 { global: /* handle.h APIs */ path_to_handle; path_to_fshandle; handle_to_fshandle; free_handle; open_by_fshandle; open_by_handle; readlink_by_handle; attr_multi_by_handle; attr_list_by_handle; parents_by_handle; parentpaths_by_handle; fssetdm_by_handle; /* jdm.h APIs */ jdm_getfshandle; jdm_new_filehandle; jdm_delete_filehandle; jdm_open; jdm_readlink; jdm_attr_multi; jdm_attr_list; jdm_parents; jdm_parentpaths; }; xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/0000755000000000000000000000000013063067174014117 5ustar xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/Makefile0000644000000000000000000000127313063067167015564 0ustar # # Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTLIBRARY = libxcmd.la LT_CURRENT = 0 LT_REVISION = 0 LT_AGE = 0 CFILES = command.c input.c paths.c projects.c help.c quit.c topology.c ifeq ($(HAVE_GETMNTENT),yes) LCFLAGS += -DHAVE_GETMNTENT endif ifeq ($(HAVE_GETMNTINFO),yes) LCFLAGS += -DHAVE_GETMNTINFO endif ifeq ($(ENABLE_READLINE),yes) LCFLAGS += -DENABLE_READLINE LTLIBS += $(LIBREADLINE) $(LIBTERMCAP) endif ifeq ($(ENABLE_EDITLINE),yes) LCFLAGS += -DENABLE_EDITLINE LTLIBS += $(LIBEDITLINE) $(LIBTERMCAP) endif default: ltdepend $(LTLIBRARY) include $(BUILDRULES) install install-dev: default -include .ltdep xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/command.c0000644000000000000000000001071113063067167015703 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "command.h" #include "input.h" cmdinfo_t *cmdtab; int ncmds; static argsfunc_t args_func; static checkfunc_t check_func; static int ncmdline; static char **cmdline; static int compare(const void *a, const void *b) { return strcmp(((const cmdinfo_t *)a)->name, ((const cmdinfo_t *)b)->name); } void add_command( const cmdinfo_t *ci) { cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab)); cmdtab[ncmds - 1] = *ci; qsort(cmdtab, ncmds, sizeof(*cmdtab), compare); } static int check_command( const cmdinfo_t *ci) { if (check_func) return check_func(ci); return 1; } void add_check_command( checkfunc_t cf) { check_func = cf; } int command_usage( const cmdinfo_t *ci) { printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline); return 0; } int command( const cmdinfo_t *ct, int argc, char **argv) { char *cmd = argv[0]; if (!check_command(ct)) return 0; if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) { if (ct->argmax == -1) fprintf(stderr, _("bad argument count %d to %s, expected at least %d arguments\n"), argc-1, cmd, ct->argmin); else if (ct->argmin == ct->argmax) fprintf(stderr, _("bad argument count %d to %s, expected %d arguments\n"), argc-1, cmd, ct->argmin); else fprintf(stderr, _("bad argument count %d to %s, expected between %d and %d arguments\n"), argc-1, cmd, ct->argmin, ct->argmax); return 0; } platform_getoptreset(); return ct->cfunc(argc, argv); } const cmdinfo_t * find_command( const char *cmd) { cmdinfo_t *ct; for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { if (strcmp(ct->name, cmd) == 0 || (ct->altname && strcmp(ct->altname, cmd) == 0)) return (const cmdinfo_t *)ct; } return NULL; } void add_user_command(char *optarg) { ncmdline++; cmdline = realloc(cmdline, sizeof(char*) * (ncmdline)); if (!cmdline) { perror("realloc"); exit(1); } cmdline[ncmdline-1] = optarg; } static int args_command( int index) { if (args_func) return args_func(index); return 0; } void add_args_command( argsfunc_t af) { args_func = af; } void command_loop(void) { int c, i, j = 0, done = 0; char *input; char **v; const cmdinfo_t *ct; for (i = 0; !done && i < ncmdline; i++) { input = strdup(cmdline[i]); if (!input) { fprintf(stderr, _("cannot strdup command '%s': %s\n"), cmdline[i], strerror(errno)); exit(1); } v = breakline(input, &c); if (c) { ct = find_command(v[0]); if (ct) { if (ct->flags & CMD_FLAG_GLOBAL) done = command(ct, c, v); else { j = 0; while (!done && (j = args_command(j))) done = command(ct, c, v); } } else fprintf(stderr, _("command \"%s\" not found\n"), v[0]); } doneline(input, v); } if (cmdline) { free(cmdline); return; } while (!done) { if ((input = fetchline()) == NULL) break; v = breakline(input, &c); if (c) { ct = find_command(v[0]); if (ct) done = command(ct, c, v); else fprintf(stderr, _("command \"%s\" not found\n"), v[0]); } doneline(input, v); } } void report_io_times( const char *verb, struct timeval *t2, long long offset, long long count, long long total, int ops, int compact) { char s1[64], s2[64], ts[64]; timestr(t2, ts, sizeof(ts), compact ? VERBOSE_FIXED_TIME : 0); if (!compact) { cvtstr((double)total, s1, sizeof(s1)); cvtstr(tdiv((double)total, *t2), s2, sizeof(s2)); printf(_("%s %lld/%lld bytes at offset %lld\n"), verb, total, count, (long long)offset); printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"), s1, ops, ts, s2, tdiv((double)ops, *t2)); } else {/* bytes,ops,time,bytes/sec,ops/sec */ printf("%lld,%d,%s,%.3f,%.3f\n", total, ops, ts, tdiv((double)total, *t2), tdiv((double)ops, *t2)); } } xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/help.c0000644000000000000000000000411213063067167015213 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "command.h" #include "../quota/init.h" static cmdinfo_t help_cmd; static void help_onecmd(const char *cmd, const cmdinfo_t *ct); static void help_oneline(const char *cmd, const cmdinfo_t *ct); static void help_all(void) { const cmdinfo_t *ct; for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) help_oneline(ct->name, ct); printf(_("\nUse 'help commandname' for extended help.\n")); } static int help_f( int argc, char **argv) { const cmdinfo_t *ct; if (argc == 1) { help_all(); return 0; } ct = find_command(argv[1]); if (ct == NULL) { printf(_("command %s not found\n"), argv[1]); return 0; } help_onecmd(argv[1], ct); return 0; } static void help_onecmd( const char *cmd, const cmdinfo_t *ct) { help_oneline(cmd, ct); if (ct->help) ct->help(); } static void help_oneline( const char *cmd, const cmdinfo_t *ct) { if (cmd) printf("%s ", cmd); else { printf("%s ", ct->name); if (ct->altname) printf("(or %s) ", ct->altname); } if (ct->args) printf("%s ", ct->args); printf("-- %s\n", ct->oneline); } void help_init(void) { help_cmd.name = "help"; help_cmd.altname = "?"; help_cmd.cfunc = help_f; help_cmd.argmin = 0; help_cmd.argmax = 1; help_cmd.flags = CMD_FLAG_GLOBAL | CMD_ALL_FSTYPES; help_cmd.args = _("[command]"); help_cmd.oneline = _("help for one or all commands"); add_command(&help_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/input.c0000644000000000000000000002137413063067167015433 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "input.h" #include #include #if defined(ENABLE_READLINE) # include # include #elif defined(ENABLE_EDITLINE) # include #endif extern char *progname; static char * get_prompt(void) { static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; if (!prompt[0]) snprintf(prompt, sizeof(prompt), "%s> ", progname); return prompt; } #if defined(ENABLE_READLINE) char * fetchline(void) { char *line; line = readline(get_prompt()); if (line && *line) add_history(line); return line; } #elif defined(ENABLE_EDITLINE) static char *el_get_prompt(EditLine *e) { return get_prompt(); } char * fetchline(void) { static EditLine *el; static History *hist; HistEvent hevent; char *line; int count; if (!el) { hist = history_init(); history(hist, &hevent, H_SETSIZE, 100); el = el_init(progname, stdin, stdout, stderr); el_source(el, NULL); el_set(el, EL_SIGNAL, 1); el_set(el, EL_PROMPT, el_get_prompt); el_set(el, EL_HIST, history, (const char *)hist); } line = strdup(el_gets(el, &count)); if (line) { if (count > 0) line[count-1] = '\0'; if (*line) history(hist, &hevent, H_ENTER, line); } return line; } #else # define MAXREADLINESZ 1024 char * fetchline(void) { char *p, *line = malloc(MAXREADLINESZ); if (!line) return NULL; printf("%s", get_prompt()); fflush(stdout); if (!fgets(line, MAXREADLINESZ, stdin)) { free(line); return NULL; } p = line + strlen(line); if (p != line && p[-1] == '\n') p[-1] = '\0'; return line; } #endif char ** breakline( char *input, int *count) { int c = 0; char *p; char **rval = calloc(sizeof(char *), 1); while (rval && (p = strsep(&input, " ")) != NULL) { if (!*p) continue; c++; rval = realloc(rval, sizeof(*rval) * (c + 1)); if (!rval) { c = 0; break; } rval[c - 1] = p; rval[c] = NULL; } *count = c; return rval; } void doneline( char *input, char **vec) { free(input); free(vec); } #define EXABYTES(x) ((long long)(x) << 60) #define PETABYTES(x) ((long long)(x) << 50) #define TERABYTES(x) ((long long)(x) << 40) #define GIGABYTES(x) ((long long)(x) << 30) #define MEGABYTES(x) ((long long)(x) << 20) #define KILOBYTES(x) ((long long)(x) << 10) long long cvtnum( size_t blocksize, size_t sectorsize, char *s) { long long i; char *sp; int c; i = strtoll(s, &sp, 0); if (i == 0 && sp == s) return -1LL; if (*sp == '\0') return i; if (sp[1] != '\0') return -1LL; c = tolower(*sp); switch (c) { case 'b': return i * blocksize; case 's': return i * sectorsize; case 'k': return KILOBYTES(i); case 'm': return MEGABYTES(i); case 'g': return GIGABYTES(i); case 't': return TERABYTES(i); case 'p': return PETABYTES(i); case 'e': return EXABYTES(i); } return -1LL; } #define TO_EXABYTES(x) ((x) / EXABYTES(1)) #define TO_PETABYTES(x) ((x) / PETABYTES(1)) #define TO_TERABYTES(x) ((x) / TERABYTES(1)) #define TO_GIGABYTES(x) ((x) / GIGABYTES(1)) #define TO_MEGABYTES(x) ((x) / MEGABYTES(1)) #define TO_KILOBYTES(x) ((x) / KILOBYTES(1)) void cvtstr( double value, char *str, size_t size) { char *fmt; int precise; precise = ((double)value * 1000 == (double)(int)value * 1000); if (value >= EXABYTES(1)) { fmt = precise ? "%.f EiB" : "%.3f EiB"; snprintf(str, size, fmt, TO_EXABYTES(value)); } else if (value >= PETABYTES(1)) { fmt = precise ? "%.f PiB" : "%.3f PiB"; snprintf(str, size, fmt, TO_PETABYTES(value)); } else if (value >= TERABYTES(1)) { fmt = precise ? "%.f TiB" : "%.3f TiB"; snprintf(str, size, fmt, TO_TERABYTES(value)); } else if (value >= GIGABYTES(1)) { fmt = precise ? "%.f GiB" : "%.3f GiB"; snprintf(str, size, fmt, TO_GIGABYTES(value)); } else if (value >= MEGABYTES(1)) { fmt = precise ? "%.f MiB" : "%.3f MiB"; snprintf(str, size, fmt, TO_MEGABYTES(value)); } else if (value >= KILOBYTES(1)) { fmt = precise ? "%.f KiB" : "%.3f KiB"; snprintf(str, size, fmt, TO_KILOBYTES(value)); } else { snprintf(str, size, "%f bytes", value); } } #define MINUTES_TO_SECONDS(m) ((m) * 60) #define HOURS_TO_SECONDS(h) ((h) * MINUTES_TO_SECONDS(60)) #define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24)) #define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7)) unsigned long cvttime( char *s) { unsigned long i; char *sp; i = strtoul(s, &sp, 0); if (i == 0 && sp == s) return 0; if (*sp == '\0') return i; if ((*sp == 'm' && sp[1] == '\0') || (strcmp(sp, "minutes") == 0) || (strcmp(sp, "minute") == 0)) return MINUTES_TO_SECONDS(i); if ((*sp == 'h' && sp[1] == '\0') || (strcmp(sp, "hours") == 0) || (strcmp(sp, "hour") == 0)) return HOURS_TO_SECONDS(i); if ((*sp == 'd' && sp[1] == '\0') || (strcmp(sp, "days") == 0) || (strcmp(sp, "day") == 0)) return DAYS_TO_SECONDS(i); if ((*sp == 'w' && sp[1] == '\0') || (strcmp(sp, "weeks") == 0) || (strcmp(sp, "week") == 0)) return WEEKS_TO_SECONDS(i); return 0; } struct timeval tadd(struct timeval t1, struct timeval t2) { t1.tv_usec += t2.tv_usec; if (t1.tv_usec > 1000000) { t1.tv_usec -= 1000000; t1.tv_sec++; } t1.tv_sec += t2.tv_sec; return t1; } struct timeval tsub(struct timeval t1, struct timeval t2) { t1.tv_usec -= t2.tv_usec; if (t1.tv_usec < 0) { t1.tv_usec += 1000000; t1.tv_sec--; } t1.tv_sec -= t2.tv_sec; return t1; } double tdiv(double value, struct timeval tv) { return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0)); } #define HOURS(sec) ((sec) / (60 * 60)) #define MINUTES(sec) (((sec) % (60 * 60)) / 60) #define SECONDS(sec) ((sec) % 60) void timestr( struct timeval *tv, char *ts, size_t size, int format) { double usec = (double)tv->tv_usec / 1000000.0; if (format & TERSE_FIXED_TIME) { if (!HOURS(tv->tv_sec)) { snprintf(ts, size, "%u:%02u.%02u", (unsigned int) MINUTES(tv->tv_sec), (unsigned int) SECONDS(tv->tv_sec), (unsigned int) usec * 100); return; } format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */ } if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) { snprintf(ts, size, "%u:%02u:%02u.%02u", (unsigned int) HOURS(tv->tv_sec), (unsigned int) MINUTES(tv->tv_sec), (unsigned int) SECONDS(tv->tv_sec), (unsigned int) usec * 100); } else { snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000); } } /* * Convert from arbitrary user strings into a numeric ID. * If it's all numeric, we convert that inplace, else we do * the name lookup, and return the found identifier. */ prid_t prid_from_string( char *project) { fs_project_t *prj; unsigned long prid_long; char *sp; /* * Allow either a full numeric or a valid projectname, even * if it starts with a digit. */ prid_long = strtoul(project, &sp, 10); if (*project != '\0' && *sp == '\0') { if ((prid_long == ULONG_MAX && errno == ERANGE) || (prid_long > (prid_t)-1)) return -1; return (prid_t)prid_long; } prj = getprnam(project); if (prj) return prj->pr_prid; return -1; } uid_t uid_from_string( char *user) { struct passwd *pwd; unsigned long uid_long; char *sp; uid_long = strtoul(user, &sp, 10); if (sp != user && *sp == '\0') { if ((uid_long == ULONG_MAX && errno == ERANGE) || (uid_long > (uid_t)-1)) return -1; return (uid_t)uid_long; } pwd = getpwnam(user); if (pwd) return pwd->pw_uid; return -1; } gid_t gid_from_string( char *group) { struct group *grp; unsigned long gid_long; char *sp; gid_long = strtoul(group, &sp, 10); if (sp != group && *sp == '\0') { if ((gid_long == ULONG_MAX && errno == ERANGE) || (gid_long > (gid_t)-1)) return -1; return (gid_t)gid_long; } grp = getgrnam(group); if (grp) return grp->gr_gid; return -1; } bool isdigits_only( const char *str) { int i; for (i = 0; i < strlen(str); i++) { if (!isdigit(str[i])) return false; } return true; } #define HAVE_FTW_H 1 /* TODO: configure me */ #ifndef HAVE_FTW_H int nftw( char *dir, int (*fn)(const char *, const struct stat *, int, struct FTW *), int depth, int flags) { fprintf(stderr, "%s: not implemented, no recursion available\n", __FUNCTION__); return 0; } #endif xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/paths.c0000644000000000000000000003055313063067167015412 0ustar /* * Copyright (c) 2005-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "path.h" #include "input.h" #include "project.h" #include extern char *progname; int fs_count; int xfs_fs_count; struct fs_path *fs_table; struct fs_path *fs_path; char *mtab_file; #define PROC_MOUNTS "/proc/self/mounts" static int fs_device_number( const char *name, dev_t *devnum) { struct stat sbuf; if (stat(name, &sbuf) < 0) return errno; /* * We want to match st_rdev if the path provided is a device * special file. Otherwise we are looking for the the * device id for the containing filesystem, in st_dev. */ if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode)) *devnum = sbuf.st_rdev; else *devnum = sbuf.st_dev; return 0; } /* * Find the FS table entry for the given path. The "flags" argument * is a mask containing FS_MOUNT_POINT or FS_PROJECT_PATH (or both) * to indicate the type of table entry sought. */ struct fs_path * fs_table_lookup( const char *dir, uint flags) { uint i; dev_t dev = 0; if (fs_device_number(dir, &dev)) return NULL; for (i = 0; i < fs_count; i++) { if (flags && !(flags & fs_table[i].fs_flags)) continue; if (fs_table[i].fs_datadev == dev) return &fs_table[i]; } return NULL; } static int fs_table_insert( char *dir, uint prid, uint flags, char *fsname, char *fslog, char *fsrt) { dev_t datadev, logdev, rtdev; struct fs_path *tmp_fs_table; int error; datadev = logdev = rtdev = 0; error = fs_device_number(dir, &datadev); if (error) goto out_nodev; if (fslog) { error = fs_device_number(fslog, &logdev); if (error) goto out_nodev; } if (fsrt) { error = fs_device_number(fsrt, &rtdev); if (error) goto out_nodev; } if (!platform_test_xfs_path(dir)) flags |= FS_FOREIGN; /* * Make copies of the directory and data device path. * The log device and real-time device, if non-null, * are already the result of strdup() calls so we * don't need to duplicate those. In fact, this * function is assumed to "consume" both of those * pointers, meaning if an error occurs they will * both get freed. */ error = ENOMEM; dir = strdup(dir); if (!dir) goto out_nodev; fsname = strdup(fsname); if (!fsname) goto out_noname; tmp_fs_table = realloc(fs_table, sizeof(fs_path_t) * (fs_count + 1)); if (!tmp_fs_table) goto out_norealloc; fs_table = tmp_fs_table; /* Put foreign filesystems at the end, xfs filesystems at the front */ if (flags & FS_FOREIGN || fs_count == 0) { fs_path = &fs_table[fs_count]; } else { /* move foreign fs entries down, insert new one just before */ memmove(&fs_table[xfs_fs_count + 1], &fs_table[xfs_fs_count], sizeof(fs_path_t)*(fs_count - xfs_fs_count)); fs_path = &fs_table[xfs_fs_count]; } fs_path->fs_dir = dir; fs_path->fs_prid = prid; fs_path->fs_flags = flags; fs_path->fs_name = fsname; fs_path->fs_log = fslog; fs_path->fs_rt = fsrt; fs_path->fs_datadev = datadev; fs_path->fs_logdev = logdev; fs_path->fs_rtdev = rtdev; fs_count++; if (!(flags & FS_FOREIGN)) xfs_fs_count++; return 0; out_norealloc: free(fsname); out_noname: free(dir); out_nodev: /* "Consume" fslog and fsrt even if there's an error */ free(fslog); free(fsrt); return error; } /* * Table iteration (cursor-based) interfaces */ /* * Initialize an fs_table cursor. If a directory path is supplied, * the cursor is set up to appear as though the table contains only * a single entry which represents the directory specified. * Otherwise it is set up to prepare for visiting all entries in the * global table, starting with the first. "flags" can be either * FS_MOUNT_POINT or FS_PROJECT_PATH to limit what type of entries * will be selected by fs_cursor_next_entry(). 0 can be used as a * wild card (selecting either type). */ void fs_cursor_initialise( char *dir, uint flags, fs_cursor_t *cur) { fs_path_t *path; memset(cur, 0, sizeof(*cur)); if (dir) { if ((path = fs_table_lookup(dir, flags)) == NULL) return; cur->local = *path; cur->count = 1; cur->table = &cur->local; } else { cur->count = fs_count; cur->table = fs_table; } cur->flags = flags; } /* * Use the cursor to find the next entry in the table having the * type specified by the cursor's "flags" field. */ struct fs_path * fs_cursor_next_entry( fs_cursor_t *cur) { while (cur->index < cur->count) { fs_path_t *next = &cur->table[cur->index++]; if (!cur->flags || (cur->flags & next->fs_flags)) return next; } return NULL; } #if defined(HAVE_GETMNTENT) #include /* * Determines whether the "logdev" or "rtdev" mount options are * present for the given mount point. If so, the value for each (a * device path) is returned in the pointers whose addresses are * provided. The pointers are assigned NULL for an option not * present. Note that the path buffers returned are allocated * dynamically and it is the caller's responsibility to free them. */ static int fs_extract_mount_options( struct mntent *mnt, char **logp, char **rtp) { char *fslog, *fsrt; /* * Extract log device and realtime device from mount options. * * Note: the glibc hasmntopt implementation requires that the * character in mnt_opts immediately after the search string * must be a NULL ('\0'), a comma (','), or an equals ('='). * Therefore we cannot search for 'logdev=' directly. */ if ((fslog = hasmntopt(mnt, "logdev")) && fslog[6] == '=') fslog += 7; if ((fsrt = hasmntopt(mnt, "rtdev")) && fsrt[5] == '=') fsrt += 6; /* Do this only after we've finished processing mount options */ if (fslog) { fslog = strndup(fslog, strcspn(fslog, " ,")); if (!fslog) goto out_nomem; } if (fsrt) { fsrt = strndup(fsrt, strcspn(fsrt, " ,")); if (!fsrt) { free(fslog); goto out_nomem; } } *logp = fslog; *rtp = fsrt; return 0; out_nomem: *logp = NULL; *rtp = NULL; fprintf(stderr, _("%s: unable to extract mount options for \"%s\"\n"), progname, mnt->mnt_dir); return ENOMEM; } /* * If *path is NULL, initialize the fs table with all xfs mount points in mtab * If *path is specified, search for that path in mtab * * Everything - path, devices, and mountpoints - are boiled down to realpath() * for comparison, but fs_table is populated with what comes from getmntent. */ static int fs_table_initialise_mounts( char *path) { struct mntent *mnt; FILE *mtp; char *fslog, *fsrt; int error, found; char rpath[PATH_MAX], rmnt_fsname[PATH_MAX], rmnt_dir[PATH_MAX]; error = found = 0; fslog = fsrt = NULL; if (!mtab_file) { mtab_file = PROC_MOUNTS; if (access(mtab_file, R_OK) != 0) mtab_file = MOUNTED; } if ((mtp = setmntent(mtab_file, "r")) == NULL) return ENOENT; /* Use realpath to resolve symlinks, relative paths, etc */ if (path) if (!realpath(path, rpath)) return errno; while ((mnt = getmntent(mtp)) != NULL) { if (!realpath(mnt->mnt_dir, rmnt_dir)) continue; if (!realpath(mnt->mnt_fsname, rmnt_fsname)) continue; if (path && ((strcmp(rpath, rmnt_dir) != 0) && (strcmp(rpath, rmnt_fsname) != 0))) continue; if (fs_extract_mount_options(mnt, &fslog, &fsrt)) continue; (void) fs_table_insert(mnt->mnt_dir, 0, FS_MOUNT_POINT, mnt->mnt_fsname, fslog, fsrt); if (path) { found = 1; break; } } endmntent(mtp); if (path && !found) error = ENXIO; return error; } #elif defined(HAVE_GETMNTINFO) #include /* * If *path is NULL, initialize the fs table with all xfs mount points in mtab * If *path is specified, search for that path in mtab * * Everything - path, devices, and mountpoints - are boiled down to realpath() * for comparison, but fs_table is populated with what comes from getmntinfo. */ static int fs_table_initialise_mounts( char *path) { struct statfs *stats; int i, count, error, found; char rpath[PATH_MAX], rmntfromname[PATH_MAX], rmntonname[PATH_MAX]; error = found = 0; if ((count = getmntinfo(&stats, 0)) < 0) { fprintf(stderr, _("%s: getmntinfo() failed: %s\n"), progname, strerror(errno)); return 0; } /* Use realpath to resolve symlinks, relative paths, etc */ if (path) if (!realpath(path, rpath)) return errno; for (i = 0; i < count; i++) { if (!realpath(stats[i].f_mntfromname, rmntfromname)) continue; if (!realpath(stats[i].f_mntonname, rmntonname)) continue; if (path && ((strcmp(rpath, rmntonname) != 0) && (strcmp(rpath, rmntfromname) != 0))) continue; /* TODO: external log and realtime device? */ (void) fs_table_insert(stats[i].f_mntonname, 0, FS_MOUNT_POINT, stats[i].f_mntfromname, NULL, NULL); if (path) { found = 1; break; } } if (path && !found) error = ENXIO; return error; } #else # error "How do I extract info about mounted filesystems on this platform?" #endif /* * Given a directory, match it up to a filesystem mount point. */ static struct fs_path * fs_mount_point_from_path( const char *dir) { fs_cursor_t cursor; fs_path_t *fs; dev_t dev = 0; if (fs_device_number(dir, &dev)) return NULL; fs_cursor_initialise(NULL, FS_MOUNT_POINT, &cursor); while ((fs = fs_cursor_next_entry(&cursor))) { if (fs->fs_datadev == dev) break; } return fs; } static void fs_table_insert_mount( char *mount) { int error; error = fs_table_initialise_mounts(mount); if (error) fprintf(stderr, _("%s: cannot setup path for mount %s: %s\n"), progname, mount, strerror(error)); } static int fs_table_initialise_projects( char *project) { fs_project_path_t *path; fs_path_t *fs; prid_t prid = 0; int error = 0, found = 0; if (project) prid = prid_from_string(project); setprpathent(); while ((path = getprpathent()) != NULL) { if (project && prid != path->pp_prid) continue; fs = fs_mount_point_from_path(path->pp_pathname); if (!fs) { fprintf(stderr, _("%s: cannot find mount point for path `%s': %s\n"), progname, path->pp_pathname, strerror(errno)); continue; } (void) fs_table_insert(path->pp_pathname, path->pp_prid, FS_PROJECT_PATH, fs->fs_name, NULL, NULL); if (project) { found = 1; break; } } endprpathent(); if (project && !found) error = ENOENT; return error; } static void fs_table_insert_project( char *project) { int error; error = fs_table_initialise_projects(project); if (error) fprintf(stderr, _("%s: cannot setup path for project %s: %s\n"), progname, project, strerror(error)); } /* * Initialize fs_table to contain the given set of mount points and * projects. If mount_count is zero, mounts is ignored and the * table is populated with mounted filesystems. If project_count is * zero, projects is ignored and the table is populated with all * projects defined in the projects file. */ void fs_table_initialise( int mount_count, char *mounts[], int project_count, char *projects[]) { int error; int i; if (mount_count) { for (i = 0; i < mount_count; i++) fs_table_insert_mount(mounts[i]); } else { error = fs_table_initialise_mounts(NULL); if (error) goto out_error; } if (project_count) { for (i = 0; i < project_count; i++) fs_table_insert_project(projects[i]); } else { error = fs_table_initialise_projects(NULL); if (error) goto out_error; } return; out_error: fprintf(stderr, _("%s: cannot initialise path table: %s\n"), progname, strerror(error)); } void fs_table_insert_project_path( char *dir, prid_t prid) { fs_path_t *fs; int error = 0; fs = fs_mount_point_from_path(dir); if (fs) error = fs_table_insert(dir, prid, FS_PROJECT_PATH, fs->fs_name, NULL, NULL); else error = ENOENT; if (error) { fprintf(stderr, _("%s: cannot setup path for project dir %s: %s\n"), progname, dir, strerror(error)); exit(1); } } xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/projects.c0000644000000000000000000000723013063067167016120 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "project.h" #define PROJID "/etc/projid" #define PROJECT_PATHS "/etc/projects" char *projid_file; char *projects_file; static FILE *projects; static fs_project_t p; static char projects_buffer[512]; static FILE *project_paths; static fs_project_path_t pp; static char project_paths_buffer[1024]; void setprfiles(void) { if (!projid_file) projid_file = PROJID; if (!projects_file) projects_file = PROJECT_PATHS; } void setprent(void) { setprfiles(); projects = fopen(projid_file, "r"); } void setprpathent(void) { setprfiles(); project_paths = fopen(projects_file, "r"); } void endprent(void) { if (projects) fclose(projects); projects = NULL; } void endprpathent(void) { if (project_paths) fclose(project_paths); project_paths = NULL; } fs_project_t * getprent(void) { char *idstart, *idend; size_t size = sizeof(projects_buffer) - 1; if (!projects) return NULL; for (;;) { if (!fgets(projects_buffer, size, projects)) break; /* * /etc/projid file format -- "name:id\n", ignore "^#..." */ if (projects_buffer[0] == '#') continue; idstart = strchr(projects_buffer, ':'); if (!idstart) continue; if ((idstart + 1) - projects_buffer >= size) continue; idend = strchr(idstart+1, ':'); if (idend) *idend = '\0'; *idstart = '\0'; p.pr_prid = atoi(idstart+1); p.pr_name = &projects_buffer[0]; return &p; } return NULL; } fs_project_t * getprnam( char *name) { fs_project_t *p = NULL; setprent(); while ((p = getprent()) != NULL) if (strcmp(p->pr_name, name) == 0) break; endprent(); return p; } fs_project_t * getprprid( prid_t prid) { fs_project_t *p = NULL; setprent(); while ((p = getprent()) != NULL) if (p->pr_prid == prid) break; endprent(); return p; } fs_project_path_t * getprpathent(void) { char *nmstart, *nmend; size_t size = sizeof(project_paths_buffer) - 1; if (!project_paths) return NULL; for (;;) { if (!fgets(project_paths_buffer, size, project_paths)) break; /* * /etc/projects format -- "id:pathname\n", ignore "^#..." */ if (project_paths_buffer[0] == '#') continue; nmstart = strchr(project_paths_buffer, ':'); if (!nmstart) continue; if ((nmstart + 1) - project_paths_buffer >= size) continue; nmend = strchr(nmstart + 1, '\n'); if (nmend) *nmend = '\0'; *nmstart = '\0'; pp.pp_pathname = nmstart + 1; pp.pp_prid = atoi(&project_paths_buffer[0]); return &pp; } return NULL; } int getprojid( const char *name, int fd, prid_t *projid) { struct fsxattr fsx; if (xfsctl(name, fd, FS_IOC_FSGETXATTR, &fsx)) { perror("FS_IOC_FSGETXATTR"); return -1; } *projid = fsx.fsx_projid; return 0; } int setprojid( const char *name, int fd, prid_t projid) { struct fsxattr fsx; int error; if ((error = xfsctl(name, fd, FS_IOC_FSGETXATTR, &fsx)) == 0) { fsx.fsx_projid = projid; error = xfsctl(name, fd, FS_IOC_FSSETXATTR, &fsx); } return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/quit.c0000644000000000000000000000222313063067167015246 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "platform_defs.h" #include "command.h" #include "../quota/init.h" static cmdinfo_t quit_cmd; /* ARGSUSED */ static int quit_f( int argc, char **argv) { return 1; } void quit_init(void) { quit_cmd.name = "quit"; quit_cmd.altname = "q"; quit_cmd.cfunc = quit_f; quit_cmd.argmin = -1; quit_cmd.argmax = -1; quit_cmd.flags = CMD_FLAG_GLOBAL | CMD_ALL_FSTYPES; quit_cmd.oneline = _("exit the program"); add_command(&quit_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/libxcmd/topology.c0000644000000000000000000002056713033541503016137 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxcmd.h" #ifdef ENABLE_BLKID # include #endif /* ENABLE_BLKID */ #include "xfs_multidisk.h" #define TERABYTES(count, blog) ((__uint64_t)(count) << (40 - (blog))) #define GIGABYTES(count, blog) ((__uint64_t)(count) << (30 - (blog))) #define MEGABYTES(count, blog) ((__uint64_t)(count) << (20 - (blog))) void calc_default_ag_geometry( int blocklog, __uint64_t dblocks, int multidisk, __uint64_t *agsize, __uint64_t *agcount) { __uint64_t blocks = 0; int shift = 0; /* * First handle the high extreme - the point at which we will * always use the maximum AG size. * * This applies regardless of storage configuration. */ if (dblocks >= TERABYTES(32, blocklog)) { blocks = XFS_AG_MAX_BLOCKS(blocklog); goto done; } /* * For a single underlying storage device over 4TB in size * use the maximum AG size. Between 128MB and 4TB, just use * 4 AGs and scale up smoothly between min/max AG sizes. */ if (!multidisk) { if (dblocks >= TERABYTES(4, blocklog)) { blocks = XFS_AG_MAX_BLOCKS(blocklog); goto done; } else if (dblocks >= MEGABYTES(128, blocklog)) { shift = XFS_NOMULTIDISK_AGLOG; goto calc_blocks; } } /* * For the multidisk configs we choose an AG count based on the number * of data blocks available, trying to keep the number of AGs higher * than the single disk configurations. This makes the assumption that * larger filesystems have more parallelism available to them. */ shift = XFS_MULTIDISK_AGLOG; if (dblocks <= GIGABYTES(512, blocklog)) shift--; if (dblocks <= GIGABYTES(8, blocklog)) shift--; if (dblocks < MEGABYTES(128, blocklog)) shift--; if (dblocks < MEGABYTES(64, blocklog)) shift--; if (dblocks < MEGABYTES(32, blocklog)) shift--; /* * If dblocks is not evenly divisible by the number of * desired AGs, round "blocks" up so we don't lose the * last bit of the filesystem. The same principle applies * to the AG count, so we don't lose the last AG! */ calc_blocks: ASSERT(shift >= 0 && shift <= XFS_MULTIDISK_AGLOG); blocks = dblocks >> shift; if (dblocks & xfs_mask32lo(shift)) { if (blocks < XFS_AG_MAX_BLOCKS(blocklog)) blocks++; } done: *agsize = blocks; *agcount = dblocks / blocks + (dblocks % blocks != 0); } /* * Check for existing filesystem or partition table on device. * Returns: * 1 for existing fs or partition * 0 for nothing found * -1 for internal error */ #ifdef ENABLE_BLKID int check_overwrite( const char *device) { const char *type; blkid_probe pr = NULL; int ret; int fd; long long size; int bsz; if (!device || !*device) return 0; ret = -1; /* will reset on success of all setup calls */ fd = open(device, O_RDONLY); if (fd < 0) goto out; platform_findsizes((char *)device, fd, &size, &bsz); close(fd); /* nothing to overwrite on a 0-length device */ if (size == 0) { ret = 0; goto out; } pr = blkid_new_probe_from_filename(device); if (!pr) goto out; ret = blkid_probe_enable_partitions(pr, 1); if (ret < 0) goto out; ret = blkid_do_fullprobe(pr); if (ret < 0) goto out; /* * Blkid returns 1 for nothing found and 0 when it finds a signature, * but we want the exact opposite, so reverse the return value here. * * In addition print some useful diagnostics about what actually is * on the device. */ if (ret) { ret = 0; goto out; } if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) { fprintf(stderr, _("%s: %s appears to contain an existing " "filesystem (%s).\n"), progname, device, type); } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) { fprintf(stderr, _("%s: %s appears to contain a partition " "table (%s).\n"), progname, device, type); } else { fprintf(stderr, _("%s: %s appears to contain something weird " "according to blkid\n"), progname, device); } ret = 1; out: if (pr) blkid_free_probe(pr); if (ret == -1) fprintf(stderr, _("%s: probe of %s failed, cannot detect " "existing filesystem.\n"), progname, device); return ret; } static void blkid_get_topology( const char *device, int *sunit, int *swidth, int *lsectorsize, int *psectorsize, int force_overwrite) { blkid_topology tp; blkid_probe pr; unsigned long val; struct stat statbuf; /* can't get topology info from a file */ if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) { fprintf(stderr, _("%s: Warning: trying to probe topology of a file %s!\n"), progname, device); return; } pr = blkid_new_probe_from_filename(device); if (!pr) return; tp = blkid_probe_get_topology(pr); if (!tp) goto out_free_probe; val = blkid_topology_get_logical_sector_size(tp); *lsectorsize = val; val = blkid_topology_get_physical_sector_size(tp); *psectorsize = val; val = blkid_topology_get_minimum_io_size(tp); *sunit = val; val = blkid_topology_get_optimal_io_size(tp); *swidth = val; /* * If the reported values are the same as the physical sector size * do not bother to report anything. It will only cause warnings * if people specify larger stripe units or widths manually. */ if (*sunit == *psectorsize || *swidth == *psectorsize) { *sunit = 0; *swidth = 0; } /* * Blkid reports the information in terms of bytes, but we want it in * terms of 512 bytes blocks (only to convert it to bytes later..) */ *sunit = *sunit >> 9; *swidth = *swidth >> 9; if (blkid_topology_get_alignment_offset(tp) != 0) { fprintf(stderr, _("warning: device is not properly aligned %s\n"), device); if (!force_overwrite) { fprintf(stderr, _("Use -f to force usage of a misaligned device\n")); exit(EXIT_FAILURE); } /* Do not use physical sector size if the device is misaligned */ *psectorsize = *lsectorsize; } blkid_free_probe(pr); return; out_free_probe: blkid_free_probe(pr); fprintf(stderr, _("warning: unable to probe device topology for device %s\n"), device); } #else /* ifdef ENABLE_BLKID */ /* * Without blkid, we can't do a good check for signatures. * So instead of some messy attempts, just disable any checks * and always return 'nothing found'. */ # warning BLKID is disabled, so signature detection and block device\ access are not working! int check_overwrite( const char *device) { return 1; } static void blkid_get_topology( const char *device, int *sunit, int *swidth, int *lsectorsize, int *psectorsize, int force_overwrite) { /* * Shouldn't make any difference (no blkid = no block device access), * but make sure this dummy replacement returns with at least some * sanity. */ *lsectorsize = *psectorsize = 512; } #endif /* ENABLE_BLKID */ void get_topology( libxfs_init_t *xi, struct fs_topology *ft, int force_overwrite) { struct stat statbuf; char *dfile = xi->volname ? xi->volname : xi->dname; /* * If our target is a regular file, use platform_findsizes * to try to obtain the underlying filesystem's requirements * for direct IO; we'll set our sector size to that if possible. */ if (xi->disfile || (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) { int fd; int flags = O_RDONLY; long long dummy; /* with xi->disfile we may not have the file yet! */ if (xi->disfile) flags |= O_CREAT; fd = open(dfile, flags, 0666); if (fd >= 0) { platform_findsizes(dfile, fd, &dummy, &ft->lsectorsize); close(fd); ft->psectorsize = ft->lsectorsize; } else ft->psectorsize = ft->lsectorsize = BBSIZE; } else { blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth, &ft->lsectorsize, &ft->psectorsize, force_overwrite); } if (xi->rtname && !xi->risfile) { int sunit, lsectorsize, psectorsize; blkid_get_topology(xi->rtname, &sunit, &ft->rtswidth, &lsectorsize, &psectorsize, force_overwrite); } } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/0000755000000000000000000000000013063067174013764 5ustar xfsprogs-4.9.0+nmu1ubuntu2/libxfs/Makefile0000644000000000000000000000706513063067170015430 0ustar # # Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTLIBRARY = libxfs.la LT_CURRENT = 0 LT_REVISION = 0 LT_AGE = 0 # headers to install in include/xfs PKGHFILES = xfs_fs.h \ xfs_types.h \ xfs_da_format.h \ xfs_format.h \ xfs_log_format.h HFILES = \ xfs_ag_resv.h \ xfs_alloc.h \ xfs_alloc_btree.h \ xfs_attr_leaf.h \ xfs_attr_sf.h \ xfs_bit.h \ xfs_bmap.h \ xfs_bmap_btree.h \ xfs_btree.h \ xfs_attr_remote.h \ xfs_cksum.h \ xfs_da_btree.h \ xfs_dir2.h \ xfs_ialloc.h \ xfs_ialloc_btree.h \ xfs_inode_buf.h \ xfs_inode_fork.h \ xfs_quota_defs.h \ xfs_refcount.h \ xfs_refcount_btree.h \ xfs_rmap.h \ xfs_rmap_btree.h \ xfs_sb.h \ xfs_shared.h \ xfs_trans_resv.h \ xfs_trans_space.h \ libxfs_io.h \ libxfs_api_defs.h \ init.h \ crc32defs.h \ crc32table.h \ libxfs_priv.h \ xfs_dir2_priv.h CFILES = cache.c \ crc32.c \ defer_item.c \ init.c \ kmem.c \ list_sort.c \ logitem.c \ radix-tree.c \ rdwr.c \ trans.c \ util.c \ xfs_ag_resv.c \ xfs_alloc.c \ xfs_alloc_btree.c \ xfs_attr.c \ xfs_attr_leaf.c \ xfs_attr_remote.c \ xfs_bit.c \ xfs_bmap.c \ xfs_bmap_btree.c \ xfs_btree.c \ xfs_da_btree.c \ xfs_da_format.c \ xfs_defer.c \ xfs_dir2.c \ xfs_dir2_block.c \ xfs_dir2_data.c \ xfs_dir2_leaf.c \ xfs_dir2_node.c \ xfs_dir2_sf.c \ xfs_dquot_buf.c \ xfs_ialloc.c \ xfs_inode_buf.c \ xfs_inode_fork.c \ xfs_ialloc_btree.c \ xfs_log_rlimit.c \ xfs_refcount.c \ xfs_refcount_btree.c \ xfs_rmap.c \ xfs_rmap_btree.c \ xfs_rtbitmap.c \ xfs_sb.c \ xfs_symlink_remote.c \ xfs_trans_resv.c CFILES += $(PKG_PLATFORM).c PCFILES = darwin.c freebsd.c irix.c linux.c LSRCFILES = $(shell echo $(PCFILES) | sed -e "s/$(PKG_PLATFORM).c//g") LSRCFILES += gen_crc32table.c # # Tracing flags: # -DIO_DEBUG reads and writes of buffers # -DMEM_DEBUG all zone memory use # -DLI_DEBUG log item (ino/buf) manipulation # -DXACT_DEBUG transaction state changes # #LCFLAGS += FCFLAGS = -I. LTLIBS = $(LIBPTHREAD) $(LIBRT) # don't try linking xfs_repair with a debug libxfs. DEBUG = -DNDEBUG LDIRT = gen_crc32table crc32table.h crc32selftest default: crc32selftest ltdepend $(LTLIBRARY) crc32table.h: gen_crc32table.c @echo " [CC] gen_crc32table" $(Q) $(BUILD_CC) $(CFLAGS) -o gen_crc32table $< @echo " [GENERATE] $@" $(Q) ./gen_crc32table > crc32table.h # The selftest binary will return an error if it fails. This is made a # dependency of the build process so that we refuse to build the tools on broken # systems/architectures. Hence we make sure that xfsprogs will never use a # busted CRC calculation at build time and hence avoid putting bad CRCs down on # disk. crc32selftest: gen_crc32table.c crc32table.h crc32.c @echo " [TEST] CRC32" $(Q) $(BUILD_CC) $(CFLAGS) -D CRC32_SELFTEST=1 crc32.c -o $@ $(Q) ./$@ # set up include/xfs header directory include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_INC_DIR) install-headers: $(addsuffix -hdrs, $(PKGHFILES)) %-hdrs: $(Q)$(LN_S) -f $(CURDIR)/$* $(TOPDIR)/include/xfs/$* install-dev: install $(INSTALL) -m 644 $(PKGHFILES) $(PKG_INC_DIR) # We need to install the headers before building the dependencies. If we # include the .ltdep file, the makefile decides that it needs to build the # dependencies to remake the makefile before running the header install target, # hence making it impossible to avoid errors being thrown by the dependency # generation. Hence we play games so that we only include this file if we aren't # running the install-headers target. ifndef NODEP -include .ltdep endif xfsprogs-4.9.0+nmu1ubuntu2/libxfs/cache.c0000644000000000000000000004305313063067171015175 0ustar /* * Copyright (c) 2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_bit.h" #define CACHE_DEBUG 1 #undef CACHE_DEBUG #define CACHE_DEBUG 1 #undef CACHE_ABORT /* #define CACHE_ABORT 1 */ #define CACHE_SHAKE_COUNT 64 static unsigned int cache_generic_bulkrelse(struct cache *, struct list_head *); struct cache * cache_init( int flags, unsigned int hashsize, struct cache_operations *cache_operations) { struct cache * cache; unsigned int i, maxcount; maxcount = hashsize * HASH_CACHE_RATIO; if (!(cache = malloc(sizeof(struct cache)))) return NULL; if (!(cache->c_hash = calloc(hashsize, sizeof(struct cache_hash)))) { free(cache); return NULL; } cache->c_flags = flags; cache->c_count = 0; cache->c_max = 0; cache->c_hits = 0; cache->c_misses = 0; cache->c_maxcount = maxcount; cache->c_hashsize = hashsize; cache->c_hashshift = libxfs_highbit32(hashsize); cache->hash = cache_operations->hash; cache->alloc = cache_operations->alloc; cache->flush = cache_operations->flush; cache->relse = cache_operations->relse; cache->compare = cache_operations->compare; cache->bulkrelse = cache_operations->bulkrelse ? cache_operations->bulkrelse : cache_generic_bulkrelse; pthread_mutex_init(&cache->c_mutex, NULL); for (i = 0; i < hashsize; i++) { list_head_init(&cache->c_hash[i].ch_list); cache->c_hash[i].ch_count = 0; pthread_mutex_init(&cache->c_hash[i].ch_mutex, NULL); } for (i = 0; i <= CACHE_DIRTY_PRIORITY; i++) { list_head_init(&cache->c_mrus[i].cm_list); cache->c_mrus[i].cm_count = 0; pthread_mutex_init(&cache->c_mrus[i].cm_mutex, NULL); } return cache; } void cache_expand( struct cache * cache) { pthread_mutex_lock(&cache->c_mutex); #ifdef CACHE_DEBUG fprintf(stderr, "doubling cache size to %d\n", 2 * cache->c_maxcount); #endif cache->c_maxcount *= 2; pthread_mutex_unlock(&cache->c_mutex); } void cache_walk( struct cache * cache, cache_walk_t visit) { struct cache_hash * hash; struct list_head * head; struct list_head * pos; unsigned int i; for (i = 0; i < cache->c_hashsize; i++) { hash = &cache->c_hash[i]; head = &hash->ch_list; pthread_mutex_lock(&hash->ch_mutex); for (pos = head->next; pos != head; pos = pos->next) visit((struct cache_node *)pos); pthread_mutex_unlock(&hash->ch_mutex); } } #ifdef CACHE_ABORT #define cache_abort() abort() #else #define cache_abort() do { } while (0) #endif #ifdef CACHE_DEBUG static void cache_zero_check( struct cache_node * node) { if (node->cn_count > 0) { fprintf(stderr, "%s: refcount is %u, not zero (node=%p)\n", __FUNCTION__, node->cn_count, node); cache_abort(); } } #define cache_destroy_check(c) cache_walk((c), cache_zero_check) #else #define cache_destroy_check(c) do { } while (0) #endif void cache_destroy( struct cache * cache) { unsigned int i; cache_destroy_check(cache); for (i = 0; i < cache->c_hashsize; i++) { list_head_destroy(&cache->c_hash[i].ch_list); pthread_mutex_destroy(&cache->c_hash[i].ch_mutex); } for (i = 0; i <= CACHE_DIRTY_PRIORITY; i++) { list_head_destroy(&cache->c_mrus[i].cm_list); pthread_mutex_destroy(&cache->c_mrus[i].cm_mutex); } pthread_mutex_destroy(&cache->c_mutex); free(cache->c_hash); free(cache); } static unsigned int cache_generic_bulkrelse( struct cache * cache, struct list_head * list) { struct cache_node * node; unsigned int count = 0; while (!list_empty(list)) { node = list_entry(list->next, struct cache_node, cn_mru); pthread_mutex_destroy(&node->cn_mutex); list_del_init(&node->cn_mru); cache->relse(node); count++; } return count; } /* * Park unflushable nodes on their own special MRU so that cache_shake() doesn't * end up repeatedly scanning them in the futile attempt to clean them before * reclaim. */ static void cache_add_to_dirty_mru( struct cache *cache, struct cache_node *node) { struct cache_mru *mru = &cache->c_mrus[CACHE_DIRTY_PRIORITY]; pthread_mutex_lock(&mru->cm_mutex); node->cn_old_priority = node->cn_priority; node->cn_priority = CACHE_DIRTY_PRIORITY; list_add(&node->cn_mru, &mru->cm_list); mru->cm_count++; pthread_mutex_unlock(&mru->cm_mutex); } /* * We've hit the limit on cache size, so we need to start reclaiming nodes we've * used. The MRU specified by the priority is shaken. Returns new priority at * end of the call (in case we call again). We are not allowed to reclaim dirty * objects, so we have to flush them first. If flushing fails, we move them to * the "dirty, unreclaimable" list. * * Hence we skip priorities > CACHE_MAX_PRIORITY unless "purge" is set as we * park unflushable (and hence unreclaimable) buffers at these priorities. * Trying to shake unreclaimable buffer lists when there is memory pressure is a * waste of time and CPU and greatly slows down cache node recycling operations. * Hence we only try to free them if we are being asked to purge the cache of * all entries. */ static unsigned int cache_shake( struct cache * cache, unsigned int priority, bool purge) { struct cache_mru *mru; struct cache_hash * hash; struct list_head temp; struct list_head * head; struct list_head * pos; struct list_head * n; struct cache_node * node; unsigned int count; ASSERT(priority <= CACHE_DIRTY_PRIORITY); if (priority > CACHE_MAX_PRIORITY && !purge) priority = 0; mru = &cache->c_mrus[priority]; count = 0; list_head_init(&temp); head = &mru->cm_list; pthread_mutex_lock(&mru->cm_mutex); for (pos = head->prev, n = pos->prev; pos != head; pos = n, n = pos->prev) { node = list_entry(pos, struct cache_node, cn_mru); if (pthread_mutex_trylock(&node->cn_mutex) != 0) continue; /* memory pressure is not allowed to release dirty objects */ if (cache->flush(node) && !purge) { list_del(&node->cn_mru); mru->cm_count--; node->cn_priority = -1; pthread_mutex_unlock(&node->cn_mutex); cache_add_to_dirty_mru(cache, node); continue; } hash = cache->c_hash + node->cn_hashidx; if (pthread_mutex_trylock(&hash->ch_mutex) != 0) { pthread_mutex_unlock(&node->cn_mutex); continue; } ASSERT(node->cn_count == 0); ASSERT(node->cn_priority == priority); node->cn_priority = -1; list_move(&node->cn_mru, &temp); list_del_init(&node->cn_hash); hash->ch_count--; mru->cm_count--; pthread_mutex_unlock(&hash->ch_mutex); pthread_mutex_unlock(&node->cn_mutex); count++; if (!purge && count == CACHE_SHAKE_COUNT) break; } pthread_mutex_unlock(&mru->cm_mutex); if (count > 0) { cache->bulkrelse(cache, &temp); pthread_mutex_lock(&cache->c_mutex); cache->c_count -= count; pthread_mutex_unlock(&cache->c_mutex); } return (count == CACHE_SHAKE_COUNT) ? priority : ++priority; } /* * Allocate a new hash node (updating atomic counter in the process), * unless doing so will push us over the maximum cache size. */ static struct cache_node * cache_node_allocate( struct cache * cache, cache_key_t key) { unsigned int nodesfree; struct cache_node * node; pthread_mutex_lock(&cache->c_mutex); nodesfree = (cache->c_count < cache->c_maxcount); if (nodesfree) { cache->c_count++; if (cache->c_count > cache->c_max) cache->c_max = cache->c_count; } cache->c_misses++; pthread_mutex_unlock(&cache->c_mutex); if (!nodesfree) return NULL; node = cache->alloc(key); if (node == NULL) { /* uh-oh */ pthread_mutex_lock(&cache->c_mutex); cache->c_count--; pthread_mutex_unlock(&cache->c_mutex); return NULL; } pthread_mutex_init(&node->cn_mutex, NULL); list_head_init(&node->cn_mru); node->cn_count = 1; node->cn_priority = 0; node->cn_old_priority = -1; return node; } int cache_overflowed( struct cache * cache) { return cache->c_maxcount == cache->c_max; } static int __cache_node_purge( struct cache * cache, struct cache_node * node) { int count; struct cache_mru * mru; pthread_mutex_lock(&node->cn_mutex); count = node->cn_count; if (count != 0) { pthread_mutex_unlock(&node->cn_mutex); return count; } /* can't purge dirty objects */ if (cache->flush(node)) { pthread_mutex_unlock(&node->cn_mutex); return 1; } mru = &cache->c_mrus[node->cn_priority]; pthread_mutex_lock(&mru->cm_mutex); list_del_init(&node->cn_mru); mru->cm_count--; pthread_mutex_unlock(&mru->cm_mutex); pthread_mutex_unlock(&node->cn_mutex); pthread_mutex_destroy(&node->cn_mutex); list_del_init(&node->cn_hash); cache->relse(node); return 0; } /* * Lookup in the cache hash table. With any luck we'll get a cache * hit, in which case this will all be over quickly and painlessly. * Otherwise, we allocate a new node, taking care not to expand the * cache beyond the requested maximum size (shrink it if it would). * Returns one if hit in cache, otherwise zero. A node is _always_ * returned, however. */ int cache_node_get( struct cache * cache, cache_key_t key, struct cache_node ** nodep) { struct cache_node * node = NULL; struct cache_hash * hash; struct cache_mru * mru; struct list_head * head; struct list_head * pos; struct list_head * n; unsigned int hashidx; int priority = 0; int purged = 0; hashidx = cache->hash(key, cache->c_hashsize, cache->c_hashshift); hash = cache->c_hash + hashidx; head = &hash->ch_list; for (;;) { pthread_mutex_lock(&hash->ch_mutex); for (pos = head->next, n = pos->next; pos != head; pos = n, n = pos->next) { int result; node = list_entry(pos, struct cache_node, cn_hash); result = cache->compare(node, key); switch (result) { case CACHE_HIT: break; case CACHE_PURGE: if ((cache->c_flags & CACHE_MISCOMPARE_PURGE) && !__cache_node_purge(cache, node)) { purged++; hash->ch_count--; } /* FALL THROUGH */ case CACHE_MISS: goto next_object; } /* * node found, bump node's reference count, remove it * from its MRU list, and update stats. */ pthread_mutex_lock(&node->cn_mutex); if (node->cn_count == 0) { ASSERT(node->cn_priority >= 0); ASSERT(!list_empty(&node->cn_mru)); mru = &cache->c_mrus[node->cn_priority]; pthread_mutex_lock(&mru->cm_mutex); mru->cm_count--; list_del_init(&node->cn_mru); pthread_mutex_unlock(&mru->cm_mutex); if (node->cn_old_priority != -1) { ASSERT(node->cn_priority == CACHE_DIRTY_PRIORITY); node->cn_priority = node->cn_old_priority; node->cn_old_priority = -1; } } node->cn_count++; pthread_mutex_unlock(&node->cn_mutex); pthread_mutex_unlock(&hash->ch_mutex); pthread_mutex_lock(&cache->c_mutex); cache->c_hits++; pthread_mutex_unlock(&cache->c_mutex); *nodep = node; return 0; next_object: continue; /* what the hell, gcc? */ } pthread_mutex_unlock(&hash->ch_mutex); /* * not found, allocate a new entry */ node = cache_node_allocate(cache, key); if (node) break; priority = cache_shake(cache, priority, false); /* * We start at 0; if we free CACHE_SHAKE_COUNT we get * back the same priority, if not we get back priority+1. * If we exceed CACHE_MAX_PRIORITY all slots are full; grow it. */ if (priority > CACHE_MAX_PRIORITY) { priority = 0; cache_expand(cache); } } node->cn_hashidx = hashidx; /* add new node to appropriate hash */ pthread_mutex_lock(&hash->ch_mutex); hash->ch_count++; list_add(&node->cn_hash, &hash->ch_list); pthread_mutex_unlock(&hash->ch_mutex); if (purged) { pthread_mutex_lock(&cache->c_mutex); cache->c_count -= purged; pthread_mutex_unlock(&cache->c_mutex); } *nodep = node; return 1; } void cache_node_put( struct cache * cache, struct cache_node * node) { struct cache_mru * mru; pthread_mutex_lock(&node->cn_mutex); #ifdef CACHE_DEBUG if (node->cn_count < 1) { fprintf(stderr, "%s: node put on refcount %u (node=%p)\n", __FUNCTION__, node->cn_count, node); cache_abort(); } if (!list_empty(&node->cn_mru)) { fprintf(stderr, "%s: node put on node (%p) in MRU list\n", __FUNCTION__, node); cache_abort(); } #endif node->cn_count--; if (node->cn_count == 0) { /* add unreferenced node to appropriate MRU for shaker */ mru = &cache->c_mrus[node->cn_priority]; pthread_mutex_lock(&mru->cm_mutex); mru->cm_count++; list_add(&node->cn_mru, &mru->cm_list); pthread_mutex_unlock(&mru->cm_mutex); } pthread_mutex_unlock(&node->cn_mutex); } void cache_node_set_priority( struct cache * cache, struct cache_node * node, int priority) { if (priority < 0) priority = 0; else if (priority > CACHE_MAX_PRIORITY) priority = CACHE_MAX_PRIORITY; pthread_mutex_lock(&node->cn_mutex); ASSERT(node->cn_count > 0); node->cn_priority = priority; node->cn_old_priority = -1; pthread_mutex_unlock(&node->cn_mutex); } int cache_node_get_priority( struct cache_node * node) { int priority; pthread_mutex_lock(&node->cn_mutex); priority = node->cn_priority; pthread_mutex_unlock(&node->cn_mutex); return priority; } /* * Purge a specific node from the cache. Reference count must be zero. */ int cache_node_purge( struct cache * cache, cache_key_t key, struct cache_node * node) { struct list_head * head; struct list_head * pos; struct list_head * n; struct cache_hash * hash; int count = -1; hash = cache->c_hash + cache->hash(key, cache->c_hashsize, cache->c_hashshift); head = &hash->ch_list; pthread_mutex_lock(&hash->ch_mutex); for (pos = head->next, n = pos->next; pos != head; pos = n, n = pos->next) { if ((struct cache_node *)pos != node) continue; count = __cache_node_purge(cache, node); if (!count) hash->ch_count--; break; } pthread_mutex_unlock(&hash->ch_mutex); if (count == 0) { pthread_mutex_lock(&cache->c_mutex); cache->c_count--; pthread_mutex_unlock(&cache->c_mutex); } #ifdef CACHE_DEBUG if (count >= 1) { fprintf(stderr, "%s: refcount was %u, not zero (node=%p)\n", __FUNCTION__, count, node); cache_abort(); } if (count == -1) { fprintf(stderr, "%s: purge node not found! (node=%p)\n", __FUNCTION__, node); cache_abort(); } #endif return count == 0; } /* * Purge all nodes from the cache. All reference counts must be zero. */ void cache_purge( struct cache * cache) { int i; for (i = 0; i <= CACHE_DIRTY_PRIORITY; i++) cache_shake(cache, i, true); #ifdef CACHE_DEBUG if (cache->c_count != 0) { /* flush referenced nodes to disk */ cache_flush(cache); fprintf(stderr, "%s: shake on cache %p left %u nodes!?\n", __FUNCTION__, cache, cache->c_count); cache_abort(); } #endif } /* * Flush all nodes in the cache to disk. */ void cache_flush( struct cache * cache) { struct cache_hash * hash; struct list_head * head; struct list_head * pos; struct cache_node * node; int i; if (!cache->flush) return; for (i = 0; i < cache->c_hashsize; i++) { hash = &cache->c_hash[i]; pthread_mutex_lock(&hash->ch_mutex); head = &hash->ch_list; for (pos = head->next; pos != head; pos = pos->next) { node = (struct cache_node *)pos; pthread_mutex_lock(&node->cn_mutex); cache->flush(node); pthread_mutex_unlock(&node->cn_mutex); } pthread_mutex_unlock(&hash->ch_mutex); } } #define HASH_REPORT (3 * HASH_CACHE_RATIO) void cache_report( FILE *fp, const char *name, struct cache *cache) { int i; unsigned long count, index, total; unsigned long hash_bucket_lengths[HASH_REPORT + 2]; if ((cache->c_hits + cache->c_misses) == 0) return; /* report cache summary */ fprintf(fp, "%s: %p\n" "Max supported entries = %u\n" "Max utilized entries = %u\n" "Active entries = %u\n" "Hash table size = %u\n" "Hits = %llu\n" "Misses = %llu\n" "Hit ratio = %5.2f\n", name, cache, cache->c_maxcount, cache->c_max, cache->c_count, cache->c_hashsize, cache->c_hits, cache->c_misses, (double)cache->c_hits * 100 / (cache->c_hits + cache->c_misses) ); for (i = 0; i <= CACHE_MAX_PRIORITY; i++) fprintf(fp, "MRU %d entries = %6u (%3u%%)\n", i, cache->c_mrus[i].cm_count, cache->c_mrus[i].cm_count * 100 / cache->c_count); i = CACHE_DIRTY_PRIORITY; fprintf(fp, "Dirty MRU %d entries = %6u (%3u%%)\n", i, cache->c_mrus[i].cm_count, cache->c_mrus[i].cm_count * 100 / cache->c_count); /* report hash bucket lengths */ bzero(hash_bucket_lengths, sizeof(hash_bucket_lengths)); for (i = 0; i < cache->c_hashsize; i++) { count = cache->c_hash[i].ch_count; if (count > HASH_REPORT) index = HASH_REPORT + 1; else index = count; hash_bucket_lengths[index]++; } total = 0; for (i = 0; i < HASH_REPORT + 1; i++) { total += i * hash_bucket_lengths[i]; if (hash_bucket_lengths[i] == 0) continue; fprintf(fp, "Hash buckets with %2d entries %6ld (%3ld%%)\n", i, hash_bucket_lengths[i], (i * hash_bucket_lengths[i] * 100) / cache->c_count); } if (hash_bucket_lengths[i]) /* last report bucket is the overflow bucket */ fprintf(fp, "Hash buckets with >%2d entries %6ld (%3ld%%)\n", i - 1, hash_bucket_lengths[i], ((cache->c_count - total) * 100) / cache->c_count); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/crc32.c0000644000000000000000000012035213063067170015043 0ustar /* * Aug 8, 2011 Bob Pearson with help from Joakim Tjernlund and George Spelvin * cleaned up code to current version of sparse and added the slicing-by-8 * algorithm to the closely similar existing slicing-by-4 algorithm. * * Oct 15, 2000 Matt Domsch * Nicer crc32 functions/docs submitted by linux@horizon.com. Thanks! * Code was from the public domain, copyright abandoned. Code was * subsequently included in the kernel, thus was re-licensed under the * GNU GPL v2. * * Oct 12, 2000 Matt Domsch * Same crc32 function was used in 5 other places in the kernel. * I made one version, and deleted the others. * There are various incantations of crc32(). Some use a seed of 0 or ~0. * Some xor at the end with ~0. The generic crc32() function takes * seed as an argument, and doesn't xor at the end. Then individual * users can do whatever they need. * drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0. * fs/jffs2 uses seed 0, doesn't xor with ~0. * fs/partitions/efi.c uses seed ~0, xor's with ~0. * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ /* see: Documentation/crc32.txt for a description of algorithms */ /* * lifted from the 3.8-rc2 kernel source for xfsprogs. Killed CONFIG_X86 * specific bits for just the generic algorithm. Also removed the big endian * version of the algorithm as XFS only uses the little endian CRC version to * match the hardware acceleration available on Intel CPUs. */ #include "platform_defs.h" #include "xfs.h" #include "xfs_arch.h" #include "crc32defs.h" /* types specifc to this file */ typedef __u8 u8; typedef __u16 u16; typedef __u32 u32; typedef __u32 u64; #define __pure #if CRC_LE_BITS > 8 # define tole(x) ((__force u32) __constant_cpu_to_le32(x)) #else # define tole(x) (x) #endif #if CRC_BE_BITS > 8 # define tobe(x) ((__force u32) __constant_cpu_to_be32(x)) #else # define tobe(x) (x) #endif #include "crc32table.h" #if CRC_LE_BITS > 8 || CRC_BE_BITS > 8 /* implements slicing-by-4 or slicing-by-8 algorithm */ static inline u32 crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256]) { #if __BYTE_ORDER == __LITTLE_ENDIAN # define DO_CRC(x) crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8) # define DO_CRC4 (t3[(q) & 255] ^ t2[(q >> 8) & 255] ^ \ t1[(q >> 16) & 255] ^ t0[(q >> 24) & 255]) # define DO_CRC8 (t7[(q) & 255] ^ t6[(q >> 8) & 255] ^ \ t5[(q >> 16) & 255] ^ t4[(q >> 24) & 255]) # elif __BYTE_ORDER == __BIG_ENDIAN # define DO_CRC(x) crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8) # define DO_CRC4 (t0[(q) & 255] ^ t1[(q >> 8) & 255] ^ \ t2[(q >> 16) & 255] ^ t3[(q >> 24) & 255]) # define DO_CRC8 (t4[(q) & 255] ^ t5[(q >> 8) & 255] ^ \ t6[(q >> 16) & 255] ^ t7[(q >> 24) & 255]) # else # error What endian are you? # endif const u32 *b; size_t rem_len; const u32 *t0=tab[0], *t1=tab[1], *t2=tab[2], *t3=tab[3]; # if CRC_LE_BITS != 32 const u32 *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7]; # endif u32 q; /* Align it */ if (((long)buf & 3) && len) { do { DO_CRC(*buf++); } while ((--len) && ((long)buf)&3); } # if CRC_LE_BITS == 32 rem_len = len & 3; len = len >> 2; # else rem_len = len & 7; len = len >> 3; # endif b = (const u32 *)buf; for (--b; len; --len) { q = crc ^ *++b; /* use pre increment for speed */ # if CRC_LE_BITS == 32 crc = DO_CRC4; # else crc = DO_CRC8; q = *++b; crc ^= DO_CRC4; # endif } len = rem_len; /* And the last few bytes */ if (len) { u8 *p = (u8 *)(b + 1) - 1; do { DO_CRC(*++p); /* use pre increment for speed */ } while (--len); } return crc; #undef DO_CRC #undef DO_CRC4 #undef DO_CRC8 } #endif /** * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for * other uses, or the previous crc32 value if computing incrementally. * @p: pointer to buffer over which CRC is run * @len: length of buffer @p */ static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p, size_t len, const u32 (*tab)[256], u32 polynomial) { #if CRC_LE_BITS == 1 int i; while (len--) { crc ^= *p++; for (i = 0; i < 8; i++) crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0); } # elif CRC_LE_BITS == 2 while (len--) { crc ^= *p++; crc = (crc >> 2) ^ tab[0][crc & 3]; crc = (crc >> 2) ^ tab[0][crc & 3]; crc = (crc >> 2) ^ tab[0][crc & 3]; crc = (crc >> 2) ^ tab[0][crc & 3]; } # elif CRC_LE_BITS == 4 while (len--) { crc ^= *p++; crc = (crc >> 4) ^ tab[0][crc & 15]; crc = (crc >> 4) ^ tab[0][crc & 15]; } # elif CRC_LE_BITS == 8 /* aka Sarwate algorithm */ while (len--) { crc ^= *p++; crc = (crc >> 8) ^ tab[0][crc & 255]; } # else crc = (__force u32) cpu_to_le32(crc); crc = crc32_body(crc, p, len, tab); crc = le32_to_cpu((__force __le32)crc); #endif return crc; } #if CRC_LE_BITS == 1 u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, NULL, CRCPOLY_LE); } u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, NULL, CRC32C_POLY_LE); } #else u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, (const u32 (*)[256])crc32table_le, CRCPOLY_LE); } u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, (const u32 (*)[256])crc32ctable_le, CRC32C_POLY_LE); } #endif #ifdef CRC32_SELFTEST /* 4096 random bytes */ static u8 __attribute__((__aligned__(8))) test_buf[] = { 0x5b, 0x85, 0x21, 0xcb, 0x09, 0x68, 0x7d, 0x30, 0xc7, 0x69, 0xd7, 0x30, 0x92, 0xde, 0x59, 0xe4, 0xc9, 0x6e, 0x8b, 0xdb, 0x98, 0x6b, 0xaa, 0x60, 0xa8, 0xb5, 0xbc, 0x6c, 0xa9, 0xb1, 0x5b, 0x2c, 0xea, 0xb4, 0x92, 0x6a, 0x3f, 0x79, 0x91, 0xe4, 0xe9, 0x70, 0x51, 0x8c, 0x7f, 0x95, 0x6f, 0x1a, 0x56, 0xa1, 0x5c, 0x27, 0x03, 0x67, 0x9f, 0x3a, 0xe2, 0x31, 0x11, 0x29, 0x6b, 0x98, 0xfc, 0xc4, 0x53, 0x24, 0xc5, 0x8b, 0xce, 0x47, 0xb2, 0xb9, 0x32, 0xcb, 0xc1, 0xd0, 0x03, 0x57, 0x4e, 0xd4, 0xe9, 0x3c, 0xa1, 0x63, 0xcf, 0x12, 0x0e, 0xca, 0xe1, 0x13, 0xd1, 0x93, 0xa6, 0x88, 0x5c, 0x61, 0x5b, 0xbb, 0xf0, 0x19, 0x46, 0xb4, 0xcf, 0x9e, 0xb6, 0x6b, 0x4c, 0x3a, 0xcf, 0x60, 0xf9, 0x7a, 0x8d, 0x07, 0x63, 0xdb, 0x40, 0xe9, 0x0b, 0x6f, 0xad, 0x97, 0xf1, 0xed, 0xd0, 0x1e, 0x26, 0xfd, 0xbf, 0xb7, 0xc8, 0x04, 0x94, 0xf8, 0x8b, 0x8c, 0xf1, 0xab, 0x7a, 0xd4, 0xdd, 0xf3, 0xe8, 0x88, 0xc3, 0xed, 0x17, 0x8a, 0x9b, 0x40, 0x0d, 0x53, 0x62, 0x12, 0x03, 0x5f, 0x1b, 0x35, 0x32, 0x1f, 0xb4, 0x7b, 0x93, 0x78, 0x0d, 0xdb, 0xce, 0xa4, 0xc0, 0x47, 0xd5, 0xbf, 0x68, 0xe8, 0x5d, 0x74, 0x8f, 0x8e, 0x75, 0x1c, 0xb2, 0x4f, 0x9a, 0x60, 0xd1, 0xbe, 0x10, 0xf4, 0x5c, 0xa1, 0x53, 0x09, 0xa5, 0xe0, 0x09, 0x54, 0x85, 0x5c, 0xdc, 0x07, 0xe7, 0x21, 0x69, 0x7b, 0x8a, 0xfd, 0x90, 0xf1, 0x22, 0xd0, 0xb4, 0x36, 0x28, 0xe6, 0xb8, 0x0f, 0x39, 0xde, 0xc8, 0xf3, 0x86, 0x60, 0x34, 0xd2, 0x5e, 0xdf, 0xfd, 0xcf, 0x0f, 0xa9, 0x65, 0xf0, 0xd5, 0x4d, 0x96, 0x40, 0xe3, 0xdf, 0x3f, 0x95, 0x5a, 0x39, 0x19, 0x93, 0xf4, 0x75, 0xce, 0x22, 0x00, 0x1c, 0x93, 0xe2, 0x03, 0x66, 0xf4, 0x93, 0x73, 0x86, 0x81, 0x8e, 0x29, 0x44, 0x48, 0x86, 0x61, 0x7c, 0x48, 0xa3, 0x43, 0xd2, 0x9c, 0x8d, 0xd4, 0x95, 0xdd, 0xe1, 0x22, 0x89, 0x3a, 0x40, 0x4c, 0x1b, 0x8a, 0x04, 0xa8, 0x09, 0x69, 0x8b, 0xea, 0xc6, 0x55, 0x8e, 0x57, 0xe6, 0x64, 0x35, 0xf0, 0xc7, 0x16, 0x9f, 0x5d, 0x5e, 0x86, 0x40, 0x46, 0xbb, 0xe5, 0x45, 0x88, 0xfe, 0xc9, 0x63, 0x15, 0xfb, 0xf5, 0xbd, 0x71, 0x61, 0xeb, 0x7b, 0x78, 0x70, 0x07, 0x31, 0x03, 0x9f, 0xb2, 0xc8, 0xa7, 0xab, 0x47, 0xfd, 0xdf, 0xa0, 0x78, 0x72, 0xa4, 0x2a, 0xe4, 0xb6, 0xba, 0xc0, 0x1e, 0x86, 0x71, 0xe6, 0x3d, 0x18, 0x37, 0x70, 0xe6, 0xff, 0xe0, 0xbc, 0x0b, 0x22, 0xa0, 0x1f, 0xd3, 0xed, 0xa2, 0x55, 0x39, 0xab, 0xa8, 0x13, 0x73, 0x7c, 0x3f, 0xb2, 0xd6, 0x19, 0xac, 0xff, 0x99, 0xed, 0xe8, 0xe6, 0xa6, 0x22, 0xe3, 0x9c, 0xf1, 0x30, 0xdc, 0x01, 0x0a, 0x56, 0xfa, 0xe4, 0xc9, 0x99, 0xdd, 0xa8, 0xd8, 0xda, 0x35, 0x51, 0x73, 0xb4, 0x40, 0x86, 0x85, 0xdb, 0x5c, 0xd5, 0x85, 0x80, 0x14, 0x9c, 0xfd, 0x98, 0xa9, 0x82, 0xc5, 0x37, 0xff, 0x32, 0x5d, 0xd0, 0x0b, 0xfa, 0xdc, 0x04, 0x5e, 0x09, 0xd2, 0xca, 0x17, 0x4b, 0x1a, 0x8e, 0x15, 0xe1, 0xcc, 0x4e, 0x52, 0x88, 0x35, 0xbd, 0x48, 0xfe, 0x15, 0xa0, 0x91, 0xfd, 0x7e, 0x6c, 0x0e, 0x5d, 0x79, 0x1b, 0x81, 0x79, 0xd2, 0x09, 0x34, 0x70, 0x3d, 0x81, 0xec, 0xf6, 0x24, 0xbb, 0xfb, 0xf1, 0x7b, 0xdf, 0x54, 0xea, 0x80, 0x9b, 0xc7, 0x99, 0x9e, 0xbd, 0x16, 0x78, 0x12, 0x53, 0x5e, 0x01, 0xa7, 0x4e, 0xbd, 0x67, 0xe1, 0x9b, 0x4c, 0x0e, 0x61, 0x45, 0x97, 0xd2, 0xf0, 0x0f, 0xfe, 0x15, 0x08, 0xb7, 0x11, 0x4c, 0xe7, 0xff, 0x81, 0x53, 0xff, 0x91, 0x25, 0x38, 0x7e, 0x40, 0x94, 0xe5, 0xe0, 0xad, 0xe6, 0xd9, 0x79, 0xb6, 0x92, 0xc9, 0xfc, 0xde, 0xc3, 0x1a, 0x23, 0xbb, 0xdd, 0xc8, 0x51, 0x0c, 0x3a, 0x72, 0xfa, 0x73, 0x6f, 0xb7, 0xee, 0x61, 0x39, 0x03, 0x01, 0x3f, 0x7f, 0x94, 0x2e, 0x2e, 0xba, 0x3a, 0xbb, 0xb4, 0xfa, 0x6a, 0x17, 0xfe, 0xea, 0xef, 0x5e, 0x66, 0x97, 0x3f, 0x32, 0x3d, 0xd7, 0x3e, 0xb1, 0xf1, 0x6c, 0x14, 0x4c, 0xfd, 0x37, 0xd3, 0x38, 0x80, 0xfb, 0xde, 0xa6, 0x24, 0x1e, 0xc8, 0xca, 0x7f, 0x3a, 0x93, 0xd8, 0x8b, 0x18, 0x13, 0xb2, 0xe5, 0xe4, 0x93, 0x05, 0x53, 0x4f, 0x84, 0x66, 0xa7, 0x58, 0x5c, 0x7b, 0x86, 0x52, 0x6d, 0x0d, 0xce, 0xa4, 0x30, 0x7d, 0xb6, 0x18, 0x9f, 0xeb, 0xff, 0x22, 0xbb, 0x72, 0x29, 0xb9, 0x44, 0x0b, 0x48, 0x1e, 0x84, 0x71, 0x81, 0xe3, 0x6d, 0x73, 0x26, 0x92, 0xb4, 0x4d, 0x2a, 0x29, 0xb8, 0x1f, 0x72, 0xed, 0xd0, 0xe1, 0x64, 0x77, 0xea, 0x8e, 0x88, 0x0f, 0xef, 0x3f, 0xb1, 0x3b, 0xad, 0xf9, 0xc9, 0x8b, 0xd0, 0xac, 0xc6, 0xcc, 0xa9, 0x40, 0xcc, 0x76, 0xf6, 0x3b, 0x53, 0xb5, 0x88, 0xcb, 0xc8, 0x37, 0xf1, 0xa2, 0xba, 0x23, 0x15, 0x99, 0x09, 0xcc, 0xe7, 0x7a, 0x3b, 0x37, 0xf7, 0x58, 0xc8, 0x46, 0x8c, 0x2b, 0x2f, 0x4e, 0x0e, 0xa6, 0x5c, 0xea, 0x85, 0x55, 0xba, 0x02, 0x0e, 0x0e, 0x48, 0xbc, 0xe1, 0xb1, 0x01, 0x35, 0x79, 0x13, 0x3d, 0x1b, 0xc0, 0x53, 0x68, 0x11, 0xe7, 0x95, 0x0f, 0x9d, 0x3f, 0x4c, 0x47, 0x7b, 0x4d, 0x1c, 0xae, 0x50, 0x9b, 0xcb, 0xdd, 0x05, 0x8d, 0x9a, 0x97, 0xfd, 0x8c, 0xef, 0x0c, 0x1d, 0x67, 0x73, 0xa8, 0x28, 0x36, 0xd5, 0xb6, 0x92, 0x33, 0x40, 0x75, 0x0b, 0x51, 0xc3, 0x64, 0xba, 0x1d, 0xc2, 0xcc, 0xee, 0x7d, 0x54, 0x0f, 0x27, 0x69, 0xa7, 0x27, 0x63, 0x30, 0x29, 0xd9, 0xc8, 0x84, 0xd8, 0xdf, 0x9f, 0x68, 0x8d, 0x04, 0xca, 0xa6, 0xc5, 0xc7, 0x7a, 0x5c, 0xc8, 0xd1, 0xcb, 0x4a, 0xec, 0xd0, 0xd8, 0x20, 0x69, 0xc5, 0x17, 0xcd, 0x78, 0xc8, 0x75, 0x23, 0x30, 0x69, 0xc9, 0xd4, 0xea, 0x5c, 0x4f, 0x6b, 0x86, 0x3f, 0x8b, 0xfe, 0xee, 0x44, 0xc9, 0x7c, 0xb7, 0xdd, 0x3e, 0xe5, 0xec, 0x54, 0x03, 0x3e, 0xaa, 0x82, 0xc6, 0xdf, 0xb2, 0x38, 0x0e, 0x5d, 0xb3, 0x88, 0xd9, 0xd3, 0x69, 0x5f, 0x8f, 0x70, 0x8a, 0x7e, 0x11, 0xd9, 0x1e, 0x7b, 0x38, 0xf1, 0x42, 0x1a, 0xc0, 0x35, 0xf5, 0xc7, 0x36, 0x85, 0xf5, 0xf7, 0xb8, 0x7e, 0xc7, 0xef, 0x18, 0xf1, 0x63, 0xd6, 0x7a, 0xc6, 0xc9, 0x0e, 0x4d, 0x69, 0x4f, 0x84, 0xef, 0x26, 0x41, 0x0c, 0xec, 0xc7, 0xe0, 0x7e, 0x3c, 0x67, 0x01, 0x4c, 0x62, 0x1a, 0x20, 0x6f, 0xee, 0x47, 0x4d, 0xc0, 0x99, 0x13, 0x8d, 0x91, 0x4a, 0x26, 0xd4, 0x37, 0x28, 0x90, 0x58, 0x75, 0x66, 0x2b, 0x0a, 0xdf, 0xda, 0xee, 0x92, 0x25, 0x90, 0x62, 0x39, 0x9e, 0x44, 0x98, 0xad, 0xc1, 0x88, 0xed, 0xe4, 0xb4, 0xaf, 0xf5, 0x8c, 0x9b, 0x48, 0x4d, 0x56, 0x60, 0x97, 0x0f, 0x61, 0x59, 0x9e, 0xa6, 0x27, 0xfe, 0xc1, 0x91, 0x15, 0x38, 0xb8, 0x0f, 0xae, 0x61, 0x7d, 0x26, 0x13, 0x5a, 0x73, 0xff, 0x1c, 0xa3, 0x61, 0x04, 0x58, 0x48, 0x55, 0x44, 0x11, 0xfe, 0x15, 0xca, 0xc3, 0xbd, 0xca, 0xc5, 0xb4, 0x40, 0x5d, 0x1b, 0x7f, 0x39, 0xb5, 0x9c, 0x35, 0xec, 0x61, 0x15, 0x32, 0x32, 0xb8, 0x4e, 0x40, 0x9f, 0x17, 0x1f, 0x0a, 0x4d, 0xa9, 0x91, 0xef, 0xb7, 0xb0, 0xeb, 0xc2, 0x83, 0x9a, 0x6c, 0xd2, 0x79, 0x43, 0x78, 0x5e, 0x2f, 0xe5, 0xdd, 0x1a, 0x3c, 0x45, 0xab, 0x29, 0x40, 0x3a, 0x37, 0x5b, 0x6f, 0xd7, 0xfc, 0x48, 0x64, 0x3c, 0x49, 0xfb, 0x21, 0xbe, 0xc3, 0xff, 0x07, 0xfb, 0x17, 0xe9, 0xc9, 0x0c, 0x4c, 0x5c, 0x15, 0x9e, 0x8e, 0x22, 0x30, 0x0a, 0xde, 0x48, 0x7f, 0xdb, 0x0d, 0xd1, 0x2b, 0x87, 0x38, 0x9e, 0xcc, 0x5a, 0x01, 0x16, 0xee, 0x75, 0x49, 0x0d, 0x30, 0x01, 0x34, 0x6a, 0xb6, 0x9a, 0x5a, 0x2a, 0xec, 0xbb, 0x48, 0xac, 0xd3, 0x77, 0x83, 0xd8, 0x08, 0x86, 0x4f, 0x48, 0x09, 0x29, 0x41, 0x79, 0xa1, 0x03, 0x12, 0xc4, 0xcd, 0x90, 0x55, 0x47, 0x66, 0x74, 0x9a, 0xcc, 0x4f, 0x35, 0x8c, 0xd6, 0x98, 0xef, 0xeb, 0x45, 0xb9, 0x9a, 0x26, 0x2f, 0x39, 0xa5, 0x70, 0x6d, 0xfc, 0xb4, 0x51, 0xee, 0xf4, 0x9c, 0xe7, 0x38, 0x59, 0xad, 0xf4, 0xbc, 0x46, 0xff, 0x46, 0x8e, 0x60, 0x9c, 0xa3, 0x60, 0x1d, 0xf8, 0x26, 0x72, 0xf5, 0x72, 0x9d, 0x68, 0x80, 0x04, 0xf6, 0x0b, 0xa1, 0x0a, 0xd5, 0xa7, 0x82, 0x3a, 0x3e, 0x47, 0xa8, 0x5a, 0xde, 0x59, 0x4f, 0x7b, 0x07, 0xb3, 0xe9, 0x24, 0x19, 0x3d, 0x34, 0x05, 0xec, 0xf1, 0xab, 0x6e, 0x64, 0x8f, 0xd3, 0xe6, 0x41, 0x86, 0x80, 0x70, 0xe3, 0x8d, 0x60, 0x9c, 0x34, 0x25, 0x01, 0x07, 0x4d, 0x19, 0x41, 0x4e, 0x3d, 0x5c, 0x7e, 0xa8, 0xf5, 0xcc, 0xd5, 0x7b, 0xe2, 0x7d, 0x3d, 0x49, 0x86, 0x7d, 0x07, 0xb7, 0x10, 0xe3, 0x35, 0xb8, 0x84, 0x6d, 0x76, 0xab, 0x17, 0xc6, 0x38, 0xb4, 0xd3, 0x28, 0x57, 0xad, 0xd3, 0x88, 0x5a, 0xda, 0xea, 0xc8, 0x94, 0xcc, 0x37, 0x19, 0xac, 0x9c, 0x9f, 0x4b, 0x00, 0x15, 0xc0, 0xc8, 0xca, 0x1f, 0x15, 0xaa, 0xe0, 0xdb, 0xf9, 0x2f, 0x57, 0x1b, 0x24, 0xc7, 0x6f, 0x76, 0x29, 0xfb, 0xed, 0x25, 0x0d, 0xc0, 0xfe, 0xbd, 0x5a, 0xbf, 0x20, 0x08, 0x51, 0x05, 0xec, 0x71, 0xa3, 0xbf, 0xef, 0x5e, 0x99, 0x75, 0xdb, 0x3c, 0x5f, 0x9a, 0x8c, 0xbb, 0x19, 0x5c, 0x0e, 0x93, 0x19, 0xf8, 0x6a, 0xbc, 0xf2, 0x12, 0x54, 0x2f, 0xcb, 0x28, 0x64, 0x88, 0xb3, 0x92, 0x0d, 0x96, 0xd1, 0xa6, 0xe4, 0x1f, 0xf1, 0x4d, 0xa4, 0xab, 0x1c, 0xee, 0x54, 0xf2, 0xad, 0x29, 0x6d, 0x32, 0x37, 0xb2, 0x16, 0x77, 0x5c, 0xdc, 0x2e, 0x54, 0xec, 0x75, 0x26, 0xc6, 0x36, 0xd9, 0x17, 0x2c, 0xf1, 0x7a, 0xdc, 0x4b, 0xf1, 0xe2, 0xd9, 0x95, 0xba, 0xac, 0x87, 0xc1, 0xf3, 0x8e, 0x58, 0x08, 0xd8, 0x87, 0x60, 0xc9, 0xee, 0x6a, 0xde, 0xa4, 0xd2, 0xfc, 0x0d, 0xe5, 0x36, 0xc4, 0x5c, 0x52, 0xb3, 0x07, 0x54, 0x65, 0x24, 0xc1, 0xb1, 0xd1, 0xb1, 0x53, 0x13, 0x31, 0x79, 0x7f, 0x05, 0x76, 0xeb, 0x37, 0x59, 0x15, 0x2b, 0xd1, 0x3f, 0xac, 0x08, 0x97, 0xeb, 0x91, 0x98, 0xdf, 0x6c, 0x09, 0x0d, 0x04, 0x9f, 0xdc, 0x3b, 0x0e, 0x60, 0x68, 0x47, 0x23, 0x15, 0x16, 0xc6, 0x0b, 0x35, 0xf8, 0x77, 0xa2, 0x78, 0x50, 0xd4, 0x64, 0x22, 0x33, 0xff, 0xfb, 0x93, 0x71, 0x46, 0x50, 0x39, 0x1b, 0x9c, 0xea, 0x4e, 0x8d, 0x0c, 0x37, 0xe5, 0x5c, 0x51, 0x3a, 0x31, 0xb2, 0x85, 0x84, 0x3f, 0x41, 0xee, 0xa2, 0xc1, 0xc6, 0x13, 0x3b, 0x54, 0x28, 0xd2, 0x18, 0x37, 0xcc, 0x46, 0x9f, 0x6a, 0x91, 0x3d, 0x5a, 0x15, 0x3c, 0x89, 0xa3, 0x61, 0x06, 0x7d, 0x2e, 0x78, 0xbe, 0x7d, 0x40, 0xba, 0x2f, 0x95, 0xb1, 0x2f, 0x87, 0x3b, 0x8a, 0xbe, 0x6a, 0xf4, 0xc2, 0x31, 0x74, 0xee, 0x91, 0xe0, 0x23, 0xaa, 0x5d, 0x7f, 0xdd, 0xf0, 0x44, 0x8c, 0x0b, 0x59, 0x2b, 0xfc, 0x48, 0x3a, 0xdf, 0x07, 0x05, 0x38, 0x6c, 0xc9, 0xeb, 0x18, 0x24, 0x68, 0x8d, 0x58, 0x98, 0xd3, 0x31, 0xa3, 0xe4, 0x70, 0x59, 0xb1, 0x21, 0xbe, 0x7e, 0x65, 0x7d, 0xb8, 0x04, 0xab, 0xf6, 0xe4, 0xd7, 0xda, 0xec, 0x09, 0x8f, 0xda, 0x6d, 0x24, 0x07, 0xcc, 0x29, 0x17, 0x05, 0x78, 0x1a, 0xc1, 0xb1, 0xce, 0xfc, 0xaa, 0x2d, 0xe7, 0xcc, 0x85, 0x84, 0x84, 0x03, 0x2a, 0x0c, 0x3f, 0xa9, 0xf8, 0xfd, 0x84, 0x53, 0x59, 0x5c, 0xf0, 0xd4, 0x09, 0xf0, 0xd2, 0x6c, 0x32, 0x03, 0xb0, 0xa0, 0x8c, 0x52, 0xeb, 0x23, 0x91, 0x88, 0x43, 0x13, 0x46, 0xf6, 0x1e, 0xb4, 0x1b, 0xf5, 0x8e, 0x3a, 0xb5, 0x3d, 0x00, 0xf6, 0xe5, 0x08, 0x3d, 0x5f, 0x39, 0xd3, 0x21, 0x69, 0xbc, 0x03, 0x22, 0x3a, 0xd2, 0x5c, 0x84, 0xf8, 0x15, 0xc4, 0x80, 0x0b, 0xbc, 0x29, 0x3c, 0xf3, 0x95, 0x98, 0xcd, 0x8f, 0x35, 0xbc, 0xa5, 0x3e, 0xfc, 0xd4, 0x13, 0x9e, 0xde, 0x4f, 0xce, 0x71, 0x9d, 0x09, 0xad, 0xf2, 0x80, 0x6b, 0x65, 0x7f, 0x03, 0x00, 0x14, 0x7c, 0x15, 0x85, 0x40, 0x6d, 0x70, 0xea, 0xdc, 0xb3, 0x63, 0x35, 0x4f, 0x4d, 0xe0, 0xd9, 0xd5, 0x3c, 0x58, 0x56, 0x23, 0x80, 0xe2, 0x36, 0xdd, 0x75, 0x1d, 0x94, 0x11, 0x41, 0x8e, 0xe0, 0x81, 0x8e, 0xcf, 0xe0, 0xe5, 0xf6, 0xde, 0xd1, 0xe7, 0x04, 0x12, 0x79, 0x92, 0x2b, 0x71, 0x2a, 0x79, 0x8b, 0x7c, 0x44, 0x79, 0x16, 0x30, 0x4e, 0xf4, 0xf6, 0x9b, 0xb7, 0x40, 0xa3, 0x5a, 0xa7, 0x69, 0x3e, 0xc1, 0x3a, 0x04, 0xd0, 0x88, 0xa0, 0x3b, 0xdd, 0xc6, 0x9e, 0x7e, 0x1e, 0x1e, 0x8f, 0x44, 0xf7, 0x73, 0x67, 0x1e, 0x1a, 0x78, 0xfa, 0x62, 0xf4, 0xa9, 0xa8, 0xc6, 0x5b, 0xb8, 0xfa, 0x06, 0x7d, 0x5e, 0x38, 0x1c, 0x9a, 0x39, 0xe9, 0x39, 0x98, 0x22, 0x0b, 0xa7, 0xac, 0x0b, 0xf3, 0xbc, 0xf1, 0xeb, 0x8c, 0x81, 0xe3, 0x48, 0x8a, 0xed, 0x42, 0xc2, 0x38, 0xcf, 0x3e, 0xda, 0xd2, 0x89, 0x8d, 0x9c, 0x53, 0xb5, 0x2f, 0x41, 0x01, 0x26, 0x84, 0x9c, 0xa3, 0x56, 0xf6, 0x49, 0xc7, 0xd4, 0x9f, 0x93, 0x1b, 0x96, 0x49, 0x5e, 0xad, 0xb3, 0x84, 0x1f, 0x3c, 0xa4, 0xe0, 0x9b, 0xd1, 0x90, 0xbc, 0x38, 0x6c, 0xdd, 0x95, 0x4d, 0x9d, 0xb1, 0x71, 0x57, 0x2d, 0x34, 0xe8, 0xb8, 0x42, 0xc7, 0x99, 0x03, 0xc7, 0x07, 0x30, 0x65, 0x91, 0x55, 0xd5, 0x90, 0x70, 0x97, 0x37, 0x68, 0xd4, 0x11, 0xf9, 0xe8, 0xce, 0xec, 0xdc, 0x34, 0xd5, 0xd3, 0xb7, 0xc4, 0xb8, 0x97, 0x05, 0x92, 0xad, 0xf8, 0xe2, 0x36, 0x64, 0x41, 0xc9, 0xc5, 0x41, 0x77, 0x52, 0xd7, 0x2c, 0xa5, 0x24, 0x2f, 0xd9, 0x34, 0x0b, 0x47, 0x35, 0xa7, 0x28, 0x8b, 0xc5, 0xcd, 0xe9, 0x46, 0xac, 0x39, 0x94, 0x3c, 0x10, 0xc6, 0x29, 0x73, 0x0e, 0x0e, 0x5d, 0xe0, 0x71, 0x03, 0x8a, 0x72, 0x0e, 0x26, 0xb0, 0x7d, 0x84, 0xed, 0x95, 0x23, 0x49, 0x5a, 0x45, 0x83, 0x45, 0x60, 0x11, 0x4a, 0x46, 0x31, 0xd4, 0xd8, 0x16, 0x54, 0x98, 0x58, 0xed, 0x6d, 0xcc, 0x5d, 0xd6, 0x50, 0x61, 0x9f, 0x9d, 0xc5, 0x3e, 0x9d, 0x32, 0x47, 0xde, 0x96, 0xe1, 0x5d, 0xd8, 0xf8, 0xb4, 0x69, 0x6f, 0xb9, 0x15, 0x90, 0x57, 0x7a, 0xf6, 0xad, 0xb0, 0x5b, 0xf5, 0xa6, 0x36, 0x94, 0xfd, 0x84, 0xce, 0x1c, 0x0f, 0x4b, 0xd0, 0xc2, 0x5b, 0x6b, 0x56, 0xef, 0x73, 0x93, 0x0b, 0xc3, 0xee, 0xd9, 0xcf, 0xd3, 0xa4, 0x22, 0x58, 0xcd, 0x50, 0x6e, 0x65, 0xf4, 0xe9, 0xb7, 0x71, 0xaf, 0x4b, 0xb3, 0xb6, 0x2f, 0x0f, 0x0e, 0x3b, 0xc9, 0x85, 0x14, 0xf5, 0x17, 0xe8, 0x7a, 0x3a, 0xbf, 0x5f, 0x5e, 0xf8, 0x18, 0x48, 0xa6, 0x72, 0xab, 0x06, 0x95, 0xe9, 0xc8, 0xa7, 0xf4, 0x32, 0x44, 0x04, 0x0c, 0x84, 0x98, 0x73, 0xe3, 0x89, 0x8d, 0x5f, 0x7e, 0x4a, 0x42, 0x8f, 0xc5, 0x28, 0xb1, 0x82, 0xef, 0x1c, 0x97, 0x31, 0x3b, 0x4d, 0xe0, 0x0e, 0x10, 0x10, 0x97, 0x93, 0x49, 0x78, 0x2f, 0x0d, 0x86, 0x8b, 0xa1, 0x53, 0xa9, 0x81, 0x20, 0x79, 0xe7, 0x07, 0x77, 0xb6, 0xac, 0x5e, 0xd2, 0x05, 0xcd, 0xe9, 0xdb, 0x8a, 0x94, 0x82, 0x8a, 0x23, 0xb9, 0x3d, 0x1c, 0xa9, 0x7d, 0x72, 0x4a, 0xed, 0x33, 0xa3, 0xdb, 0x21, 0xa7, 0x86, 0x33, 0x45, 0xa5, 0xaa, 0x56, 0x45, 0xb5, 0x83, 0x29, 0x40, 0x47, 0x79, 0x04, 0x6e, 0xb9, 0x95, 0xd0, 0x81, 0x77, 0x2d, 0x48, 0x1e, 0xfe, 0xc3, 0xc2, 0x1e, 0xe5, 0xf2, 0xbe, 0xfd, 0x3b, 0x94, 0x9f, 0xc4, 0xc4, 0x26, 0x9d, 0xe4, 0x66, 0x1e, 0x19, 0xee, 0x6c, 0x79, 0x97, 0x11, 0x31, 0x4b, 0x0d, 0x01, 0xcb, 0xde, 0xa8, 0xf6, 0x6d, 0x7c, 0x39, 0x46, 0x4e, 0x7e, 0x3f, 0x94, 0x17, 0xdf, 0xa1, 0x7d, 0xd9, 0x1c, 0x8e, 0xbc, 0x7d, 0x33, 0x7d, 0xe3, 0x12, 0x40, 0xca, 0xab, 0x37, 0x11, 0x46, 0xd4, 0xae, 0xef, 0x44, 0xa2, 0xb3, 0x6a, 0x66, 0x0e, 0x0c, 0x90, 0x7f, 0xdf, 0x5c, 0x66, 0x5f, 0xf2, 0x94, 0x9f, 0xa6, 0x73, 0x4f, 0xeb, 0x0d, 0xad, 0xbf, 0xc0, 0x63, 0x5c, 0xdc, 0x46, 0x51, 0xe8, 0x8e, 0x90, 0x19, 0xa8, 0xa4, 0x3c, 0x91, 0x79, 0xfa, 0x7e, 0x58, 0x85, 0x13, 0x55, 0xc5, 0x19, 0x82, 0x37, 0x1b, 0x0a, 0x02, 0x1f, 0x99, 0x6b, 0x18, 0xf1, 0x28, 0x08, 0xa2, 0x73, 0xb8, 0x0f, 0x2e, 0xcd, 0xbf, 0xf3, 0x86, 0x7f, 0xea, 0xef, 0xd0, 0xbb, 0xa6, 0x21, 0xdf, 0x49, 0x73, 0x51, 0xcc, 0x36, 0xd3, 0x3e, 0xa0, 0xf8, 0x44, 0xdf, 0xd3, 0xa6, 0xbe, 0x8a, 0xd4, 0x57, 0xdd, 0x72, 0x94, 0x61, 0x0f, 0x82, 0xd1, 0x07, 0xb8, 0x7c, 0x18, 0x83, 0xdf, 0x3a, 0xe5, 0x50, 0x6a, 0x82, 0x20, 0xac, 0xa9, 0xa8, 0xff, 0xd9, 0xf3, 0x77, 0x33, 0x5a, 0x9e, 0x7f, 0x6d, 0xfe, 0x5d, 0x33, 0x41, 0x42, 0xe7, 0x6c, 0x19, 0xe0, 0x44, 0x8a, 0x15, 0xf6, 0x70, 0x98, 0xb7, 0x68, 0x4d, 0xfa, 0x97, 0x39, 0xb0, 0x8e, 0xe8, 0x84, 0x8b, 0x75, 0x30, 0xb7, 0x7d, 0x92, 0x69, 0x20, 0x9c, 0x81, 0xfb, 0x4b, 0xf4, 0x01, 0x50, 0xeb, 0xce, 0x0c, 0x1c, 0x6c, 0xb5, 0x4a, 0xd7, 0x27, 0x0c, 0xce, 0xbb, 0xe5, 0x85, 0xf0, 0xb6, 0xee, 0xd5, 0x70, 0xdd, 0x3b, 0xfc, 0xd4, 0x99, 0xf1, 0x33, 0xdd, 0x8b, 0xc4, 0x2f, 0xae, 0xab, 0x74, 0x96, 0x32, 0xc7, 0x4c, 0x56, 0x3c, 0x89, 0x0f, 0x96, 0x0b, 0x42, 0xc0, 0xcb, 0xee, 0x0f, 0x0b, 0x8c, 0xfb, 0x7e, 0x47, 0x7b, 0x64, 0x48, 0xfd, 0xb2, 0x00, 0x80, 0x89, 0xa5, 0x13, 0x55, 0x62, 0xfc, 0x8f, 0xe2, 0x42, 0x03, 0xb7, 0x4e, 0x2a, 0x79, 0xb4, 0x82, 0xea, 0x23, 0x49, 0xda, 0xaf, 0x52, 0x63, 0x1e, 0x60, 0x03, 0x89, 0x06, 0x44, 0x46, 0x08, 0xc3, 0xc4, 0x87, 0x70, 0x2e, 0xda, 0x94, 0xad, 0x6b, 0xe0, 0xe4, 0xd1, 0x8a, 0x06, 0xc2, 0xa8, 0xc0, 0xa7, 0x43, 0x3c, 0x47, 0x52, 0x0e, 0xc3, 0x77, 0x81, 0x11, 0x67, 0x0e, 0xa0, 0x70, 0x04, 0x47, 0x29, 0x40, 0x86, 0x0d, 0x34, 0x56, 0xa7, 0xc9, 0x35, 0x59, 0x68, 0xdc, 0x93, 0x81, 0x70, 0xee, 0x86, 0xd9, 0x80, 0x06, 0x40, 0x4f, 0x1a, 0x0d, 0x40, 0x30, 0x0b, 0xcb, 0x96, 0x47, 0xc1, 0xb7, 0x52, 0xfd, 0x56, 0xe0, 0x72, 0x4b, 0xfb, 0xbd, 0x92, 0x45, 0x61, 0x71, 0xc2, 0x33, 0x11, 0xbf, 0x52, 0x83, 0x79, 0x26, 0xe0, 0x49, 0x6b, 0xb7, 0x05, 0x8b, 0xe8, 0x0e, 0x87, 0x31, 0xd7, 0x9d, 0x8a, 0xf5, 0xc0, 0x5f, 0x2e, 0x58, 0x4a, 0xdb, 0x11, 0xb3, 0x6c, 0x30, 0x2a, 0x46, 0x19, 0xe3, 0x27, 0x84, 0x1f, 0x63, 0x6e, 0xf6, 0x57, 0xc7, 0xc9, 0xd8, 0x5e, 0xba, 0xb3, 0x87, 0xd5, 0x83, 0x26, 0x34, 0x21, 0x9e, 0x65, 0xde, 0x42, 0xd3, 0xbe, 0x7b, 0xbc, 0x91, 0x71, 0x44, 0x4d, 0x99, 0x3b, 0x31, 0xe5, 0x3f, 0x11, 0x4e, 0x7f, 0x13, 0x51, 0x3b, 0xae, 0x79, 0xc9, 0xd3, 0x81, 0x8e, 0x25, 0x40, 0x10, 0xfc, 0x07, 0x1e, 0xf9, 0x7b, 0x9a, 0x4b, 0x6c, 0xe3, 0xb3, 0xad, 0x1a, 0x0a, 0xdd, 0x9e, 0x59, 0x0c, 0xa2, 0xcd, 0xae, 0x48, 0x4a, 0x38, 0x5b, 0x47, 0x41, 0x94, 0x65, 0x6b, 0xbb, 0xeb, 0x5b, 0xe3, 0xaf, 0x07, 0x5b, 0xd4, 0x4a, 0xa2, 0xc9, 0x5d, 0x2f, 0x64, 0x03, 0xd7, 0x3a, 0x2c, 0x6e, 0xce, 0x76, 0x95, 0xb4, 0xb3, 0xc0, 0xf1, 0xe2, 0x45, 0x73, 0x7a, 0x5c, 0xab, 0xc1, 0xfc, 0x02, 0x8d, 0x81, 0x29, 0xb3, 0xac, 0x07, 0xec, 0x40, 0x7d, 0x45, 0xd9, 0x7a, 0x59, 0xee, 0x34, 0xf0, 0xe9, 0xd5, 0x7b, 0x96, 0xb1, 0x3d, 0x95, 0xcc, 0x86, 0xb5, 0xb6, 0x04, 0x2d, 0xb5, 0x92, 0x7e, 0x76, 0xf4, 0x06, 0xa9, 0xa3, 0x12, 0x0f, 0xb1, 0xaf, 0x26, 0xba, 0x7c, 0xfc, 0x7e, 0x1c, 0xbc, 0x2c, 0x49, 0x97, 0x53, 0x60, 0x13, 0x0b, 0xa6, 0x61, 0x83, 0x89, 0x42, 0xd4, 0x17, 0x0c, 0x6c, 0x26, 0x52, 0xc3, 0xb3, 0xd4, 0x67, 0xf5, 0xe3, 0x04, 0xb7, 0xf4, 0xcb, 0x80, 0xb8, 0xcb, 0x77, 0x56, 0x3e, 0xaa, 0x57, 0x54, 0xee, 0xb4, 0x2c, 0x67, 0xcf, 0xf2, 0xdc, 0xbe, 0x55, 0xf9, 0x43, 0x1f, 0x6e, 0x22, 0x97, 0x67, 0x7f, 0xc4, 0xef, 0xb1, 0x26, 0x31, 0x1e, 0x27, 0xdf, 0x41, 0x80, 0x47, 0x6c, 0xe2, 0xfa, 0xa9, 0x8c, 0x2a, 0xf6, 0xf2, 0xab, 0xf0, 0x15, 0xda, 0x6c, 0xc8, 0xfe, 0xb5, 0x23, 0xde, 0xa9, 0x05, 0x3f, 0x06, 0x54, 0x4c, 0xcd, 0xe1, 0xab, 0xfc, 0x0e, 0x62, 0x33, 0x31, 0x73, 0x2c, 0x76, 0xcb, 0xb4, 0x47, 0x1e, 0x20, 0xad, 0xd8, 0xf2, 0x31, 0xdd, 0xc4, 0x8b, 0x0c, 0x77, 0xbe, 0xe1, 0x8b, 0x26, 0x00, 0x02, 0x58, 0xd6, 0x8d, 0xef, 0xad, 0x74, 0x67, 0xab, 0x3f, 0xef, 0xcb, 0x6f, 0xb0, 0xcc, 0x81, 0x44, 0x4c, 0xaf, 0xe9, 0x49, 0x4f, 0xdb, 0xa0, 0x25, 0xa4, 0xf0, 0x89, 0xf1, 0xbe, 0xd8, 0x10, 0xff, 0xb1, 0x3b, 0x4b, 0xfa, 0x98, 0xf5, 0x79, 0x6d, 0x1e, 0x69, 0x4d, 0x57, 0xb1, 0xc8, 0x19, 0x1b, 0xbd, 0x1e, 0x8c, 0x84, 0xb7, 0x7b, 0xe8, 0xd2, 0x2d, 0x09, 0x41, 0x41, 0x37, 0x3d, 0xb1, 0x6f, 0x26, 0x5d, 0x71, 0x16, 0x3d, 0xb7, 0x83, 0x27, 0x2c, 0xa7, 0xb6, 0x50, 0xbd, 0x91, 0x86, 0xab, 0x24, 0xa1, 0x38, 0xfd, 0xea, 0x71, 0x55, 0x7e, 0x9a, 0x07, 0x77, 0x4b, 0xfa, 0x61, 0x66, 0x20, 0x1e, 0x28, 0x95, 0x18, 0x1b, 0xa4, 0xa0, 0xfd, 0xc0, 0x89, 0x72, 0x43, 0xd9, 0x3b, 0x49, 0x5a, 0x3f, 0x9d, 0xbf, 0xdb, 0xb4, 0x46, 0xea, 0x42, 0x01, 0x77, 0x23, 0x68, 0x95, 0xb6, 0x24, 0xb3, 0xa8, 0x6c, 0x28, 0x3b, 0x11, 0x40, 0x7e, 0x18, 0x65, 0x6d, 0xd8, 0x24, 0x42, 0x7d, 0x88, 0xc0, 0x52, 0xd9, 0x05, 0xe4, 0x95, 0x90, 0x87, 0x8c, 0xf4, 0xd0, 0x6b, 0xb9, 0x83, 0x99, 0x34, 0x6d, 0xfe, 0x54, 0x40, 0x94, 0x52, 0x21, 0x4f, 0x14, 0x25, 0xc5, 0xd6, 0x5e, 0x95, 0xdc, 0x0a, 0x2b, 0x89, 0x20, 0x11, 0x84, 0x48, 0xd6, 0x3a, 0xcd, 0x5c, 0x24, 0xad, 0x62, 0xe3, 0xb1, 0x93, 0x25, 0x8d, 0xcd, 0x7e, 0xfc, 0x27, 0xa3, 0x37, 0xfd, 0x84, 0xfc, 0x1b, 0xb2, 0xf1, 0x27, 0x38, 0x5a, 0xb7, 0xfc, 0xf2, 0xfa, 0x95, 0x66, 0xd4, 0xfb, 0xba, 0xa7, 0xd7, 0xa3, 0x72, 0x69, 0x48, 0x48, 0x8c, 0xeb, 0x28, 0x89, 0xfe, 0x33, 0x65, 0x5a, 0x36, 0x01, 0x7e, 0x06, 0x79, 0x0a, 0x09, 0x3b, 0x74, 0x11, 0x9a, 0x6e, 0xbf, 0xd4, 0x9e, 0x58, 0x90, 0x49, 0x4f, 0x4d, 0x08, 0xd4, 0xe5, 0x4a, 0x09, 0x21, 0xef, 0x8b, 0xb8, 0x74, 0x3b, 0x91, 0xdd, 0x36, 0x85, 0x60, 0x2d, 0xfa, 0xd4, 0x45, 0x7b, 0x45, 0x53, 0xf5, 0x47, 0x87, 0x7e, 0xa6, 0x37, 0xc8, 0x78, 0x7a, 0x68, 0x9d, 0x8d, 0x65, 0x2c, 0x0e, 0x91, 0x5c, 0xa2, 0x60, 0xf0, 0x8e, 0x3f, 0xe9, 0x1a, 0xcd, 0xaa, 0xe7, 0xd5, 0x77, 0x18, 0xaf, 0xc9, 0xbc, 0x18, 0xea, 0x48, 0x1b, 0xfb, 0x22, 0x48, 0x70, 0x16, 0x29, 0x9e, 0x5b, 0xc1, 0x2c, 0x66, 0x23, 0xbc, 0xf0, 0x1f, 0xef, 0xaf, 0xe4, 0xd6, 0x04, 0x19, 0x82, 0x7a, 0x0b, 0xba, 0x4b, 0x46, 0xb1, 0x6a, 0x85, 0x5d, 0xb4, 0x73, 0xd6, 0x21, 0xa1, 0x71, 0x60, 0x14, 0xee, 0x0a, 0x77, 0xc4, 0x66, 0x2e, 0xf9, 0x69, 0x30, 0xaf, 0x41, 0x0b, 0xc8, 0x83, 0x3c, 0x53, 0x99, 0x19, 0x27, 0x46, 0xf7, 0x41, 0x6e, 0x56, 0xdc, 0x94, 0x28, 0x67, 0x4e, 0xb7, 0x25, 0x48, 0x8a, 0xc2, 0xe0, 0x60, 0x96, 0xcc, 0x18, 0xf4, 0x84, 0xdd, 0xa7, 0x5e, 0x3e, 0x05, 0x0b, 0x26, 0x26, 0xb2, 0x5c, 0x1f, 0x57, 0x1a, 0x04, 0x7e, 0x6a, 0xe3, 0x2f, 0xb4, 0x35, 0xb6, 0x38, 0x40, 0x40, 0xcd, 0x6f, 0x87, 0x2e, 0xef, 0xa3, 0xd7, 0xa9, 0xc2, 0xe8, 0x0d, 0x27, 0xdf, 0x44, 0x62, 0x99, 0xa0, 0xfc, 0xcf, 0x81, 0x78, 0xcb, 0xfe, 0xe5, 0xa0, 0x03, 0x4e, 0x6c, 0xd7, 0xf4, 0xaf, 0x7a, 0xbb, 0x61, 0x82, 0xfe, 0x71, 0x89, 0xb2, 0x22, 0x7c, 0x8e, 0x83, 0x04, 0xce, 0xf6, 0x5d, 0x84, 0x8f, 0x95, 0x6a, 0x7f, 0xad, 0xfd, 0x32, 0x9c, 0x5e, 0xe4, 0x9c, 0x89, 0x60, 0x54, 0xaa, 0x96, 0x72, 0xd2, 0xd7, 0x36, 0x85, 0xa9, 0x45, 0xd2, 0x2a, 0xa1, 0x81, 0x49, 0x6f, 0x7e, 0x04, 0xfa, 0xe2, 0xfe, 0x90, 0x26, 0x77, 0x5a, 0x33, 0xb8, 0x04, 0x9a, 0x7a, 0xe6, 0x4c, 0x4f, 0xad, 0x72, 0x96, 0x08, 0x28, 0x58, 0x13, 0xf8, 0xc4, 0x1c, 0xf0, 0xc3, 0x45, 0x95, 0x49, 0x20, 0x8c, 0x9f, 0x39, 0x70, 0xe1, 0x77, 0xfe, 0xd5, 0x4b, 0xaf, 0x86, 0xda, 0xef, 0x22, 0x06, 0x83, 0x36, 0x29, 0x12, 0x11, 0x40, 0xbc, 0x3b, 0x86, 0xaa, 0xaa, 0x65, 0x60, 0xc3, 0x80, 0xca, 0xed, 0xa9, 0xf3, 0xb0, 0x79, 0x96, 0xa2, 0x55, 0x27, 0x28, 0x55, 0x73, 0x26, 0xa5, 0x50, 0xea, 0x92, 0x4b, 0x3c, 0x5c, 0x82, 0x33, 0xf0, 0x01, 0x3f, 0x03, 0xc1, 0x08, 0x05, 0xbf, 0x98, 0xf4, 0x9b, 0x6d, 0xa5, 0xa8, 0xb4, 0x82, 0x0c, 0x06, 0xfa, 0xff, 0x2d, 0x08, 0xf3, 0x05, 0x4f, 0x57, 0x2a, 0x39, 0xd4, 0x83, 0x0d, 0x75, 0x51, 0xd8, 0x5b, 0x1b, 0xd3, 0x51, 0x5a, 0x32, 0x2a, 0x9b, 0x32, 0xb2, 0xf2, 0xa4, 0x96, 0x12, 0xf2, 0xae, 0x40, 0x34, 0x67, 0xa8, 0xf5, 0x44, 0xd5, 0x35, 0x53, 0xfe, 0xa3, 0x60, 0x96, 0x63, 0x0f, 0x1f, 0x6e, 0xb0, 0x5a, 0x42, 0xa6, 0xfc, 0x51, 0x0b, 0x60, 0x27, 0xbc, 0x06, 0x71, 0xed, 0x65, 0x5b, 0x23, 0x86, 0x4a, 0x07, 0x3b, 0x22, 0x07, 0x46, 0xe6, 0x90, 0x3e, 0xf3, 0x25, 0x50, 0x1b, 0x4c, 0x7f, 0x03, 0x08, 0xa8, 0x36, 0x6b, 0x87, 0xe5, 0xe3, 0xdb, 0x9a, 0x38, 0x83, 0xff, 0x9f, 0x1a, 0x9f, 0x57, 0xa4, 0x2a, 0xf6, 0x37, 0xbc, 0x1a, 0xff, 0xc9, 0x1e, 0x35, 0x0c, 0xc3, 0x7c, 0xa3, 0xb2, 0xe5, 0xd2, 0xc6, 0xb4, 0x57, 0x47, 0xe4, 0x32, 0x16, 0x6d, 0xa9, 0xae, 0x64, 0xe6, 0x2d, 0x8d, 0xc5, 0x8d, 0x50, 0x8e, 0xe8, 0x1a, 0x22, 0x34, 0x2a, 0xd9, 0xeb, 0x51, 0x90, 0x4a, 0xb1, 0x41, 0x7d, 0x64, 0xf9, 0xb9, 0x0d, 0xf6, 0x23, 0x33, 0xb0, 0x33, 0xf4, 0xf7, 0x3f, 0x27, 0x84, 0xc6, 0x0f, 0x54, 0xa5, 0xc0, 0x2e, 0xec, 0x0b, 0x3a, 0x48, 0x6e, 0x80, 0x35, 0x81, 0x43, 0x9b, 0x90, 0xb1, 0xd0, 0x2b, 0xea, 0x21, 0xdc, 0xda, 0x5b, 0x09, 0xf4, 0xcc, 0x10, 0xb4, 0xc7, 0xfe, 0x79, 0x51, 0xc3, 0xc5, 0xac, 0x88, 0x74, 0x84, 0x0b, 0x4b, 0xca, 0x79, 0x16, 0x29, 0xfb, 0x69, 0x54, 0xdf, 0x41, 0x7e, 0xe9, 0xc7, 0x8e, 0xea, 0xa5, 0xfe, 0xfc, 0x76, 0x0e, 0x90, 0xc4, 0x92, 0x38, 0xad, 0x7b, 0x48, 0xe6, 0x6e, 0xf7, 0x21, 0xfd, 0x4e, 0x93, 0x0a, 0x7b, 0x41, 0x83, 0x68, 0xfb, 0x57, 0x51, 0x76, 0x34, 0xa9, 0x6c, 0x00, 0xaa, 0x4f, 0x66, 0x65, 0x98, 0x4a, 0x4f, 0xa3, 0xa0, 0xef, 0x69, 0x3f, 0xe3, 0x1c, 0x92, 0x8c, 0xfd, 0xd8, 0xe8, 0xde, 0x7c, 0x7f, 0x3e, 0x84, 0x8e, 0x69, 0x3c, 0xf1, 0xf2, 0x05, 0x46, 0xdc, 0x2f, 0x9d, 0x5e, 0x6e, 0x4c, 0xfb, 0xb5, 0x99, 0x2a, 0x59, 0x63, 0xc1, 0x34, 0xbc, 0x57, 0xc0, 0x0d, 0xb9, 0x61, 0x25, 0xf3, 0x33, 0x23, 0x51, 0xb6, 0x0d, 0x07, 0xa6, 0xab, 0x94, 0x4a, 0xb7, 0x2a, 0xea, 0xee, 0xac, 0xa3, 0xc3, 0x04, 0x8b, 0x0e, 0x56, 0xfe, 0x44, 0xa7, 0x39, 0xe2, 0xed, 0xed, 0xb4, 0x22, 0x2b, 0xac, 0x12, 0x32, 0x28, 0x91, 0xd8, 0xa5, 0xab, 0xff, 0x5f, 0xe0, 0x4b, 0xda, 0x78, 0x17, 0xda, 0xf1, 0x01, 0x5b, 0xcd, 0xe2, 0x5f, 0x50, 0x45, 0x73, 0x2b, 0xe4, 0x76, 0x77, 0xf4, 0x64, 0x1d, 0x43, 0xfb, 0x84, 0x7a, 0xea, 0x91, 0xae, 0xf9, 0x9e, 0xb7, 0xb4, 0xb0, 0x91, 0x5f, 0x16, 0x35, 0x9a, 0x11, 0xb8, 0xc7, 0xc1, 0x8c, 0xc6, 0x10, 0x8d, 0x2f, 0x63, 0x4a, 0xa7, 0x57, 0x3a, 0x51, 0xd6, 0x32, 0x2d, 0x64, 0x72, 0xd4, 0x66, 0xdc, 0x10, 0xa6, 0x67, 0xd6, 0x04, 0x23, 0x9d, 0x0a, 0x11, 0x77, 0xdd, 0x37, 0x94, 0x17, 0x3c, 0xbf, 0x8b, 0x65, 0xb0, 0x2e, 0x5e, 0x66, 0x47, 0x64, 0xac, 0xdd, 0xf0, 0x84, 0xfd, 0x39, 0xfa, 0x15, 0x5d, 0xef, 0xae, 0xca, 0xc1, 0x36, 0xa7, 0x5c, 0xbf, 0xc7, 0x08, 0xc2, 0x66, 0x00, 0x74, 0x74, 0x4e, 0x27, 0x3f, 0x55, 0x8a, 0xb7, 0x38, 0x66, 0x83, 0x6d, 0xcf, 0x99, 0x9e, 0x60, 0x8f, 0xdd, 0x2e, 0x62, 0x22, 0x0e, 0xef, 0x0c, 0x98, 0xa7, 0x85, 0x74, 0x3b, 0x9d, 0xec, 0x9e, 0xa9, 0x19, 0x72, 0xa5, 0x7f, 0x2c, 0x39, 0xb7, 0x7d, 0xb7, 0xf1, 0x12, 0x65, 0x27, 0x4b, 0x5a, 0xde, 0x17, 0xfe, 0xad, 0x44, 0xf3, 0x20, 0x4d, 0xfd, 0xe4, 0x1f, 0xb5, 0x81, 0xb0, 0x36, 0x37, 0x08, 0x6f, 0xc3, 0x0c, 0xe9, 0x85, 0x98, 0x82, 0xa9, 0x62, 0x0c, 0xc4, 0x97, 0xc0, 0x50, 0xc8, 0xa7, 0x3c, 0x50, 0x9f, 0x43, 0xb9, 0xcd, 0x5e, 0x4d, 0xfa, 0x1c, 0x4b, 0x0b, 0xa9, 0x98, 0x85, 0x38, 0x92, 0xac, 0x8d, 0xe4, 0xad, 0x9b, 0x98, 0xab, 0xd9, 0x38, 0xac, 0x62, 0x52, 0xa3, 0x22, 0x63, 0x0f, 0xbf, 0x95, 0x48, 0xdf, 0x69, 0xe7, 0x8b, 0x33, 0xd5, 0xb2, 0xbd, 0x05, 0x49, 0x49, 0x9d, 0x57, 0x73, 0x19, 0x33, 0xae, 0xfa, 0x33, 0xf1, 0x19, 0xa8, 0x80, 0xce, 0x04, 0x9f, 0xbc, 0x1d, 0x65, 0x82, 0x1b, 0xe5, 0x3a, 0x51, 0xc8, 0x1c, 0x21, 0xe3, 0x5d, 0xf3, 0x7d, 0x9b, 0x2f, 0x2c, 0x1d, 0x4a, 0x7f, 0x9b, 0x68, 0x35, 0xa3, 0xb2, 0x50, 0xf7, 0x62, 0x79, 0xcd, 0xf4, 0x98, 0x4f, 0xe5, 0x63, 0x7c, 0x3e, 0x45, 0x31, 0x8c, 0x16, 0xa0, 0x12, 0xc8, 0x58, 0xce, 0x39, 0xa6, 0xbc, 0x54, 0xdb, 0xc5, 0xe0, 0xd5, 0xba, 0xbc, 0xb9, 0x04, 0xf4, 0x8d, 0xe8, 0x2f, 0x15, 0x9d, }; /* 100 test cases */ static struct crc_test { u32 crc; /* random starting crc */ u32 start; /* random 6 bit offset in buf */ u32 length; /* random 11 bit length of test */ u32 crc_le; /* expected crc32_le result */ u32 crc_be; /* expected crc32_be result */ u32 crc32c_le; /* expected crc32c_le result */ } test[] = { {0x674bf11d, 0x00000038, 0x00000542, 0x0af6d466, 0xd8b6e4c1, 0xf6e93d6c}, {0x35c672c6, 0x0000003a, 0x000001aa, 0xc6d3dfba, 0x28aaf3ad, 0x0fe92aca}, {0x496da28e, 0x00000039, 0x000005af, 0xd933660f, 0x5d57e81f, 0x52e1ebb8}, {0x09a9b90e, 0x00000027, 0x000001f8, 0xb45fe007, 0xf45fca9a, 0x0798af9a}, {0xdc97e5a9, 0x00000025, 0x000003b6, 0xf81a3562, 0xe0126ba2, 0x18eb3152}, {0x47c58900, 0x0000000a, 0x000000b9, 0x8e58eccf, 0xf3afc793, 0xd00d08c7}, {0x292561e8, 0x0000000c, 0x00000403, 0xa2ba8aaf, 0x0b797aed, 0x8ba966bc}, {0x415037f6, 0x00000003, 0x00000676, 0xa17d52e8, 0x7f0fdf35, 0x11d694a2}, {0x3466e707, 0x00000026, 0x00000042, 0x258319be, 0x75c484a2, 0x6ab3208d}, {0xafd1281b, 0x00000023, 0x000002ee, 0x4428eaf8, 0x06c7ad10, 0xba4603c5}, {0xd3857b18, 0x00000028, 0x000004a2, 0x5c430821, 0xb062b7cb, 0xe6071c6f}, {0x1d825a8f, 0x0000002b, 0x0000050b, 0xd2c45f0c, 0xd68634e0, 0x179ec30a}, {0x5033e3bc, 0x0000000b, 0x00000078, 0xa3ea4113, 0xac6d31fb, 0x0903beb8}, {0x94f1fb5e, 0x0000000f, 0x000003a2, 0xfbfc50b1, 0x3cfe50ed, 0x6a7cb4fa}, {0xc9a0fe14, 0x00000009, 0x00000473, 0x5fb61894, 0x87070591, 0xdb535801}, {0x88a034b1, 0x0000001c, 0x000005ad, 0xc1b16053, 0x46f95c67, 0x92bed597}, {0xf0f72239, 0x00000020, 0x0000026d, 0xa6fa58f3, 0xf8c2c1dd, 0x192a3f1b}, {0xcc20a5e3, 0x0000003b, 0x0000067a, 0x7740185a, 0x308b979a, 0xccbaec1a}, {0xce589c95, 0x0000002b, 0x00000641, 0xd055e987, 0x40aae25b, 0x7eabae4d}, {0x78edc885, 0x00000035, 0x000005be, 0xa39cb14b, 0x035b0d1f, 0x28c72982}, {0x9d40a377, 0x0000003b, 0x00000038, 0x1f47ccd2, 0x197fbc9d, 0xc3cd4d18}, {0x703d0e01, 0x0000003c, 0x000006f1, 0x88735e7c, 0xfed57c5a, 0xbca8f0e7}, {0x776bf505, 0x0000000f, 0x000005b2, 0x5cc4fc01, 0xf32efb97, 0x713f60b3}, {0x4a3e7854, 0x00000027, 0x000004b8, 0x8d923c82, 0x0cbfb4a2, 0xebd08fd5}, {0x209172dd, 0x0000003b, 0x00000356, 0xb89e9c2b, 0xd7868138, 0x64406c59}, {0x3ba4cc5b, 0x0000002f, 0x00000203, 0xe51601a9, 0x5b2a1032, 0x7421890e}, {0xfc62f297, 0x00000000, 0x00000079, 0x71a8e1a2, 0x5d88685f, 0xe9347603}, {0x64280b8b, 0x00000016, 0x000007ab, 0x0fa7a30c, 0xda3a455f, 0x1bef9060}, {0x97dd724b, 0x00000033, 0x000007ad, 0x5788b2f4, 0xd7326d32, 0x34720072}, {0x61394b52, 0x00000035, 0x00000571, 0xc66525f1, 0xcabe7fef, 0x48310f59}, {0x29b4faff, 0x00000024, 0x0000006e, 0xca13751e, 0x993648e0, 0x783a4213}, {0x29bfb1dc, 0x0000000b, 0x00000244, 0x436c43f7, 0x429f7a59, 0x9e8efd41}, {0x86ae934b, 0x00000035, 0x00000104, 0x0760ec93, 0x9cf7d0f4, 0xfc3d34a5}, {0xc4c1024e, 0x0000002e, 0x000006b1, 0x6516a3ec, 0x19321f9c, 0x17a52ae2}, {0x3287a80a, 0x00000026, 0x00000496, 0x0b257eb1, 0x754ebd51, 0x886d935a}, {0xa4db423e, 0x00000023, 0x0000045d, 0x9b3a66dc, 0x873e9f11, 0xeaaeaeb2}, {0x7a1078df, 0x00000015, 0x0000014a, 0x8c2484c5, 0x6a628659, 0x8e900a4b}, {0x6048bd5b, 0x00000006, 0x0000006a, 0x897e3559, 0xac9961af, 0xd74662b1}, {0xd8f9ea20, 0x0000003d, 0x00000277, 0x60eb905b, 0xed2aaf99, 0xd26752ba}, {0xea5ec3b4, 0x0000002a, 0x000004fe, 0x869965dc, 0x6c1f833b, 0x8b1fcd62}, {0x2dfb005d, 0x00000016, 0x00000345, 0x6a3b117e, 0xf05e8521, 0xf54342fe}, {0x5a214ade, 0x00000020, 0x000005b6, 0x467f70be, 0xcb22ccd3, 0x5b95b988}, {0xf0ab9cca, 0x00000032, 0x00000515, 0xed223df3, 0x7f3ef01d, 0x2e1176be}, {0x91b444f9, 0x0000002e, 0x000007f8, 0x84e9a983, 0x5676756f, 0x66120546}, {0x1b5d2ddb, 0x0000002e, 0x0000012c, 0xba638c4c, 0x3f42047b, 0xf256a5cc}, {0xd824d1bb, 0x0000003a, 0x000007b5, 0x6288653b, 0x3a3ebea0, 0x4af1dd69}, {0x0470180c, 0x00000034, 0x000001f0, 0x9d5b80d6, 0x3de08195, 0x56f0a04a}, {0xffaa3a3f, 0x00000036, 0x00000299, 0xf3a82ab8, 0x53e0c13d, 0x74f6b6b2}, {0x6406cfeb, 0x00000023, 0x00000600, 0xa920b8e8, 0xe4e2acf4, 0x085951fd}, {0xb24aaa38, 0x0000003e, 0x000004a1, 0x657cc328, 0x5077b2c3, 0xc65387eb}, {0x58b2ab7c, 0x00000039, 0x000002b4, 0x3a17ee7e, 0x9dcb3643, 0x1ca9257b}, {0x3db85970, 0x00000006, 0x000002b6, 0x95268b59, 0xb9812c10, 0xfd196d76}, {0x857830c5, 0x00000003, 0x00000590, 0x4ef439d5, 0xf042161d, 0x5ef88339}, {0xe1fcd978, 0x0000003e, 0x000007d8, 0xae8d8699, 0xce0a1ef5, 0x2c3714d9}, {0xb982a768, 0x00000016, 0x000006e0, 0x62fad3df, 0x5f8a067b, 0x58576548}, {0x1d581ce8, 0x0000001e, 0x0000058b, 0xf0f5da53, 0x26e39eee, 0xfd7c57de}, {0x2456719b, 0x00000025, 0x00000503, 0x4296ac64, 0xd50e4c14, 0xd5fedd59}, {0xfae6d8f2, 0x00000000, 0x0000055d, 0x057fdf2e, 0x2a31391a, 0x1cc3b17b}, {0xcba828e3, 0x00000039, 0x000002ce, 0xe3f22351, 0x8f00877b, 0x270eed73}, {0x13d25952, 0x0000000a, 0x0000072d, 0x76d4b4cc, 0x5eb67ec3, 0x91ecbb11}, {0x0342be3f, 0x00000015, 0x00000599, 0xec75d9f1, 0x9d4d2826, 0x05ed8d0c}, {0xeaa344e0, 0x00000014, 0x000004d8, 0x72a4c981, 0x2064ea06, 0x0b09ad5b}, {0xbbb52021, 0x0000003b, 0x00000272, 0x04af99fc, 0xaf042d35, 0xf8d511fb}, {0xb66384dc, 0x0000001d, 0x000007fc, 0xd7629116, 0x782bd801, 0x5ad832cc}, {0x616c01b6, 0x00000022, 0x000002c8, 0x5b1dab30, 0x783ce7d2, 0x1214d196}, {0xce2bdaad, 0x00000016, 0x0000062a, 0x932535c8, 0x3f02926d, 0x5747218a}, {0x00fe84d7, 0x00000005, 0x00000205, 0x850e50aa, 0x753d649c, 0xde8f14de}, {0xbebdcb4c, 0x00000006, 0x0000055d, 0xbeaa37a2, 0x2d8c9eba, 0x3563b7b9}, {0xd8b1a02a, 0x00000010, 0x00000387, 0x5017d2fc, 0x503541a5, 0x071475d0}, {0x3b96cad2, 0x00000036, 0x00000347, 0x1d2372ae, 0x926cd90b, 0x54c79d60}, {0xc94c1ed7, 0x00000005, 0x0000038b, 0x9e9fdb22, 0x144a9178, 0x4c53eee6}, {0x1aad454e, 0x00000025, 0x000002b2, 0xc3f6315c, 0x5c7a35b3, 0x10137a3c}, {0xa4fec9a6, 0x00000000, 0x000006d6, 0x90be5080, 0xa4107605, 0xaa9d6c73}, {0x1bbe71e2, 0x0000001f, 0x000002fd, 0x4e504c3b, 0x284ccaf1, 0xb63d23e7}, {0x4201c7e4, 0x00000002, 0x000002b7, 0x7822e3f9, 0x0cc912a9, 0x7f53e9cf}, {0x23fddc96, 0x00000003, 0x00000627, 0x8a385125, 0x07767e78, 0x13c1cd83}, {0xd82ba25c, 0x00000016, 0x0000063e, 0x98e4148a, 0x283330c9, 0x49ff5867}, {0x786f2032, 0x0000002d, 0x0000060f, 0xf201600a, 0xf561bfcd, 0x8467f211}, {0xfebe4e1f, 0x0000002a, 0x000004f2, 0x95e51961, 0xfd80dcab, 0x3f9683b2}, {0x1a6e0a39, 0x00000008, 0x00000672, 0x8af6c2a5, 0x78dd84cb, 0x76a3f874}, {0x56000ab8, 0x0000000e, 0x000000e5, 0x36bacb8f, 0x22ee1f77, 0x863b702f}, {0x4717fe0c, 0x00000000, 0x000006ec, 0x8439f342, 0x5c8e03da, 0xdc6c58ff}, {0xd5d5d68e, 0x0000003c, 0x000003a3, 0x46fff083, 0x177d1b39, 0x0622cc95}, {0xc25dd6c6, 0x00000024, 0x000006c0, 0x5ceb8eb4, 0x892b0d16, 0xe85605cd}, {0xe9b11300, 0x00000023, 0x00000683, 0x07a5d59a, 0x6c6a3208, 0x31da5f06}, {0x95cd285e, 0x00000001, 0x00000047, 0x7b3a4368, 0x0202c07e, 0xa1f2e784}, {0xd9245a25, 0x0000001e, 0x000003a6, 0xd33c1841, 0x1936c0d5, 0xb07cc616}, {0x103279db, 0x00000006, 0x0000039b, 0xca09b8a0, 0x77d62892, 0xbf943b6c}, {0x1cba3172, 0x00000027, 0x000001c8, 0xcb377194, 0xebe682db, 0x2c01af1c}, {0x8f613739, 0x0000000c, 0x000001df, 0xb4b0bc87, 0x7710bd43, 0x0fe5f56d}, {0x1c6aa90d, 0x0000001b, 0x0000053c, 0x70559245, 0xda7894ac, 0xf8943b2d}, {0xaabe5b93, 0x0000003d, 0x00000715, 0xcdbf42fa, 0x0c3b99e7, 0xe4d89272}, {0xf15dd038, 0x00000006, 0x000006db, 0x6e104aea, 0x8d5967f2, 0x7c2f6bbb}, {0x584dd49c, 0x00000020, 0x000007bc, 0x36b6cfd6, 0xad4e23b2, 0xabbf388b}, {0x5d8c9506, 0x00000020, 0x00000470, 0x4c62378e, 0x31d92640, 0x1dca1f4e}, {0xb80d17b0, 0x00000032, 0x00000346, 0x22a5bb88, 0x9a7ec89f, 0x5c170e23}, {0xdaf0592e, 0x00000023, 0x000007b0, 0x3cab3f99, 0x9b1fdd99, 0xc0e9d672}, {0x4793cc85, 0x0000000d, 0x00000706, 0xe82e04f6, 0xed3db6b7, 0xc18bdc86}, {0x82ebf64e, 0x00000009, 0x000007c3, 0x69d590a9, 0x9efa8499, 0xa874fcdd}, {0xb18a0319, 0x00000026, 0x000007db, 0x1cf98dcc, 0x8fa9ad6a, 0x9dc0bb48}, }; static int crc32c_test(void) { int i; int errors = 0; int bytes = 0; struct timeval start, stop; uint64_t usec; /* keep static to prevent cache warming code from * getting eliminated by the compiler */ static u32 crc; /* pre-warm the cache */ for (i = 0; i < 100; i++) { bytes += 2*test[i].length; crc ^= crc32c_le(test[i].crc, test_buf + test[i].start, test[i].length); } gettimeofday(&start, NULL); for (i = 0; i < 100; i++) { if (test[i].crc32c_le != crc32c_le(test[i].crc, test_buf + test[i].start, test[i].length)) errors++; } gettimeofday(&stop, NULL); usec = stop.tv_usec - start.tv_usec + 1000000 * (stop.tv_sec - start.tv_sec); if (errors) printf("crc32c: %d self tests failed\n", errors); else { printf("crc32c: tests passed, %d bytes in %" PRIu64 " usec\n", bytes, usec); } return errors; } static int crc32_test(void) { int i; int errors = 0; int bytes = 0; struct timeval start, stop; uint64_t usec; /* keep static to prevent cache warming code from * getting eliminated by the compiler */ static u32 crc; /* pre-warm the cache */ for (i = 0; i < 100; i++) { bytes += 2*test[i].length; crc ^= crc32_le(test[i].crc, test_buf + test[i].start, test[i].length); #if 0 /* not used */ crc ^= crc32_be(test[i].crc, test_buf + test[i].start, test[i].length); #endif } gettimeofday(&start, NULL); for (i = 0; i < 100; i++) { if (test[i].crc_le != crc32_le(test[i].crc, test_buf + test[i].start, test[i].length)) errors++; #if 0 /* not used */ if (test[i].crc_be != crc32_be(test[i].crc, test_buf + test[i].start, test[i].length)) errors++; #endif } gettimeofday(&stop, NULL); usec = stop.tv_usec - start.tv_usec + 1000000000 * (stop.tv_sec - start.tv_sec); if (errors) printf("crc32: %d self tests failed\n", errors); else { printf("crc32: tests passed, %d bytes in %" PRIu64 " usec\n", bytes, usec); } return errors; } /* * make sure we always return 0 for a successful test run, and non-zero for a * failed run. The build infrastructure is looking for this information to * determine whether to allow the build to proceed. */ int main(int argc, char **argv) { int errors; printf("CRC_LE_BITS = %d\n", CRC_LE_BITS); errors = crc32_test(); errors += crc32c_test(); return errors != 0; } #endif /* CRC32_SELFTEST */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/crc32defs.h0000644000000000000000000000400613063067171015710 0ustar /* * There are multiple 16-bit CRC polynomials in common use, but this is * *the* standard CRC-32 polynomial, first popularized by Ethernet. * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 */ #define CRCPOLY_LE 0xedb88320 #define CRCPOLY_BE 0x04c11db7 /* * This is the CRC32c polynomial, as outlined by Castagnoli. * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+ * x^8+x^6+x^0 */ #define CRC32C_POLY_LE 0x82F63B78 /* Try to choose an implementation variant via Kconfig */ #ifdef CONFIG_CRC32_SLICEBY8 # define CRC_LE_BITS 64 # define CRC_BE_BITS 64 #endif #ifdef CONFIG_CRC32_SLICEBY4 # define CRC_LE_BITS 32 # define CRC_BE_BITS 32 #endif #ifdef CONFIG_CRC32_SARWATE # define CRC_LE_BITS 8 # define CRC_BE_BITS 8 #endif #ifdef CONFIG_CRC32_BIT # define CRC_LE_BITS 1 # define CRC_BE_BITS 1 #endif /* * How many bits at a time to use. Valid values are 1, 2, 4, 8, 32 and 64. * For less performance-sensitive, use 4 or 8 to save table size. * For larger systems choose same as CPU architecture as default. * This works well on X86_64, SPARC64 systems. This may require some * elaboration after experiments with other architectures. */ #ifndef CRC_LE_BITS # ifdef CONFIG_64BIT # define CRC_LE_BITS 64 # else # define CRC_LE_BITS 32 # endif #endif #ifndef CRC_BE_BITS # ifdef CONFIG_64BIT # define CRC_BE_BITS 64 # else # define CRC_BE_BITS 32 # endif #endif /* * Little-endian CRC computation. Used with serial bit streams sent * lsbit-first. Be sure to use cpu_to_le32() to append the computed CRC. */ #if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \ CRC_LE_BITS & CRC_LE_BITS-1 # error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}" #endif /* * Big-endian CRC computation. Used with serial bit streams sent * msbit-first. Be sure to use cpu_to_be32() to append the computed CRC. */ #if CRC_BE_BITS > 64 || CRC_BE_BITS < 1 || CRC_BE_BITS == 16 || \ CRC_BE_BITS & CRC_BE_BITS-1 # error "CRC_BE_BITS must be one of {1, 2, 4, 8, 32, 64}" #endif xfsprogs-4.9.0+nmu1ubuntu2/libxfs/darwin.c0000644000000000000000000000564313063067170015420 0ustar /* * Copyright (c) 2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "libxfs.h" int platform_has_uuid = 1; extern char *progname; int platform_check_ismounted(char *name, char *block, struct stat *s, int verbose) { return 0; } int platform_check_iswritable(char *name, char *block, struct stat *s) { int fd, writable; if ((fd = open(block, O_RDONLY, 0)) < 0) { fprintf(stderr, _("%s: " "error opening the device special file \"%s\": %s\n"), progname, block, strerror(errno)); exit(1); } if (ioctl(fd, DKIOCISWRITABLE, &writable) < 0) { fprintf(stderr, _("%s: can't tell if \"%s\" is writable: %s\n"), progname, block, strerror(errno)); exit(1); } close(fd); return writable == 0; } int platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fatal) { return fatal; } void platform_flush_device(int fd, dev_t device) { ioctl(fd, DKIOCSYNCHRONIZECACHE, NULL); } void platform_findsizes(char *path, int fd, long long *sz, int *bsz) { __uint64_t size; struct stat st; if (fstat(fd, &st) < 0) { fprintf(stderr, _("%s: cannot stat the device file \"%s\": %s\n"), progname, path, strerror(errno)); exit(1); } if ((st.st_mode & S_IFMT) == S_IFREG) { *sz = (long long)(st.st_size >> 9); *bsz = BBSIZE; return; } if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size) < 0) { fprintf(stderr, _("%s: can't determine device size: %s\n"), progname, strerror(errno)); exit(1); } *sz = (long long)size; *bsz = BBSIZE; } char * platform_findrawpath(char *path) { return path; } char * platform_findblockpath(char *path) { return path; } int platform_direct_blockdev(void) { return 0; } int platform_align_blockdev(void) { return sizeof(void *); } int platform_nproc(void) { int ncpu; size_t len = sizeof(ncpu); static int mib[2] = {CTL_HW, HW_NCPU}; if (sysctl(mib, 2, &ncpu, &len, NULL, 0) < 0) ncpu = 1; return ncpu; } unsigned long platform_physmem(void) { unsigned long physmem; size_t len = sizeof(physmem); static int mib[2] = {CTL_HW, HW_PHYSMEM}; if (sysctl(mib, 2, &physmem, &len, NULL, 0) < 0) { fprintf(stderr, _("%s: can't determine memory size\n"), progname); exit(1); } return physmem >> 10; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/defer_item.c0000644000000000000000000002661313033541503016231 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_alloc.h" #include "xfs_rmap.h" #include "xfs_refcount.h" #include "xfs_bmap.h" #include "xfs_inode.h" /* Dummy defer item ops, since we don't do logging. */ /* Extent Freeing */ /* Sort bmap items by AG. */ static int xfs_extent_free_diff_items( void *priv, struct list_head *a, struct list_head *b) { struct xfs_mount *mp = priv; struct xfs_extent_free_item *ra; struct xfs_extent_free_item *rb; ra = container_of(a, struct xfs_extent_free_item, xefi_list); rb = container_of(b, struct xfs_extent_free_item, xefi_list); return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) - XFS_FSB_TO_AGNO(mp, rb->xefi_startblock); } /* Get an EFI. */ STATIC void * xfs_extent_free_create_intent( struct xfs_trans *tp, unsigned int count) { return NULL; } /* Log a free extent to the intent item. */ STATIC void xfs_extent_free_log_item( struct xfs_trans *tp, void *intent, struct list_head *item) { } /* Get an EFD so we can process all the free extents. */ STATIC void * xfs_extent_free_create_done( struct xfs_trans *tp, void *intent, unsigned int count) { return NULL; } /* Process a free extent. */ STATIC int xfs_extent_free_finish_item( struct xfs_trans *tp, struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) { struct xfs_extent_free_item *free; int error; free = container_of(item, struct xfs_extent_free_item, xefi_list); error = xfs_free_extent(tp, free->xefi_startblock, free->xefi_blockcount, &free->xefi_oinfo, XFS_AG_RESV_NONE); kmem_free(free); return error; } /* Abort all pending EFIs. */ STATIC void xfs_extent_free_abort_intent( void *intent) { } /* Cancel a free extent. */ STATIC void xfs_extent_free_cancel_item( struct list_head *item) { struct xfs_extent_free_item *free; free = container_of(item, struct xfs_extent_free_item, xefi_list); kmem_free(free); } static const struct xfs_defer_op_type xfs_extent_free_defer_type = { .type = XFS_DEFER_OPS_TYPE_FREE, .diff_items = xfs_extent_free_diff_items, .create_intent = xfs_extent_free_create_intent, .abort_intent = xfs_extent_free_abort_intent, .log_item = xfs_extent_free_log_item, .create_done = xfs_extent_free_create_done, .finish_item = xfs_extent_free_finish_item, .cancel_item = xfs_extent_free_cancel_item, }; /* Register the deferred op type. */ void xfs_extent_free_init_defer_op(void) { xfs_defer_init_op_type(&xfs_extent_free_defer_type); } /* Reverse Mapping */ /* Sort rmap intents by AG. */ static int xfs_rmap_update_diff_items( void *priv, struct list_head *a, struct list_head *b) { struct xfs_mount *mp = priv; struct xfs_rmap_intent *ra; struct xfs_rmap_intent *rb; ra = container_of(a, struct xfs_rmap_intent, ri_list); rb = container_of(b, struct xfs_rmap_intent, ri_list); return XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) - XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock); } /* Get an RUI. */ STATIC void * xfs_rmap_update_create_intent( struct xfs_trans *tp, unsigned int count) { return NULL; } /* Log rmap updates in the intent item. */ STATIC void xfs_rmap_update_log_item( struct xfs_trans *tp, void *intent, struct list_head *item) { } /* Get an RUD so we can process all the deferred rmap updates. */ STATIC void * xfs_rmap_update_create_done( struct xfs_trans *tp, void *intent, unsigned int count) { return NULL; } /* Process a deferred rmap update. */ STATIC int xfs_rmap_update_finish_item( struct xfs_trans *tp, struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) { struct xfs_rmap_intent *rmap; int error; rmap = container_of(item, struct xfs_rmap_intent, ri_list); error = xfs_rmap_finish_one(tp, rmap->ri_type, rmap->ri_owner, rmap->ri_whichfork, rmap->ri_bmap.br_startoff, rmap->ri_bmap.br_startblock, rmap->ri_bmap.br_blockcount, rmap->ri_bmap.br_state, (struct xfs_btree_cur **)state); kmem_free(rmap); return error; } /* Clean up after processing deferred rmaps. */ STATIC void xfs_rmap_update_finish_cleanup( struct xfs_trans *tp, void *state, int error) { struct xfs_btree_cur *rcur = state; xfs_rmap_finish_one_cleanup(tp, rcur, error); } /* Abort all pending RUIs. */ STATIC void xfs_rmap_update_abort_intent( void *intent) { } /* Cancel a deferred rmap update. */ STATIC void xfs_rmap_update_cancel_item( struct list_head *item) { struct xfs_rmap_intent *rmap; rmap = container_of(item, struct xfs_rmap_intent, ri_list); kmem_free(rmap); } static const struct xfs_defer_op_type xfs_rmap_update_defer_type = { .type = XFS_DEFER_OPS_TYPE_RMAP, .diff_items = xfs_rmap_update_diff_items, .create_intent = xfs_rmap_update_create_intent, .abort_intent = xfs_rmap_update_abort_intent, .log_item = xfs_rmap_update_log_item, .create_done = xfs_rmap_update_create_done, .finish_item = xfs_rmap_update_finish_item, .finish_cleanup = xfs_rmap_update_finish_cleanup, .cancel_item = xfs_rmap_update_cancel_item, }; /* Register the deferred op type. */ void xfs_rmap_update_init_defer_op(void) { xfs_defer_init_op_type(&xfs_rmap_update_defer_type); } /* Reference Counting */ /* Sort refcount intents by AG. */ static int xfs_refcount_update_diff_items( void *priv, struct list_head *a, struct list_head *b) { struct xfs_mount *mp = priv; struct xfs_refcount_intent *ra; struct xfs_refcount_intent *rb; ra = container_of(a, struct xfs_refcount_intent, ri_list); rb = container_of(b, struct xfs_refcount_intent, ri_list); return XFS_FSB_TO_AGNO(mp, ra->ri_startblock) - XFS_FSB_TO_AGNO(mp, rb->ri_startblock); } /* Get an CUI. */ STATIC void * xfs_refcount_update_create_intent( struct xfs_trans *tp, unsigned int count) { return NULL; } /* Log refcount updates in the intent item. */ STATIC void xfs_refcount_update_log_item( struct xfs_trans *tp, void *intent, struct list_head *item) { } /* Get an CUD so we can process all the deferred refcount updates. */ STATIC void * xfs_refcount_update_create_done( struct xfs_trans *tp, void *intent, unsigned int count) { return NULL; } /* Process a deferred refcount update. */ STATIC int xfs_refcount_update_finish_item( struct xfs_trans *tp, struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) { struct xfs_refcount_intent *refc; xfs_fsblock_t new_fsb; xfs_extlen_t new_aglen; int error; refc = container_of(item, struct xfs_refcount_intent, ri_list); error = xfs_refcount_finish_one(tp, dop, refc->ri_type, refc->ri_startblock, refc->ri_blockcount, &new_fsb, &new_aglen, (struct xfs_btree_cur **)state); /* Did we run out of reservation? Requeue what we didn't finish. */ if (!error && new_aglen > 0) { ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE || refc->ri_type == XFS_REFCOUNT_DECREASE); refc->ri_startblock = new_fsb; refc->ri_blockcount = new_aglen; return -EAGAIN; } kmem_free(refc); return error; } /* Clean up after processing deferred refcounts. */ STATIC void xfs_refcount_update_finish_cleanup( struct xfs_trans *tp, void *state, int error) { struct xfs_btree_cur *rcur = state; xfs_refcount_finish_one_cleanup(tp, rcur, error); } /* Abort all pending CUIs. */ STATIC void xfs_refcount_update_abort_intent( void *intent) { } /* Cancel a deferred refcount update. */ STATIC void xfs_refcount_update_cancel_item( struct list_head *item) { struct xfs_refcount_intent *refc; refc = container_of(item, struct xfs_refcount_intent, ri_list); kmem_free(refc); } static const struct xfs_defer_op_type xfs_refcount_update_defer_type = { .type = XFS_DEFER_OPS_TYPE_REFCOUNT, .diff_items = xfs_refcount_update_diff_items, .create_intent = xfs_refcount_update_create_intent, .abort_intent = xfs_refcount_update_abort_intent, .log_item = xfs_refcount_update_log_item, .create_done = xfs_refcount_update_create_done, .finish_item = xfs_refcount_update_finish_item, .finish_cleanup = xfs_refcount_update_finish_cleanup, .cancel_item = xfs_refcount_update_cancel_item, }; /* Register the deferred op type. */ void xfs_refcount_update_init_defer_op(void) { xfs_defer_init_op_type(&xfs_refcount_update_defer_type); } /* Inode Block Mapping */ /* Sort bmap intents by inode. */ static int xfs_bmap_update_diff_items( void *priv, struct list_head *a, struct list_head *b) { struct xfs_bmap_intent *ba; struct xfs_bmap_intent *bb; ba = container_of(a, struct xfs_bmap_intent, bi_list); bb = container_of(b, struct xfs_bmap_intent, bi_list); return ba->bi_owner->i_ino - bb->bi_owner->i_ino; } /* Get an BUI. */ STATIC void * xfs_bmap_update_create_intent( struct xfs_trans *tp, unsigned int count) { return NULL; } /* Log bmap updates in the intent item. */ STATIC void xfs_bmap_update_log_item( struct xfs_trans *tp, void *intent, struct list_head *item) { } /* Get an BUD so we can process all the deferred rmap updates. */ STATIC void * xfs_bmap_update_create_done( struct xfs_trans *tp, void *intent, unsigned int count) { return NULL; } /* Process a deferred rmap update. */ STATIC int xfs_bmap_update_finish_item( struct xfs_trans *tp, struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) { struct xfs_bmap_intent *bmap; int error; bmap = container_of(item, struct xfs_bmap_intent, bi_list); error = xfs_bmap_finish_one(tp, dop, bmap->bi_owner, bmap->bi_type, bmap->bi_whichfork, bmap->bi_bmap.br_startoff, bmap->bi_bmap.br_startblock, bmap->bi_bmap.br_blockcount, bmap->bi_bmap.br_state); kmem_free(bmap); return error; } /* Abort all pending BUIs. */ STATIC void xfs_bmap_update_abort_intent( void *intent) { } /* Cancel a deferred rmap update. */ STATIC void xfs_bmap_update_cancel_item( struct list_head *item) { struct xfs_bmap_intent *bmap; bmap = container_of(item, struct xfs_bmap_intent, bi_list); kmem_free(bmap); } static const struct xfs_defer_op_type xfs_bmap_update_defer_type = { .type = XFS_DEFER_OPS_TYPE_BMAP, .diff_items = xfs_bmap_update_diff_items, .create_intent = xfs_bmap_update_create_intent, .abort_intent = xfs_bmap_update_abort_intent, .log_item = xfs_bmap_update_log_item, .create_done = xfs_bmap_update_create_done, .finish_item = xfs_bmap_update_finish_item, .cancel_item = xfs_bmap_update_cancel_item, }; /* Register the deferred op type. */ void xfs_bmap_update_init_defer_op(void) { xfs_defer_init_op_type(&xfs_bmap_update_defer_type); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/freebsd.c0000644000000000000000000001007613063067171015543 0ustar /* * Copyright (c) 2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include #include #include #include int platform_has_uuid = 1; extern char *progname; int platform_check_ismounted(char *name, char *block, struct stat *s, int verbose) { struct stat st; int cnt, i; struct statfs *fsinfo; if (!s) { if (stat(block, &st) < 0) return 0; s = &st; } /* Remember, FreeBSD can now mount char devices! -- adrian */ if (((st.st_mode & S_IFMT) != S_IFBLK) && ((st.st_mode & S_IFMT) != S_IFCHR)) return 0; if ((cnt = getmntinfo(&fsinfo, MNT_NOWAIT)) == 0) { fprintf(stderr, _("%s: %s possibly contains a mounted filesystem\n"), progname, name); return 1; } for (i = 0; i < cnt; i++) { if (strcmp (name, fsinfo[i].f_mntfromname) != 0) continue; if (verbose) fprintf(stderr, _("%s: %s contains a mounted filesystem\n"), progname, name); break; } return i < cnt; } int platform_check_iswritable(char *name, char *block, struct stat *s) { int cnt, i; struct statfs *fsinfo; if ((cnt = getmntinfo(&fsinfo, MNT_NOWAIT)) == 0) { fprintf(stderr, _("%s: %s contains a possibly writable, " "mounted filesystem\n"), progname, name); return 1; } for (i = 0; i < cnt; i++) { if (strcmp (name, fsinfo[i].f_mntfromname) != 0) continue; if (fsinfo[i].f_flags &= MNT_RDONLY) break; } if (i == cnt) { fprintf(stderr, _("%s: %s contains a mounted and writable " "filesystem\n"), progname, name); return 1; } return 0; } int platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fatal) { return fatal; } void platform_flush_device(int fd, dev_t device) { return; } void platform_findsizes(char *path, int fd, long long *sz, int *bsz) { struct stat st; __int64_t size; u_int ssize; if (fstat(fd, &st) < 0) { fprintf(stderr, _("%s: " "cannot stat the device file \"%s\": %s\n"), progname, path, strerror(errno)); exit(1); } if ((st.st_mode & S_IFMT) == S_IFREG) { *sz = (long long)(st.st_size >> 9); *bsz = 512; return; } if ((st.st_mode & S_IFMT) != S_IFCHR) { fprintf(stderr, _("%s: Not a device or file: \"%s\"\n"), progname, path); exit(1); } if (ioctl(fd, DIOCGMEDIASIZE, &size) != 0) { fprintf(stderr, _("%s: DIOCGMEDIASIZE failed on \"%s\": %s\n"), progname, path, strerror(errno)); exit(1); } if (ioctl(fd, DIOCGSECTORSIZE, &ssize) != 0) { fprintf(stderr, _("%s: " "DIOCGSECTORSIZE failed on \"%s\": %s\n"), progname, path, strerror(errno)); exit(1); } *sz = (long long) (size / ssize); *bsz = (int)ssize; } char * platform_findrawpath(char *path) { return path; } char * platform_findblockpath(char *path) { return path; } int platform_direct_blockdev(void) { return 0; } int platform_align_blockdev(void) { return sizeof(void *); } int platform_nproc(void) { int ncpu; size_t len = sizeof(ncpu); static int mib[2] = {CTL_HW, HW_NCPU}; if (sysctl(mib, 2, &ncpu, &len, NULL, 0) < 0) ncpu = 1; return ncpu; } unsigned long platform_physmem(void) { unsigned long physmem; size_t len = sizeof(physmem); static int mib[2] = {CTL_HW, HW_PHYSMEM}; if (sysctl(mib, 2, &physmem, &len, NULL, 0) < 0) { fprintf(stderr, _("%s: can't determine memory size\n"), progname); exit(1); } return physmem >> 10; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/gen_crc32table.c0000644000000000000000000000632013063067171016703 0ustar #include #include "crc32defs.h" #include #define ENTRIES_PER_LINE 4 #if CRC_LE_BITS > 8 # define LE_TABLE_ROWS (CRC_LE_BITS/8) # define LE_TABLE_SIZE 256 #else # define LE_TABLE_ROWS 1 # define LE_TABLE_SIZE (1 << CRC_LE_BITS) #endif #if CRC_BE_BITS > 8 # define BE_TABLE_ROWS (CRC_BE_BITS/8) # define BE_TABLE_SIZE 256 #else # define BE_TABLE_ROWS 1 # define BE_TABLE_SIZE (1 << CRC_BE_BITS) #endif static uint32_t crc32table_le[LE_TABLE_ROWS][256]; static uint32_t crc32ctable_le[LE_TABLE_ROWS][256]; /* * big endian ordered CRC not used by XFS. static uint32_t crc32table_be[BE_TABLE_ROWS][256]; */ /** * crc32init_le() - allocate and initialize LE table data * * crc is the crc of the byte i; other entries are filled in based on the * fact that crctable[i^j] = crctable[i] ^ crctable[j]. * */ static void crc32init_le_generic(const uint32_t polynomial, uint32_t (*tab)[256]) { unsigned i, j; uint32_t crc = 1; tab[0][0] = 0; for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) { crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0); for (j = 0; j < LE_TABLE_SIZE; j += 2 * i) tab[0][i + j] = crc ^ tab[0][j]; } for (i = 0; i < LE_TABLE_SIZE; i++) { crc = tab[0][i]; for (j = 1; j < LE_TABLE_ROWS; j++) { crc = tab[0][crc & 0xff] ^ (crc >> 8); tab[j][i] = crc; } } } static void crc32init_le(void) { crc32init_le_generic(CRCPOLY_LE, crc32table_le); } static void crc32cinit_le(void) { crc32init_le_generic(CRC32C_POLY_LE, crc32ctable_le); } /** * crc32init_be() - allocate and initialize BE table data */ #if 0 /* not used */ static void crc32init_be(void) { unsigned i, j; uint32_t crc = 0x80000000; crc32table_be[0][0] = 0; for (i = 1; i < BE_TABLE_SIZE; i <<= 1) { crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0); for (j = 0; j < i; j++) crc32table_be[0][i + j] = crc ^ crc32table_be[0][j]; } for (i = 0; i < BE_TABLE_SIZE; i++) { crc = crc32table_be[0][i]; for (j = 1; j < BE_TABLE_ROWS; j++) { crc = crc32table_be[0][(crc >> 24) & 0xff] ^ (crc << 8); crc32table_be[j][i] = crc; } } } #endif static void output_table(uint32_t (*table)[256], int rows, int len, char *trans) { int i, j; for (j = 0 ; j < rows; j++) { printf("{"); for (i = 0; i < len - 1; i++) { if (i % ENTRIES_PER_LINE == 0) printf("\n"); printf("%s(0x%8.8xL), ", trans, table[j][i]); } printf("%s(0x%8.8xL)},\n", trans, table[j][len - 1]); } } int main(int argc, char** argv) { printf("/* this file is generated - do not edit */\n\n"); if (CRC_LE_BITS > 1) { crc32init_le(); printf("static u32 crc32table_le[%d][%d] = {", LE_TABLE_ROWS, LE_TABLE_SIZE); output_table(crc32table_le, LE_TABLE_ROWS, LE_TABLE_SIZE, "tole"); printf("};\n"); } #if 0 /* not used by xfsprogs */ if (CRC_BE_BITS > 1) { crc32init_be(); printf("static u32 crc32table_be[%d][%d] = {", BE_TABLE_ROWS, BE_TABLE_SIZE); output_table(crc32table_be, LE_TABLE_ROWS, BE_TABLE_SIZE, "tobe"); printf("};\n"); } #endif if (CRC_LE_BITS > 1) { crc32cinit_le(); printf("static u32 crc32ctable_le[%d][%d] = {", LE_TABLE_ROWS, LE_TABLE_SIZE); output_table(crc32ctable_le, LE_TABLE_ROWS, LE_TABLE_SIZE, "tole"); printf("};\n"); } return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/init.c0000644000000000000000000005327713063067171015106 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "init.h" #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_rmap_btree.h" #include "xfs_refcount_btree.h" #include "libxfs.h" /* for now */ char *progname = "libxfs"; /* default, changed by each tool */ struct cache *libxfs_bcache; /* global buffer cache */ int libxfs_bhash_size; /* #buckets in bcache */ int use_xfs_buf_lock; /* global flag: use xfs_buf_t locks for MT */ static void manage_zones(int); /* setup global zones */ kmem_zone_t *xfs_inode_zone; /* * dev_map - map open devices to fd. */ #define MAX_DEVS 10 /* arbitary maximum */ int nextfakedev = -1; /* device number to give to next fake device */ static struct dev_to_fd { dev_t dev; int fd; } dev_map[MAX_DEVS]={{0}}; /* * Checks whether a given device has a mounted, writable * filesystem, returns 1 if it does & fatal (just warns * if not fatal, but allows us to proceed). * * Useful to tools which will produce uncertain results * if the filesystem is active - repair, check, logprint. */ static int check_isactive(char *name, char *block, int fatal) { struct stat st; if (stat(block, &st) < 0) return 0; if ((st.st_mode & S_IFMT) != S_IFBLK) return 0; if (platform_check_ismounted(name, block, &st, 0) == 0) return 0; if (platform_check_iswritable(name, block, &st)) return fatal ? 1 : 0; return 0; } /* libxfs_device_to_fd: * lookup a device number in the device map * return the associated fd */ int libxfs_device_to_fd(dev_t device) { int d; for (d = 0; d < MAX_DEVS; d++) if (dev_map[d].dev == device) return dev_map[d].fd; fprintf(stderr, _("%s: %s: device %lld is not open\n"), progname, __FUNCTION__, (long long)device); exit(1); /* NOTREACHED */ } /* libxfs_device_open: * open a device and return its device number */ dev_t libxfs_device_open(char *path, int creat, int xflags, int setblksize) { dev_t dev; int fd, d, flags; int readonly, dio, excl; struct stat statb; readonly = (xflags & LIBXFS_ISREADONLY); excl = (xflags & LIBXFS_EXCLUSIVELY) && !creat; dio = (xflags & LIBXFS_DIRECT) && !creat && platform_direct_blockdev(); retry: flags = (readonly ? O_RDONLY : O_RDWR) | \ (creat ? (O_CREAT|O_TRUNC) : 0) | \ (dio ? O_DIRECT : 0) | \ (excl ? O_EXCL : 0); if ((fd = open(path, flags, 0666)) < 0) { if (errno == EINVAL && --dio == 0) goto retry; fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); exit(1); } if (fstat(fd, &statb) < 0) { fprintf(stderr, _("%s: cannot stat %s: %s\n"), progname, path, strerror(errno)); exit(1); } if (!readonly && setblksize && (statb.st_mode & S_IFMT) == S_IFBLK) { if (setblksize == 1) /* use the default blocksize */ (void)platform_set_blocksize(fd, path, statb.st_rdev, XFS_MIN_SECTORSIZE, 0); else { /* given an explicit blocksize to use */ if (platform_set_blocksize(fd, path, statb.st_rdev, setblksize, 1)) exit(1); } } /* * Get the device number from the stat buf - unless * we're not opening a real device, in which case * choose a new fake device number. */ dev = (statb.st_rdev) ? (statb.st_rdev) : (nextfakedev--); for (d = 0; d < MAX_DEVS; d++) if (dev_map[d].dev == dev) { fprintf(stderr, _("%s: device %lld is already open\n"), progname, (long long)dev); exit(1); } for (d = 0; d < MAX_DEVS; d++) if (!dev_map[d].dev) { dev_map[d].dev = dev; dev_map[d].fd = fd; return dev; } fprintf(stderr, _("%s: %s: too many open devices\n"), progname, __FUNCTION__); exit(1); /* NOTREACHED */ } void libxfs_device_close(dev_t dev) { int d; for (d = 0; d < MAX_DEVS; d++) if (dev_map[d].dev == dev) { int fd; fd = dev_map[d].fd; dev_map[d].dev = dev_map[d].fd = 0; fsync(fd); platform_flush_device(fd, dev); close(fd); return; } fprintf(stderr, _("%s: %s: device %lld is not open\n"), progname, __FUNCTION__, (long long)dev); exit(1); } static int check_open(char *path, int flags, char **rawfile, char **blockfile) { int readonly = (flags & LIBXFS_ISREADONLY); int inactive = (flags & LIBXFS_ISINACTIVE); int dangerously = (flags & LIBXFS_DANGEROUSLY); struct stat stbuf; if (stat(path, &stbuf) < 0) { perror(path); return 0; } if (!(*rawfile = platform_findrawpath(path))) { fprintf(stderr, _("%s: " "can't find a character device matching %s\n"), progname, path); return 0; } if (!(*blockfile = platform_findblockpath(path))) { fprintf(stderr, _("%s: " "can't find a block device matching %s\n"), progname, path); return 0; } if (!readonly && !inactive && platform_check_ismounted(path, *blockfile, NULL, 1)) return 0; if (inactive && check_isactive(path, *blockfile, ((readonly|dangerously)?1:0))) return 0; return 1; } /* * libxfs initialization. * Caller gets a 0 on failure (and we print a message), 1 on success. */ int libxfs_init(libxfs_init_t *a) { char *blockfile; char curdir[MAXPATHLEN]; char *dname; char dpath[25]; int fd; char *logname; char logpath[25]; int needcd; char *rawfile; char *rtname; char rtpath[25]; int rval = 0; int flags; dpath[0] = logpath[0] = rtpath[0] = '\0'; dname = a->dname; logname = a->logname; rtname = a->rtname; a->dfd = a->logfd = a->rtfd = -1; a->ddev = a->logdev = a->rtdev = 0; a->dsize = a->lbsize = a->rtbsize = 0; a->dbsize = a->logBBsize = a->logBBstart = a->rtsize = 0; (void)getcwd(curdir,MAXPATHLEN); needcd = 0; fd = -1; flags = (a->isreadonly | a->isdirect); xfs_extent_free_init_defer_op(); xfs_rmap_update_init_defer_op(); xfs_refcount_update_init_defer_op(); xfs_bmap_update_init_defer_op(); radix_tree_init(); if (a->volname) { if(!check_open(a->volname,flags,&rawfile,&blockfile)) goto done; needcd = 1; fd = open(rawfile, O_RDONLY); dname = a->dname = a->volname; a->volname = NULL; } if (dname) { if (dname[0] != '/' && needcd) chdir(curdir); if (a->disfile) { a->ddev= libxfs_device_open(dname, a->dcreat, flags, a->setblksize); a->dfd = libxfs_device_to_fd(a->ddev); platform_findsizes(dname, a->dfd, &a->dsize, &a->dbsize); } else { if (!check_open(dname, flags, &rawfile, &blockfile)) goto done; a->ddev = libxfs_device_open(rawfile, a->dcreat, flags, a->setblksize); a->dfd = libxfs_device_to_fd(a->ddev); platform_findsizes(rawfile, a->dfd, &a->dsize, &a->dbsize); } needcd = 1; } else a->dsize = 0; if (logname) { if (logname[0] != '/' && needcd) chdir(curdir); if (a->lisfile) { a->logdev = libxfs_device_open(logname, a->lcreat, flags, a->setblksize); a->logfd = libxfs_device_to_fd(a->logdev); platform_findsizes(dname, a->logfd, &a->logBBsize, &a->lbsize); } else { if (!check_open(logname, flags, &rawfile, &blockfile)) goto done; a->logdev = libxfs_device_open(rawfile, a->lcreat, flags, a->setblksize); a->logfd = libxfs_device_to_fd(a->logdev); platform_findsizes(rawfile, a->logfd, &a->logBBsize, &a->lbsize); } needcd = 1; } else a->logBBsize = 0; if (rtname) { if (rtname[0] != '/' && needcd) chdir(curdir); if (a->risfile) { a->rtdev = libxfs_device_open(rtname, a->rcreat, flags, a->setblksize); a->rtfd = libxfs_device_to_fd(a->rtdev); platform_findsizes(dname, a->rtfd, &a->rtsize, &a->rtbsize); } else { if (!check_open(rtname, flags, &rawfile, &blockfile)) goto done; a->rtdev = libxfs_device_open(rawfile, a->rcreat, flags, a->setblksize); a->rtfd = libxfs_device_to_fd(a->rtdev); platform_findsizes(rawfile, a->rtfd, &a->rtsize, &a->rtbsize); } needcd = 1; } else a->rtsize = 0; if (a->dsize < 0) { fprintf(stderr, _("%s: can't get size for data subvolume\n"), progname); goto done; } if (a->logBBsize < 0) { fprintf(stderr, _("%s: can't get size for log subvolume\n"), progname); goto done; } if (a->rtsize < 0) { fprintf(stderr, _("%s: can't get size for realtime subvolume\n"), progname); goto done; } if (needcd) chdir(curdir); if (!libxfs_bhash_size) libxfs_bhash_size = LIBXFS_BHASHSIZE(sbp); libxfs_bcache = cache_init(a->bcache_flags, libxfs_bhash_size, &libxfs_bcache_operations); use_xfs_buf_lock = a->usebuflock; manage_zones(0); rval = 1; done: if (dpath[0]) unlink(dpath); if (logpath[0]) unlink(logpath); if (rtpath[0]) unlink(rtpath); if (fd >= 0) close(fd); if (!rval && a->ddev) libxfs_device_close(a->ddev); if (!rval && a->logdev) libxfs_device_close(a->logdev); if (!rval && a->rtdev) libxfs_device_close(a->rtdev); return rval; } /* * Initialize/destroy all of the zone allocators we use. */ static void manage_zones(int release) { extern kmem_zone_t *xfs_buf_zone; extern kmem_zone_t *xfs_ili_zone; extern kmem_zone_t *xfs_ifork_zone; extern kmem_zone_t *xfs_buf_item_zone; extern kmem_zone_t *xfs_da_state_zone; extern kmem_zone_t *xfs_btree_cur_zone; extern kmem_zone_t *xfs_bmap_free_item_zone; extern kmem_zone_t *xfs_log_item_desc_zone; extern void xfs_dir_startup(); if (release) { /* free zone allocation */ kmem_free(xfs_buf_zone); kmem_free(xfs_inode_zone); kmem_free(xfs_ifork_zone); kmem_free(xfs_buf_item_zone); kmem_free(xfs_da_state_zone); kmem_free(xfs_btree_cur_zone); kmem_free(xfs_bmap_free_item_zone); kmem_free(xfs_log_item_desc_zone); return; } /* otherwise initialise zone allocation */ xfs_buf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buffer"); xfs_inode_zone = kmem_zone_init(sizeof(struct xfs_inode), "xfs_inode"); xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork"); xfs_ili_zone = kmem_zone_init( sizeof(xfs_inode_log_item_t), "xfs_inode_log_item"); xfs_buf_item_zone = kmem_zone_init( sizeof(xfs_buf_log_item_t), "xfs_buf_log_item"); xfs_da_state_zone = kmem_zone_init( sizeof(xfs_da_state_t), "xfs_da_state"); xfs_btree_cur_zone = kmem_zone_init( sizeof(xfs_btree_cur_t), "xfs_btree_cur"); xfs_bmap_free_item_zone = kmem_zone_init( sizeof(struct xfs_extent_free_item), "xfs_bmap_free_item"); xfs_log_item_desc_zone = kmem_zone_init( sizeof(struct xfs_log_item_desc), "xfs_log_item_desc"); xfs_dir_startup(); } /* * Initialize realtime fields in the mount structure. */ static int rtmount_init( xfs_mount_t *mp, /* file system mount structure */ int flags) { xfs_buf_t *bp; /* buffer for last block of subvolume */ xfs_daddr_t d; /* address of last block of subvolume */ xfs_sb_t *sbp; /* filesystem superblock copy in mount */ sbp = &mp->m_sb; if (sbp->sb_rblocks == 0) return 0; if (mp->m_rtdev_targp->dev == 0 && !(flags & LIBXFS_MOUNT_DEBUGGER)) { fprintf(stderr, _("%s: filesystem has a realtime subvolume\n"), progname); return -1; } mp->m_rsumlevels = sbp->sb_rextslog + 1; mp->m_rsumsize = (uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels * sbp->sb_rbmblocks; mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize); mp->m_rbmip = mp->m_rsumip = NULL; /* * Allow debugger to be run without the realtime device present. */ if (flags & LIBXFS_MOUNT_DEBUGGER) return 0; /* * Check that the realtime section is an ok size. */ d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) { fprintf(stderr, _("%s: realtime init - %llu != %llu\n"), progname, (unsigned long long) XFS_BB_TO_FSB(mp, d), (unsigned long long) mp->m_sb.sb_rblocks); return -1; } bp = libxfs_readbuf(mp->m_rtdev, d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_BB(mp, 1), 0, NULL); if (bp == NULL) { fprintf(stderr, _("%s: realtime size check failed\n"), progname); return -1; } libxfs_putbuf(bp); return 0; } static int libxfs_initialize_perag( xfs_mount_t *mp, xfs_agnumber_t agcount, xfs_agnumber_t *maxagi) { xfs_agnumber_t index, max_metadata; xfs_agnumber_t first_initialised = 0; xfs_perag_t *pag; xfs_agino_t agino; xfs_ino_t ino; xfs_sb_t *sbp = &mp->m_sb; int error = -ENOMEM; /* * Walk the current per-ag tree so we don't try to initialise AGs * that already exist (growfs case). Allocate and insert all the * AGs we don't find ready for initialisation. */ for (index = 0; index < agcount; index++) { pag = xfs_perag_get(mp, index); if (pag) { xfs_perag_put(pag); continue; } if (!first_initialised) first_initialised = index; pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL); if (!pag) goto out_unwind; pag->pag_agno = index; pag->pag_mount = mp; if (radix_tree_insert(&mp->m_perag_tree, index, pag)) { error = -EEXIST; goto out_unwind; } } /* * If we mount with the inode64 option, or no inode overflows * the legacy 32-bit address space clear the inode32 option. */ agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0); ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino); if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32) mp->m_flags |= XFS_MOUNT_32BITINODES; else mp->m_flags &= ~XFS_MOUNT_32BITINODES; if (mp->m_flags & XFS_MOUNT_32BITINODES) { /* * Calculate how much should be reserved for inodes to meet * the max inode percentage. */ if (mp->m_maxicount) { __uint64_t icount; icount = sbp->sb_dblocks * sbp->sb_imax_pct; do_div(icount, 100); icount += sbp->sb_agblocks - 1; do_div(icount, sbp->sb_agblocks); max_metadata = icount; } else { max_metadata = agcount; } for (index = 0; index < agcount; index++) { ino = XFS_AGINO_TO_INO(mp, index, agino); if (ino > XFS_MAXINUMBER_32) { index++; break; } pag = xfs_perag_get(mp, index); pag->pagi_inodeok = 1; if (index < max_metadata) pag->pagf_metadata = 1; xfs_perag_put(pag); } } else { for (index = 0; index < agcount; index++) { pag = xfs_perag_get(mp, index); pag->pagi_inodeok = 1; xfs_perag_put(pag); } } if (maxagi) *maxagi = index; mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp); return 0; out_unwind: kmem_free(pag); for (; index > first_initialised; index--) { pag = radix_tree_delete(&mp->m_perag_tree, index); kmem_free(pag); } return error; } static struct xfs_buftarg * libxfs_buftarg_alloc( struct xfs_mount *mp, dev_t dev) { struct xfs_buftarg *btp; btp = malloc(sizeof(*btp)); if (!btp) { fprintf(stderr, _("%s: buftarg init failed\n"), progname); exit(1); } btp->bt_mount = mp; btp->dev = dev; return btp; } void libxfs_buftarg_init( struct xfs_mount *mp, dev_t dev, dev_t logdev, dev_t rtdev) { if (mp->m_ddev_targp) { /* should already have all buftargs initialised */ if (mp->m_ddev_targp->dev != dev || mp->m_ddev_targp->bt_mount != mp) { fprintf(stderr, _("%s: bad buftarg reinit, ddev\n"), progname); exit(1); } if (!logdev || logdev == dev) { if (mp->m_logdev_targp != mp->m_ddev_targp) { fprintf(stderr, _("%s: bad buftarg reinit, ldev mismatch\n"), progname); exit(1); } } else if (mp->m_logdev_targp->dev != logdev || mp->m_logdev_targp->bt_mount != mp) { fprintf(stderr, _("%s: bad buftarg reinit, logdev\n"), progname); exit(1); } if (rtdev && (mp->m_rtdev_targp->dev != rtdev || mp->m_rtdev_targp->bt_mount != mp)) { fprintf(stderr, _("%s: bad buftarg reinit, rtdev\n"), progname); exit(1); } return; } mp->m_ddev_targp = libxfs_buftarg_alloc(mp, dev); if (!logdev || logdev == dev) mp->m_logdev_targp = mp->m_ddev_targp; else mp->m_logdev_targp = libxfs_buftarg_alloc(mp, logdev); mp->m_rtdev_targp = libxfs_buftarg_alloc(mp, rtdev); } /* * Mount structure initialization, provides a filled-in xfs_mount_t * such that the numerous XFS_* macros can be used. If dev is zero, * no IO will be performed (no size checks, read root inodes). */ xfs_mount_t * libxfs_mount( xfs_mount_t *mp, xfs_sb_t *sb, dev_t dev, dev_t logdev, dev_t rtdev, int flags) { xfs_daddr_t d; xfs_buf_t *bp; xfs_sb_t *sbp; int error; libxfs_buftarg_init(mp, dev, logdev, rtdev); mp->m_flags = (LIBXFS_MOUNT_32BITINODES|LIBXFS_MOUNT_32BITINOOPT); mp->m_sb = *sb; INIT_RADIX_TREE(&mp->m_perag_tree, GFP_KERNEL); sbp = &(mp->m_sb); xfs_sb_mount_common(mp, sb); xfs_alloc_compute_maxlevels(mp); xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); xfs_ialloc_compute_maxlevels(mp); xfs_rmapbt_compute_maxlevels(mp); xfs_refcountbt_compute_maxlevels(mp); if (sbp->sb_imax_pct) { /* Make sure the maximum inode count is a multiple of the * units we allocate inodes in. */ mp->m_maxicount = (sbp->sb_dblocks * sbp->sb_imax_pct) / 100; mp->m_maxicount = ((mp->m_maxicount / mp->m_ialloc_blks) * mp->m_ialloc_blks) << sbp->sb_inopblog; } else mp->m_maxicount = 0; mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; /* * Set whether we're using stripe alignment. */ if (xfs_sb_version_hasdalign(&mp->m_sb)) { mp->m_dalign = sbp->sb_unit; mp->m_swidth = sbp->sb_width; } /* * Set whether we're using inode alignment. */ if (xfs_sb_version_hasalign(&mp->m_sb) && mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1; else mp->m_inoalign_mask = 0; /* * If we are using stripe alignment, check whether * the stripe unit is a multiple of the inode alignment */ if (mp->m_dalign && mp->m_inoalign_mask && !(mp->m_dalign & mp->m_inoalign_mask)) mp->m_sinoalign = mp->m_dalign; else mp->m_sinoalign = 0; /* * Check that the data (and log if separate) are an ok size. */ d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { fprintf(stderr, _("%s: size check failed\n"), progname); if (!(flags & LIBXFS_MOUNT_DEBUGGER)) return NULL; } /* * We automatically convert v1 inodes to v2 inodes now, so if * the NLINK bit is not set we can't operate on the filesystem. */ if (!(sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)) { fprintf(stderr, _( "%s: V1 inodes unsupported. Please try an older xfsprogs.\n"), progname); exit(1); } /* Check for supported directory formats */ if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) { fprintf(stderr, _( "%s: V1 directories unsupported. Please try an older xfsprogs.\n"), progname); exit(1); } /* check for unsupported other features */ if (!xfs_sb_good_version(sbp)) { fprintf(stderr, _( "%s: Unsupported features detected. Please try a newer xfsprogs.\n"), progname); exit(1); } xfs_da_mount(mp); if (xfs_sb_version_hasattr2(&mp->m_sb)) mp->m_flags |= LIBXFS_MOUNT_ATTR2; /* Initialize the precomputed transaction reservations values */ xfs_trans_init(mp); if (dev == 0) /* maxtrres, we have no device so leave now */ return mp; bp = libxfs_readbuf(mp->m_dev, d - XFS_FSS_TO_BB(mp, 1), XFS_FSS_TO_BB(mp, 1), !(flags & LIBXFS_MOUNT_DEBUGGER), NULL); if (!bp) { fprintf(stderr, _("%s: data size check failed\n"), progname); if (!(flags & LIBXFS_MOUNT_DEBUGGER)) return NULL; } else libxfs_putbuf(bp); if (mp->m_logdev_targp->dev && mp->m_logdev_targp->dev != mp->m_ddev_targp->dev) { d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); if ( (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) || (!(bp = libxfs_readbuf(mp->m_logdev_targp, d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_BB(mp, 1), !(flags & LIBXFS_MOUNT_DEBUGGER), NULL))) ) { fprintf(stderr, _("%s: log size checks failed\n"), progname); if (!(flags & LIBXFS_MOUNT_DEBUGGER)) return NULL; } if (bp) libxfs_putbuf(bp); } /* Initialize realtime fields in the mount structure */ if (rtmount_init(mp, flags)) { fprintf(stderr, _("%s: realtime device init failed\n"), progname); return NULL; } error = libxfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); if (error) { fprintf(stderr, _("%s: perag init failed\n"), progname); exit(1); } return mp; } void libxfs_rtmount_destroy(xfs_mount_t *mp) { if (mp->m_rsumip) IRELE(mp->m_rsumip); if (mp->m_rbmip) IRELE(mp->m_rbmip); mp->m_rsumip = mp->m_rbmip = NULL; } /* * Release any resource obtained during a mount. */ void libxfs_umount(xfs_mount_t *mp) { struct xfs_perag *pag; int agno; libxfs_rtmount_destroy(mp); libxfs_bcache_purge(); for (agno = 0; agno < mp->m_maxagi; agno++) { pag = radix_tree_delete(&mp->m_perag_tree, agno); kmem_free(pag); } kmem_free(mp->m_attr_geo); kmem_free(mp->m_dir_geo); kmem_free(mp->m_rtdev_targp); if (mp->m_logdev_targp != mp->m_ddev_targp) kmem_free(mp->m_logdev_targp); kmem_free(mp->m_ddev_targp); } /* * Release any global resources used by libxfs. */ void libxfs_destroy(void) { manage_zones(1); cache_destroy(libxfs_bcache); } int libxfs_device_alignment(void) { return platform_align_blockdev(); } void libxfs_report(FILE *fp) { time_t t; char *c; cache_report(fp, "libxfs_bcache", libxfs_bcache); t = time(NULL); c = asctime(localtime(&t)); fprintf(fp, "%s", c); } int libxfs_nproc(void) { return platform_nproc(); } unsigned long libxfs_physmem(void) { return platform_physmem(); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/init.h0000644000000000000000000000267213063067171015104 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIBXFS_INIT_H #define LIBXFS_INIT_H struct stat; extern int platform_check_ismounted (char *path, char *block, struct stat *sptr, int verbose); extern int platform_check_iswritable (char *path, char *block, struct stat *sptr); extern int platform_set_blocksize (int fd, char *path, dev_t device, int bsz, int fatal); extern void platform_flush_device (int fd, dev_t device); extern char *platform_findrawpath(char *path); extern char *platform_findrawpath (char *path); extern char *platform_findblockpath (char *path); extern int platform_direct_blockdev (void); extern int platform_align_blockdev (void); extern unsigned long platform_physmem(void); /* in kilobytes */ extern int platform_has_uuid; #endif /* LIBXFS_INIT_H */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/irix.c0000644000000000000000000000422013063067171015076 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include int platform_has_uuid = 0; extern char *progname; extern __int64_t findsize(char *); int platform_check_ismounted(char *name, char *block, struct stat *s, int verbose) { return 0; } int platform_check_iswritable(char *name, char *block, struct stat *s) { return 1; } int platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fatal) { return fatal; } void platform_flush_device(int fd, dev_t device) { return; } void platform_findsizes(char *path, int fd, long long *sz, int *bsz) { struct stat st; if (fstat(fd, &st) < 0) { fprintf(stderr, _("%s: cannot stat the device file \"%s\": %s\n"), progname, path, strerror(errno)); exit(1); } if ((st.st_mode & S_IFMT) == S_IFREG) { *sz = (long long)(st.st_size >> 9); } else { *sz = findsize(path); } *bsz = BBSIZE; } char * platform_findrawpath(char *path) { return findrawpath(path); } char * platform_findblockpath(char *path) { return findblockpath(path); } int platform_direct_blockdev(void) { return 0; } int platform_align_blockdev(void) { return sizeof(void *); } int platform_nproc(void) { return sysmp(MP_NPROCS); } unsigned long platform_physmem(void) { struct rminfo ri; if (sysmp(MP_SAGET, MPSA_RMINFO, &ri, sizeof(ri)) < 0) fprintf(stderr, _("%s: can't determine memory size\n"), progname); exit(1); } return (ri.physmem >> 10) * getpagesize(); /* kilobytes */ } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/kmem.c0000644000000000000000000000270313063067170015057 0ustar #include "libxfs_priv.h" /* * Simple memory interface */ kmem_zone_t * kmem_zone_init(int size, char *name) { kmem_zone_t *ptr = malloc(sizeof(kmem_zone_t)); if (ptr == NULL) { fprintf(stderr, _("%s: zone init failed (%s, %d bytes): %s\n"), progname, name, (int)sizeof(kmem_zone_t), strerror(errno)); exit(1); } ptr->zone_unitsize = size; ptr->zone_name = name; ptr->allocated = 0; return ptr; } void * kmem_zone_alloc(kmem_zone_t *zone, int flags) { void *ptr = malloc(zone->zone_unitsize); if (ptr == NULL) { fprintf(stderr, _("%s: zone alloc failed (%s, %d bytes): %s\n"), progname, zone->zone_name, zone->zone_unitsize, strerror(errno)); exit(1); } zone->allocated++; return ptr; } void * kmem_zone_zalloc(kmem_zone_t *zone, int flags) { void *ptr = kmem_zone_alloc(zone, flags); memset(ptr, 0, zone->zone_unitsize); return ptr; } void * kmem_alloc(size_t size, int flags) { void *ptr = malloc(size); if (ptr == NULL) { fprintf(stderr, _("%s: malloc failed (%d bytes): %s\n"), progname, (int)size, strerror(errno)); exit(1); } return ptr; } void * kmem_zalloc(size_t size, int flags) { void *ptr = kmem_alloc(size, flags); memset(ptr, 0, size); return ptr; } void * kmem_realloc(void *ptr, size_t new_size, int flags) { ptr = realloc(ptr, new_size); if (ptr == NULL) { fprintf(stderr, _("%s: realloc failed (%d bytes): %s\n"), progname, (int)new_size, strerror(errno)); exit(1); } return ptr; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/libxfs_api_defs.h0000644000000000000000000001423013063067171017253 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LIBXFS_API_DEFS_H__ #define __LIBXFS_API_DEFS_H__ /* * This file defines all the kernel based functions we expose to userspace * via the libxfs_* namespace. This is kept in a separate header file so * it can be included in both the internal and external libxfs header files * without introducing any depenencies between the two. */ #define xfs_highbit32 libxfs_highbit32 #define xfs_highbit64 libxfs_highbit64 #define xfs_fs_repair_cmn_err libxfs_fs_repair_cmn_err #define xfs_fs_cmn_err libxfs_fs_cmn_err #define xfs_trans_alloc libxfs_trans_alloc #define xfs_trans_add_item libxfs_trans_add_item #define xfs_trans_bhold libxfs_trans_bhold #define xfs_trans_binval libxfs_trans_binval #define xfs_trans_bjoin libxfs_trans_bjoin #define xfs_trans_brelse libxfs_trans_brelse #define xfs_trans_commit libxfs_trans_commit #define xfs_trans_cancel libxfs_trans_cancel #define xfs_trans_del_item libxfs_trans_del_item #define xfs_trans_get_buf libxfs_trans_get_buf #define xfs_trans_getsb libxfs_trans_getsb #define xfs_trans_iget libxfs_trans_iget #define xfs_trans_ichgtime libxfs_trans_ichgtime #define xfs_trans_ijoin libxfs_trans_ijoin #define xfs_trans_ijoin_ref libxfs_trans_ijoin_ref #define xfs_trans_init libxfs_trans_init #define xfs_trans_inode_alloc_buf libxfs_trans_inode_alloc_buf #define xfs_trans_log_buf libxfs_trans_log_buf #define xfs_trans_log_inode libxfs_trans_log_inode #define xfs_trans_mod_sb libxfs_trans_mod_sb #define xfs_trans_read_buf libxfs_trans_read_buf #define xfs_trans_read_buf_map libxfs_trans_read_buf_map #define xfs_trans_roll libxfs_trans_roll #define xfs_trans_get_buf_map libxfs_trans_get_buf_map #define xfs_trans_resv_calc libxfs_trans_resv_calc #define xfs_attr_get libxfs_attr_get #define xfs_attr_set libxfs_attr_set #define xfs_attr_remove libxfs_attr_remove #define xfs_attr_leaf_newentsize libxfs_attr_leaf_newentsize #define xfs_alloc_fix_freelist libxfs_alloc_fix_freelist #define xfs_alloc_min_freelist libxfs_alloc_min_freelist #define xfs_alloc_read_agf libxfs_alloc_read_agf #define xfs_bmap_last_offset libxfs_bmap_last_offset #define xfs_bmap_search_extents libxfs_bmap_search_extents #define xfs_bmapi_write libxfs_bmapi_write #define xfs_bmapi_read libxfs_bmapi_read #define xfs_bunmapi libxfs_bunmapi #define xfs_bmbt_get_all libxfs_bmbt_get_all #define xfs_rtfree_extent libxfs_rtfree_extent #define xfs_zero_extent libxfs_zero_extent #define xfs_defer_init libxfs_defer_init #define xfs_defer_finish libxfs_defer_finish #define xfs_defer_cancel libxfs_defer_cancel #define xfs_da_brelse libxfs_da_brelse #define xfs_da_hashname libxfs_da_hashname #define xfs_da_shrink_inode libxfs_da_shrink_inode #define xfs_da_read_buf libxfs_da_read_buf #define xfs_dir_createname libxfs_dir_createname #define xfs_dir_init libxfs_dir_init #define xfs_dir_lookup libxfs_dir_lookup #define xfs_dir_replace libxfs_dir_replace #define xfs_dir2_isblock libxfs_dir2_isblock #define xfs_dir2_isleaf libxfs_dir2_isleaf #define __xfs_dir2_data_freescan libxfs_dir2_data_freescan #define xfs_dir2_data_log_entry libxfs_dir2_data_log_entry #define xfs_dir2_data_log_header libxfs_dir2_data_log_header #define xfs_dir2_data_make_free libxfs_dir2_data_make_free #define xfs_dir2_data_use_free libxfs_dir2_data_use_free #define xfs_dir2_shrink_inode libxfs_dir2_shrink_inode #define xfs_inode_from_disk libxfs_inode_from_disk #define xfs_inode_to_disk libxfs_inode_to_disk #define xfs_dinode_calc_crc libxfs_dinode_calc_crc #define xfs_idata_realloc libxfs_idata_realloc #define xfs_idestroy_fork libxfs_idestroy_fork #define xfs_rmap_ag_owner libxfs_rmap_ag_owner #define xfs_rmap_alloc libxfs_rmap_alloc #define xfs_rmap_query_range libxfs_rmap_query_range #define xfs_rmap_lookup_le libxfs_rmap_lookup_le #define xfs_rmap_get_rec libxfs_rmap_get_rec #define xfs_rmap_irec_offset_pack libxfs_rmap_irec_offset_pack #define xfs_rmap_irec_offset_unpack libxfs_rmap_irec_offset_unpack #define xfs_rmapbt_init_cursor libxfs_rmapbt_init_cursor #define xfs_btree_del_cursor libxfs_btree_del_cursor #define xfs_log_sb libxfs_log_sb #define xfs_sb_from_disk libxfs_sb_from_disk #define xfs_sb_quota_from_disk libxfs_sb_quota_from_disk #define xfs_sb_to_disk libxfs_sb_to_disk #define xfs_symlink_blocks libxfs_symlink_blocks #define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok #define xfs_verify_cksum libxfs_verify_cksum #define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable #define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs #define xfs_bmbt_maxrecs libxfs_bmbt_maxrecs #define xfs_bmdr_maxrecs libxfs_bmdr_maxrecs #define xfs_btree_init_block libxfs_btree_init_block #define xfs_dir_ino_validate libxfs_dir_ino_validate #define xfs_initialize_perag_data libxfs_initialize_perag_data #define xfs_inobt_maxrecs libxfs_inobt_maxrecs #define xfs_iread_extents libxfs_iread_extents #define xfs_log_calc_minimum_size libxfs_log_calc_minimum_size #define xfs_perag_get libxfs_perag_get #define xfs_perag_put libxfs_perag_put #define xfs_prealloc_blocks libxfs_prealloc_blocks #define xfs_dinode_good_version libxfs_dinode_good_version #define xfs_free_extent libxfs_free_extent #define xfs_refcountbt_init_cursor libxfs_refcountbt_init_cursor #define xfs_refcount_lookup_le libxfs_refcount_lookup_le #define xfs_refcount_get_rec libxfs_refcount_get_rec #define xfs_rmap_lookup_le_range libxfs_rmap_lookup_le_range #define xfs_refc_block libxfs_refc_block #endif /* __LIBXFS_API_DEFS_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/libxfs_io.h0000644000000000000000000001772613063067171016125 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LIBXFS_IO_H_ #define __LIBXFS_IO_H_ /* * Kernel equivalent buffer based I/O interface */ struct xfs_buf; struct xfs_mount; struct xfs_perag; /* * IO verifier callbacks need the xfs_mount pointer, so we have to behave * somewhat like the kernel now for userspace IO in terms of having buftarg * based devices... */ struct xfs_buftarg { struct xfs_mount *bt_mount; dev_t dev; }; extern void libxfs_buftarg_init(struct xfs_mount *mp, dev_t ddev, dev_t logdev, dev_t rtdev); #define LIBXFS_BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT) #define XB_PAGES 2 struct xfs_buf_map { xfs_daddr_t bm_bn; /* block number for I/O */ int bm_len; /* size of I/O */ }; #define DEFINE_SINGLE_BUF_MAP(map, blkno, numblk) \ struct xfs_buf_map (map) = { .bm_bn = (blkno), .bm_len = (numblk) }; struct xfs_buf_ops { char *name; void (*verify_read)(struct xfs_buf *); void (*verify_write)(struct xfs_buf *); }; typedef struct xfs_buf { struct cache_node b_node; unsigned int b_flags; xfs_daddr_t b_bn; unsigned b_bcount; unsigned int b_length; struct xfs_buftarg *b_target; #define b_dev b_target->dev pthread_mutex_t b_lock; pthread_t b_holder; unsigned int b_recur; void *b_fspriv; void *b_fsprivate2; void *b_fsprivate3; void *b_addr; int b_error; const struct xfs_buf_ops *b_ops; struct xfs_perag *b_pag; struct xfs_buf_map *b_maps; int b_nmaps; #ifdef XFS_BUF_TRACING struct list_head b_lock_list; const char *b_func; const char *b_file; int b_line; #endif } xfs_buf_t; enum xfs_buf_flags_t { /* b_flags bits */ LIBXFS_B_EXIT = 0x0001, /* ==LIBXFS_EXIT_ON_FAILURE */ LIBXFS_B_DIRTY = 0x0002, /* buffer has been modified */ LIBXFS_B_STALE = 0x0004, /* buffer marked as invalid */ LIBXFS_B_UPTODATE = 0x0008, /* buffer is sync'd to disk */ LIBXFS_B_DISCONTIG = 0x0010, /* discontiguous buffer */ LIBXFS_B_UNCHECKED = 0x0020, /* needs verification */ }; #define XFS_BUF_DADDR_NULL ((xfs_daddr_t) (-1LL)) #define XFS_BUF_PTR(bp) ((char *)(bp)->b_addr) #define xfs_buf_offset(bp, offset) ((bp)->b_addr + (offset)) #define XFS_BUF_ADDR(bp) ((bp)->b_bn) #define XFS_BUF_SIZE(bp) ((bp)->b_bcount) #define XFS_BUF_COUNT(bp) ((bp)->b_bcount) #define XFS_BUF_TARGET(bp) ((bp)->b_dev) #define XFS_BUF_SET_PTR(bp,p,cnt) ({ \ (bp)->b_addr = (char *)(p); \ XFS_BUF_SET_COUNT(bp,cnt); \ }) #define XFS_BUF_SET_ADDR(bp,blk) ((bp)->b_bn = (blk)) #define XFS_BUF_SET_COUNT(bp,cnt) ((bp)->b_bcount = (cnt)) #define XFS_BUF_FSPRIVATE(bp,type) ((type)(bp)->b_fspriv) #define XFS_BUF_SET_FSPRIVATE(bp,val) (bp)->b_fspriv = (void *)(val) #define XFS_BUF_FSPRIVATE2(bp,type) ((type)(bp)->b_fsprivate2) #define XFS_BUF_SET_FSPRIVATE2(bp,val) (bp)->b_fsprivate2 = (void *)(val) #define XFS_BUF_FSPRIVATE3(bp,type) ((type)(bp)->b_fsprivate3) #define XFS_BUF_SET_FSPRIVATE3(bp,val) (bp)->b_fsprivate3 = (void *)(val) #define XFS_BUF_SET_PRIORITY(bp,pri) cache_node_set_priority( \ libxfs_bcache, \ (struct cache_node *)(bp), \ (pri)) #define XFS_BUF_PRIORITY(bp) (cache_node_get_priority( \ (struct cache_node *)(bp))) #define xfs_buf_set_ref(bp,ref) ((void) 0) #define xfs_buf_ioerror(bp,err) ((bp)->b_error = (err)) #define xfs_daddr_to_agno(mp,d) \ ((xfs_agnumber_t)(XFS_BB_TO_FSBT(mp, d) / (mp)->m_sb.sb_agblocks)) #define xfs_daddr_to_agbno(mp,d) \ ((xfs_agblock_t)(XFS_BB_TO_FSBT(mp, d) % (mp)->m_sb.sb_agblocks)) /* Buffer Cache Interfaces */ extern struct cache *libxfs_bcache; extern struct cache_operations libxfs_bcache_operations; #define LIBXFS_GETBUF_TRYLOCK (1 << 0) #ifdef XFS_BUF_TRACING #define libxfs_readbuf(dev, daddr, len, flags, ops) \ libxfs_trace_readbuf(__FUNCTION__, __FILE__, __LINE__, \ (dev), (daddr), (len), (flags), (ops)) #define libxfs_readbuf_map(dev, map, nmaps, flags, ops) \ libxfs_trace_readbuf_map(__FUNCTION__, __FILE__, __LINE__, \ (dev), (map), (nmaps), (flags), (ops)) #define libxfs_writebuf(buf, flags) \ libxfs_trace_writebuf(__FUNCTION__, __FILE__, __LINE__, \ (buf), (flags)) #define libxfs_getbuf(dev, daddr, len) \ libxfs_trace_getbuf(__FUNCTION__, __FILE__, __LINE__, \ (dev), (daddr), (len)) #define libxfs_getbuf_map(dev, map, nmaps, flags) \ libxfs_trace_getbuf_map(__FUNCTION__, __FILE__, __LINE__, \ (dev), (map), (nmaps), (flags)) #define libxfs_getbuf_flags(dev, daddr, len, flags) \ libxfs_trace_getbuf_flags(__FUNCTION__, __FILE__, __LINE__, \ (dev), (daddr), (len), (flags)) #define libxfs_putbuf(buf) \ libxfs_trace_putbuf(__FUNCTION__, __FILE__, __LINE__, (buf)) extern xfs_buf_t *libxfs_trace_readbuf(const char *, const char *, int, struct xfs_buftarg *, xfs_daddr_t, int, int, const struct xfs_buf_ops *); extern xfs_buf_t *libxfs_trace_readbuf_map(const char *, const char *, int, struct xfs_buftarg *, struct xfs_buf_map *, int, int, const struct xfs_buf_ops *); extern int libxfs_trace_writebuf(const char *, const char *, int, xfs_buf_t *, int); extern xfs_buf_t *libxfs_trace_getbuf(const char *, const char *, int, struct xfs_buftarg *, xfs_daddr_t, int); extern xfs_buf_t *libxfs_trace_getbuf_map(const char *, const char *, int, struct xfs_buftarg *, struct xfs_buf_map *, int, int); extern xfs_buf_t *libxfs_trace_getbuf_flags(const char *, const char *, int, struct xfs_buftarg *, xfs_daddr_t, int, unsigned int); extern void libxfs_trace_putbuf (const char *, const char *, int, xfs_buf_t *); #else extern xfs_buf_t *libxfs_readbuf(struct xfs_buftarg *, xfs_daddr_t, int, int, const struct xfs_buf_ops *); extern xfs_buf_t *libxfs_readbuf_map(struct xfs_buftarg *, struct xfs_buf_map *, int, int, const struct xfs_buf_ops *); extern int libxfs_writebuf(xfs_buf_t *, int); extern xfs_buf_t *libxfs_getbuf(struct xfs_buftarg *, xfs_daddr_t, int); extern xfs_buf_t *libxfs_getbuf_map(struct xfs_buftarg *, struct xfs_buf_map *, int, int); extern xfs_buf_t *libxfs_getbuf_flags(struct xfs_buftarg *, xfs_daddr_t, int, unsigned int); extern void libxfs_putbuf (xfs_buf_t *); #endif extern void libxfs_readbuf_verify(struct xfs_buf *bp, const struct xfs_buf_ops *ops); extern xfs_buf_t *libxfs_getsb(struct xfs_mount *, int); extern void libxfs_bcache_purge(void); extern void libxfs_bcache_flush(void); extern void libxfs_purgebuf(xfs_buf_t *); extern int libxfs_bcache_overflowed(void); extern int libxfs_bcache_usage(void); /* Buffer (Raw) Interfaces */ extern xfs_buf_t *libxfs_getbufr(struct xfs_buftarg *, xfs_daddr_t, int); extern void libxfs_putbufr(xfs_buf_t *); extern int libxfs_writebuf_int(xfs_buf_t *, int); extern int libxfs_writebufr(struct xfs_buf *); extern int libxfs_readbufr(struct xfs_buftarg *, xfs_daddr_t, xfs_buf_t *, int, int); extern int libxfs_readbufr_map(struct xfs_buftarg *, struct xfs_buf *, int); extern int libxfs_device_zero(struct xfs_buftarg *, xfs_daddr_t, uint); extern int libxfs_bhash_size; #define LIBXFS_BREAD 0x1 #define LIBXFS_BWRITE 0x2 #define LIBXFS_BZERO 0x4 extern void libxfs_iomove (xfs_buf_t *, uint, int, void *, int); static inline int xfs_buf_verify_cksum(struct xfs_buf *bp, unsigned long cksum_offset) { return xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), cksum_offset); } static inline void xfs_buf_update_cksum(struct xfs_buf *bp, unsigned long cksum_offset) { xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), cksum_offset); } #endif /* __LIBXFS_IO_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/libxfs_priv.h0000644000000000000000000004040513063067171016464 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * This header is effectively a "namespace multiplexor" for the * user level XFS code. It provides all of the necessary stuff * such that we can build some parts of the XFS kernel code in * user space in a controlled fashion, and translates the names * used in the kernel into the names which libxfs is going to * make available to user tools. * * It should only ever be #include'd by XFS "kernel" code being * compiled in user space. * * Our goals here are to... * o "share" large amounts of complex code between user and * kernel space; * o shield the user tools from changes in the bleeding * edge kernel code, merging source changes when * convenient and not immediately (no symlinks); * o i.e. be able to merge changes to the kernel source back * into the affected user tools in a controlled fashion; * o provide a _minimalist_ life-support system for kernel * code in user land, not the "everything + the kitchen * sink" model which libsim had mutated into; * o allow the kernel code to be completely free of code * specifically there to support the user level build. */ /* * define a guard and something we can check to determine what include context * we are running from. */ #ifndef __LIBXFS_INTERNAL_XFS_H__ #define __LIBXFS_INTERNAL_XFS_H__ /* * Repair doesn't have a inode when it calls libxfs_dir2_data_freescan, * so we to work around this internally for now. */ #define xfs_dir2_data_freescan(ip, hdr, loghead) \ __xfs_dir2_data_freescan((ip)->i_mount->m_dir_geo, \ (ip)->d_ops, hdr, loghead) #include "libxfs_api_defs.h" #include "platform_defs.h" #include "xfs.h" #include "list.h" #include "hlist.h" #include "cache.h" #include "bitops.h" #include "kmem.h" #include "radix-tree.h" #include "atomic.h" #include "xfs_types.h" #include "xfs_arch.h" #include "xfs_fs.h" /* CRC stuff, buffer API dependent on it */ extern uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len); extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len); #define crc32(c,p,l) crc32_le((c),(unsigned char const *)(p),(l)) #define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l)) #include "xfs_cksum.h" /* * This mirrors the kernel include for xfs_buf.h - it's implicitly included in * every files via a similar include in the kernel xfs_linux.h. */ #include "libxfs_io.h" /* for all the support code that uses progname in error messages */ extern char *progname; #undef ASSERT #define ASSERT(ex) assert(ex) #ifndef EWRONGFS #define EWRONGFS EINVAL #endif #define xfs_error_level 0 #define STATIC static /* XXX: need to push these out to make LIBXFS_ATTR defines */ #define ATTR_ROOT 0x0002 #define ATTR_SECURE 0x0008 #define ATTR_CREATE 0x0010 #define ATTR_REPLACE 0x0020 #define ATTR_KERNOTIME 0 #define ATTR_KERNOVAL 0 #define IHOLD(ip) ((void) 0) #define XFS_IGET_CREATE 0x1 #define XFS_IGET_UNTRUSTED 0x2 extern void cmn_err(int, char *, ...); enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC }; #define xfs_notice(mp,fmt,args...) cmn_err(CE_NOTE,fmt, ## args) #define xfs_warn(mp,fmt,args...) cmn_err(CE_WARN,fmt, ## args) #define xfs_hex_dump(d,n) ((void) 0) #define xfs_force_shutdown(d,n) ((void) 0) /* stop unused var warnings by assigning mp to itself */ #define XFS_CORRUPTION_ERROR(e,l,mp,m) do { \ (mp) = (mp); \ cmn_err(CE_ALERT, "%s: XFS_CORRUPTION_ERROR", (e)); \ } while (0) #define XFS_ERROR_REPORT(e,l,mp) do { \ (mp) = (mp); \ cmn_err(CE_ALERT, "%s: XFS_ERROR_REPORT", (e)); \ } while (0) #define XFS_QM_DQATTACH(mp,ip,flags) 0 #define XFS_ERRLEVEL_LOW 1 #define XFS_FORCED_SHUTDOWN(mp) 0 #define XFS_ILOCK_EXCL 0 #define XFS_STATS_INC(mp, count) do { (mp) = (mp); } while (0) #define XFS_STATS_DEC(mp, count, x) do { (mp) = (mp); } while (0) #define XFS_STATS_ADD(mp, count, x) do { (mp) = (mp); } while (0) #define XFS_TRANS_MOD_DQUOT_BYINO(mp,tp,ip,field,delta) do { } while (0) #define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,tp,ip,nblks,ninos,fl) 0 #define XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp,tp,ip,nblks,ninos,fl) 0 #define XFS_TEST_ERROR(expr,a,b,c) ( expr ) #define XFS_WANT_CORRUPTED_GOTO(mp, expr, l) \ { \ if (!(expr)) { \ if ((mp)->m_flags & LIBXFS_MOUNT_WANT_CORRUPTED) \ printf("WANT_CORRUPTED_GOTO at %s:%d\n", \ __func__, __LINE__); \ error = -EFSCORRUPTED; \ goto l; \ } \ } #define XFS_WANT_CORRUPTED_RETURN(mp, expr) \ { \ if (!(expr)) { \ if ((mp)->m_flags & LIBXFS_MOUNT_WANT_CORRUPTED) \ printf("WANT_CORRUPTED_RETURN at %s:%d\n", \ __func__, __LINE__); \ return -EFSCORRUPTED; \ } \ } #ifdef __GNUC__ #define __return_address __builtin_return_address(0) #endif #define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1 /* miscellaneous kernel routines not in user space */ #define down_read(a) ((void) 0) #define up_read(a) ((void) 0) #define spin_lock_init(a) ((void) 0) #define spin_lock(a) ((void) 0) #define spin_unlock(a) ((void) 0) #define likely(x) (x) #define unlikely(x) (x) #define rcu_read_lock() ((void) 0) #define rcu_read_unlock() ((void) 0) #define WARN_ON_ONCE(expr) ((void) 0) #define percpu_counter_read(x) (*x) #define percpu_counter_read_positive(x) ((*x) > 0 ? (*x) : 0) #define percpu_counter_sum(x) (*x) /* * prandom_u32 is used for di_gen inode allocation, it must be zero for libxfs * or all sorts of badness can occur! */ #define prandom_u32() 0 #define PAGE_SIZE getpagesize() static inline int __do_div(unsigned long long *n, unsigned base) { int __res; __res = (int)(((unsigned long) *n) % (unsigned) base); *n = ((unsigned long) *n) / (unsigned) base; return __res; } #define do_div(n,base) (__do_div((unsigned long long *)&(n), (base))) #define do_mod(a, b) ((a) % (b)) #define rol32(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) #define min_t(type,x,y) \ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) #define max_t(type,x,y) \ ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) #define __round_mask(x, y) ((__typeof__(x))((y)-1)) #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) #define round_down(x, y) ((x) & ~__round_mask(x, y)) #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) /* * Handling for kernel bitmap types. */ #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, NBBY * sizeof(long)) #define DECLARE_BITMAP(name,bits) \ unsigned long name[BITS_TO_LONGS(bits)] #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) /* * This is a common helper function for find_next_bit and * find_next_zero_bit. The difference is the "invert" argument, which * is XORed with each fetched word before searching it for one bits. */ static inline unsigned long _find_next_bit(const unsigned long *addr, unsigned long nbits, unsigned long start, unsigned long invert) { unsigned long tmp; if (!nbits || start >= nbits) return nbits; tmp = addr[start / BITS_PER_LONG] ^ invert; /* Handle 1st word. */ tmp &= BITMAP_FIRST_WORD_MASK(start); start = round_down(start, BITS_PER_LONG); while (!tmp) { start += BITS_PER_LONG; if (start >= nbits) return nbits; tmp = addr[start / BITS_PER_LONG] ^ invert; } return min(start + ffs(tmp), nbits); } /* * Find the next set bit in a memory region. */ static inline unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { return _find_next_bit(addr, size, offset, 0UL); } static inline unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { return _find_next_bit(addr, size, offset, ~0UL); } #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) static inline __attribute__((const)) int is_power_of_2(unsigned long n) { return (n != 0 && ((n & (n - 1)) == 0)); } /* * xfs_iroundup: round up argument to next power of two */ static inline uint roundup_pow_of_two(uint v) { int i; uint m; if ((v & (v - 1)) == 0) return v; ASSERT((v & 0x80000000) == 0); if ((v & (v + 1)) == 0) return v + 1; for (i = 0, m = 1; i < 31; i++, m <<= 1) { if (v & m) continue; v |= m; if ((v & (v + 1)) == 0) return v + 1; } ASSERT(0); return 0; } static inline __uint64_t roundup_64(__uint64_t x, __uint32_t y) { x += y - 1; do_div(x, y); return x * y; } /* buffer management */ #define XFS_BUF_LOCK 0 #define XFS_BUF_TRYLOCK 0 #define XBF_LOCK XFS_BUF_LOCK #define XBF_TRYLOCK XFS_BUF_TRYLOCK #define XBF_DONT_BLOCK 0 #define XBF_UNMAPPED 0 #define XBF_DONE 0 #define XFS_BUF_GETERROR(bp) 0 #define XFS_BUF_DONE(bp) ((bp)->b_flags |= LIBXFS_B_UPTODATE) #define XFS_BUF_ISDONE(bp) ((bp)->b_flags & LIBXFS_B_UPTODATE) #define xfs_buf_stale(bp) ((bp)->b_flags |= LIBXFS_B_STALE) #define XFS_BUF_UNDELAYWRITE(bp) ((bp)->b_flags &= ~LIBXFS_B_DIRTY) #define XFS_BUF_SET_VTYPE(a,b) ((void) 0) #define XFS_BUF_SET_VTYPE_REF(a,b,c) ((void) 0) #define XFS_BUF_SET_BDSTRAT_FUNC(a,b) ((void) 0) /* avoid gcc warning */ #define xfs_incore(bt,blkno,len,lockit) ({ \ typeof(blkno) __foo = (blkno); \ typeof(len) __bar = (len); \ (blkno) = __foo; \ (len) = __bar; /* no set-but-unused warning */ \ NULL; \ }) #define xfs_buf_relse(bp) libxfs_putbuf(bp) #define xfs_buf_get(devp,blkno,len,f) (libxfs_getbuf((devp), (blkno), (len))) #define xfs_bwrite(bp) libxfs_writebuf((bp), 0) #define xfs_buf_delwri_queue(bp, bl) libxfs_writebuf((bp), 0) #define XBRW_READ LIBXFS_BREAD #define XBRW_WRITE LIBXFS_BWRITE #define xfs_buf_iomove(bp,off,len,data,f) libxfs_iomove(bp,off,len,data,f) #define xfs_buf_zero(bp,off,len) libxfs_iomove(bp,off,len,0,LIBXFS_BZERO) /* mount stuff */ #define XFS_MOUNT_32BITINODES LIBXFS_MOUNT_32BITINODES #define XFS_MOUNT_ATTR2 LIBXFS_MOUNT_ATTR2 #define XFS_MOUNT_SMALL_INUMS 0 /* ignored in userspace */ #define XFS_MOUNT_WSYNC 0 /* ignored in userspace */ #define XFS_MOUNT_NOALIGN 0 /* ignored in userspace */ #define XFS_MOUNT_IKEEP 0 /* ignored in userspace */ #define XFS_MOUNT_SWALLOC 0 /* ignored in userspace */ #define XFS_MOUNT_RDONLY 0 /* ignored in userspace */ #define xfs_trans_get_block_res(tp) 1 #define xfs_trans_set_sync(tp) ((void) 0) #define xfs_trans_ordered_buf(tp, bp) ((void) 0) #define xfs_trans_agblocks_delta(tp, d) #define xfs_trans_agflist_delta(tp, d) #define xfs_trans_agbtree_delta(tp, d) #define xfs_trans_buf_set_type(tp, bp, t) ({ \ int __t = (t); \ __t = __t; /* no set-but-unused warning */ \ tp = tp; /* no set-but-unused warning */ \ }) #define xfs_trans_buf_copy_type(dbp, sbp) /* no readahead, need to avoid set-but-unused var warnings. */ #define xfs_buf_readahead(a,d,c,ops) ({ \ xfs_daddr_t __d = d; \ __d = __d; /* no set-but-unused warning */ \ }) #define xfs_buf_readahead_map(a,b,c,ops) ((void) 0) /* no readahead */ #define xfs_buftrace(x,y) ((void) 0) /* debug only */ #define xfs_cmn_err(tag,level,mp,fmt,args...) cmn_err(level,fmt, ## args) #define xfs_warn(mp,fmt,args...) cmn_err(CE_WARN,fmt, ## args) #define xfs_alert(mp,fmt,args...) cmn_err(CE_ALERT,fmt, ## args) #define xfs_alert_tag(mp,tag,fmt,args...) cmn_err(CE_ALERT,fmt, ## args) #define xfs_dir2_trace_args(where, args) ((void) 0) #define xfs_dir2_trace_args_b(where, args, bp) ((void) 0) #define xfs_dir2_trace_args_bb(where, args, lbp, dbp) ((void) 0) #define xfs_dir2_trace_args_bibii(where, args, bs, ss, bd, sd, c) ((void) 0) #define xfs_dir2_trace_args_db(where, args, db, bp) ((void) 0) #define xfs_dir2_trace_args_i(where, args, i) ((void) 0) #define xfs_dir2_trace_args_s(where, args, s) ((void) 0) #define xfs_dir2_trace_args_sb(where, args, s, bp) ((void) 0) #define xfs_sort qsort #define xfs_icsb_reinit_counters(mp) do { } while (0) #define xfs_initialize_perag_icache(pag) ((void) 0) #define xfs_ilock(ip,mode) ((void) 0) #define xfs_ilock_nowait(ip,mode) ((void) 0) #define xfs_ilock_demote(ip,mode) ((void) 0) #define xfs_ilock_data_map_shared(ip) (0) #define xfs_ilock_attr_map_shared(ip) (0) #define xfs_iunlock(ip,mode) ({ \ typeof(mode) __mode = mode; \ __mode = __mode; /* no set-but-unused warning */ \ }) #define __xfs_flock(ip) ((void) 0) /* space allocation */ #define xfs_extent_busy_reuse(mp,ag,bno,len,user) ((void) 0) /* avoid unused variable warning */ #define xfs_extent_busy_insert(tp,ag,bno,len,flags)({ \ xfs_agnumber_t __foo = ag; \ __foo = __foo; /* no set-but-unused warning */ \ }) #define xfs_extent_busy_trim(args,fbno,flen,bno,len) \ do { \ *(bno) = (fbno); \ *(len) = (flen); \ } while (0) /* avoid unused variable warning */ #define xfs_alloc_busy_insert(tp,ag,b,len) ({ \ xfs_agnumber_t __foo = ag; \ __foo = 0; \ }) #define xfs_rotorstep 1 #define xfs_bmap_rtalloc(a) (-ENOSYS) #define xfs_get_extsz_hint(ip) (0) #define xfs_get_cowextsz_hint(ip) (0) #define xfs_inode_is_filestream(ip) (0) #define xfs_filestream_lookup_ag(ip) (0) #define xfs_filestream_new_ag(ip,ag) (0) #define xfs_log_force(mp,flags) ((void) 0) #define XFS_LOG_SYNC 1 /* quota bits */ #define xfs_trans_mod_dquot_byino(t,i,f,d) ((void) 0) #define xfs_trans_reserve_quota_nblks(t,i,b,n,f) (0) #define xfs_trans_unreserve_quota_nblks(t,i,b,n,f) ((void) 0) #define xfs_qm_dqattach(i,f) (0) #define uuid_copy(s,d) platform_uuid_copy((s),(d)) #define uuid_equal(s,d) (platform_uuid_compare((s),(d)) == 0) #define xfs_icreate_log(tp, agno, agbno, cnt, isize, len, gen) ((void) 0) #define xfs_sb_validate_fsb_count(sbp, nblks) (0) /* * Prototypes for kernel static functions that are aren't in their * associated header files. */ struct xfs_da_args; struct xfs_bmap_free; struct xfs_bmap_free_item; struct xfs_mount; struct xfs_sb; struct xfs_trans; struct xfs_inode; struct xfs_log_item; struct xfs_buf; struct xfs_buf_map; struct xfs_buf_log_item; struct xfs_buftarg; /* xfs_attr.c */ int xfs_attr_rmtval_get(struct xfs_da_args *); /* xfs_bmap.c */ void xfs_bmap_del_free(struct xfs_bmap_free *, struct xfs_bmap_free_item *); /* xfs_mount.c */ int xfs_initialize_perag_data(struct xfs_mount *, xfs_agnumber_t); void xfs_mount_common(struct xfs_mount *, struct xfs_sb *); /* * logitem.c and trans.c prototypes */ void xfs_trans_init(struct xfs_mount *); int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); /* xfs_trans_item.c */ void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *); void xfs_trans_del_item(struct xfs_log_item *); /* xfs_inode_item.c */ void xfs_inode_item_init(struct xfs_inode *, struct xfs_mount *); /* xfs_buf_item.c */ void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); void xfs_buf_item_log(struct xfs_buf_log_item *, uint, uint); /* xfs_trans_buf.c */ struct xfs_buf *xfs_trans_buf_item_match(struct xfs_trans *, struct xfs_buftarg *, struct xfs_buf_map *, int); /* local source files */ #define xfs_mod_fdblocks(mp, delta, rsvd) \ libxfs_mod_incore_sb(mp, XFS_TRANS_SB_FDBLOCKS, delta, rsvd) #define xfs_mod_frextents(mp, delta) \ libxfs_mod_incore_sb(mp, XFS_TRANS_SB_FREXTENTS, delta, 0) int libxfs_mod_incore_sb(struct xfs_mount *, int, int64_t, int); /* percpu counters in mp are #defined to the superblock sb_ counters */ #define xfs_reinit_percpu_counters(mp) void xfs_trans_mod_sb(struct xfs_trans *, uint, long); void xfs_trans_init(struct xfs_mount *); int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); void xfs_verifier_error(struct xfs_buf *bp); /* XXX: this is clearly a bug - a shared header needs to export this */ /* xfs_rtalloc.c */ int libxfs_rtfree_extent(struct xfs_trans *, xfs_rtblock_t, xfs_extlen_t); int libxfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb, xfs_off_t count_fsb); bool xfs_log_check_lsn(struct xfs_mount *, xfs_lsn_t); #endif /* __LIBXFS_INTERNAL_XFS_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/linux.c0000644000000000000000000001322013063067171015262 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "libxfs_priv.h" #include "xfs_fs.h" int platform_has_uuid = 1; extern char *progname; static int max_block_alignment; #ifndef BLKGETSIZE64 # define BLKGETSIZE64 _IOR(0x12,114,size_t) #endif #ifndef BLKBSZSET # define BLKBSZSET _IOW(0x12,113,size_t) #endif #ifndef BLKSSZGET # define BLKSSZGET _IO(0x12,104) #endif #ifndef RAMDISK_MAJOR #define RAMDISK_MAJOR 1 /* ramdisk major number */ #endif #define PROC_MOUNTED "/proc/mounts" /* * Check if the filesystem is mounted. Be verbose if asked, and * optionally restrict check to /writable/ mounts (i.e. RO is OK) */ #define CHECK_MOUNT_VERBOSE 0x1 #define CHECK_MOUNT_WRITABLE 0x2 static int platform_check_mount(char *name, char *block, struct stat *s, int flags) { FILE *f; struct stat st, mst; struct mntent *mnt; char mounts[MAXPATHLEN]; if (!s) { /* If either fails we are not mounted */ if (stat(block, &st) < 0) return 0; if ((st.st_mode & S_IFMT) != S_IFBLK) return 0; s = &st; } strcpy(mounts, (!access(PROC_MOUNTED, R_OK)) ? PROC_MOUNTED : MOUNTED); if ((f = setmntent(mounts, "r")) == NULL) { /* Unexpected failure, warn unconditionally */ fprintf(stderr, _("%s: %s possibly contains a mounted filesystem\n"), progname, name); return 1; } while ((mnt = getmntent(f)) != NULL) { if (stat(mnt->mnt_dir, &mst) < 0) continue; if (mst.st_dev != s->st_rdev) continue; /* Found our device, is RO OK? */ if ((flags & CHECK_MOUNT_WRITABLE) && hasmntopt(mnt, MNTOPT_RO)) continue; else break; } endmntent(f); /* No mounts contained the condition we were looking for */ if (mnt == NULL) return 0; if (flags & CHECK_MOUNT_VERBOSE) { if (flags & CHECK_MOUNT_WRITABLE) { fprintf(stderr, _("%s: %s contains a mounted and writable filesystem\n"), progname, name); } else { fprintf(stderr, _("%s: %s contains a mounted filesystem\n"), progname, name); } } return 1; } int platform_check_ismounted(char *name, char *block, struct stat *s, int verbose) { int flags; flags = verbose ? CHECK_MOUNT_VERBOSE : 0; return platform_check_mount(name, block, s, flags); } int platform_check_iswritable(char *name, char *block, struct stat *s) { int flags; /* Writable checks are always verbose */ flags = CHECK_MOUNT_WRITABLE | CHECK_MOUNT_VERBOSE; return platform_check_mount(name, block, s, flags); } int platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fatal) { int error = 0; if (major(device) != RAMDISK_MAJOR) { if ((error = ioctl(fd, BLKBSZSET, &blocksize)) < 0) { fprintf(stderr, _("%s: %s - cannot set blocksize " "%d on block device %s: %s\n"), progname, fatal ? "error": "warning", blocksize, path, strerror(errno)); } } return error; } void platform_flush_device(int fd, dev_t device) { struct stat st; if (major(device) == RAMDISK_MAJOR) return; if (fstat(fd, &st) < 0) return; if (S_ISREG(st.st_mode)) fsync(fd); else ioctl(fd, BLKFLSBUF, 0); } void platform_findsizes(char *path, int fd, long long *sz, int *bsz) { struct stat st; __uint64_t size; int error; if (fstat(fd, &st) < 0) { fprintf(stderr, _("%s: " "cannot stat the device file \"%s\": %s\n"), progname, path, strerror(errno)); exit(1); } if ((st.st_mode & S_IFMT) == S_IFREG) { struct dioattr da; *sz = (long long)(st.st_size >> 9); if (ioctl(fd, XFS_IOC_DIOINFO, &da) < 0) { /* * fall back to BBSIZE; mkfs might fail if there's a * size mismatch between the image & the host fs... */ *bsz = BBSIZE; } else *bsz = da.d_miniosz; if (*bsz > max_block_alignment) max_block_alignment = *bsz; return; } error = ioctl(fd, BLKGETSIZE64, &size); if (error >= 0) { /* BLKGETSIZE64 returns size in bytes not 512-byte blocks */ *sz = (long long)(size >> 9); } else { /* If BLKGETSIZE64 fails, try BLKGETSIZE */ unsigned long tmpsize; error = ioctl(fd, BLKGETSIZE, &tmpsize); if (error < 0) { fprintf(stderr, _("%s: can't determine device size\n"), progname); exit(1); } *sz = (long long)tmpsize; } if (ioctl(fd, BLKSSZGET, bsz) < 0) { fprintf(stderr, _("%s: warning - cannot get sector size " "from block device %s: %s\n"), progname, path, strerror(errno)); *bsz = BBSIZE; } if (*bsz > max_block_alignment) max_block_alignment = *bsz; } char * platform_findrawpath(char *path) { return path; } char * platform_findblockpath(char *path) { return path; } int platform_direct_blockdev(void) { return 1; } int platform_align_blockdev(void) { if (!max_block_alignment) return getpagesize(); return max_block_alignment; } int platform_nproc(void) { return sysconf(_SC_NPROCESSORS_ONLN); } unsigned long platform_physmem(void) { struct sysinfo si; if (sysinfo(&si) < 0) { fprintf(stderr, _("%s: can't determine memory size\n"), progname); exit(1); } return (si.totalram >> 10) * si.mem_unit; /* kilobytes */ } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/list_sort.c0000644000000000000000000000665513033541503016154 0ustar /* List sorting code from Linux::lib/list_sort.c. */ #include "libxfs_priv.h" #include "libxfs_io.h" #include "init.h" #include "list.h" #define MAX_LIST_LENGTH_BITS 20 /* * Returns a list organized in an intermediate format suited * to chaining of merge() calls: null-terminated, no reserved or * sentinel head node, "prev" links not maintained. */ static struct list_head *merge(void *priv, int (*cmp)(void *priv, struct list_head *a, struct list_head *b), struct list_head *a, struct list_head *b) { struct list_head head, *tail = &head; while (a && b) { /* if equal, take 'a' -- important for sort stability */ if ((*cmp)(priv, a, b) <= 0) { tail->next = a; a = a->next; } else { tail->next = b; b = b->next; } tail = tail->next; } tail->next = a?:b; return head.next; } /* * Combine final list merge with restoration of standard doubly-linked * list structure. This approach duplicates code from merge(), but * runs faster than the tidier alternatives of either a separate final * prev-link restoration pass, or maintaining the prev links * throughout. */ static void merge_and_restore_back_links(void *priv, int (*cmp)(void *priv, struct list_head *a, struct list_head *b), struct list_head *head, struct list_head *a, struct list_head *b) { struct list_head *tail = head; unsigned count = 0; while (a && b) { /* if equal, take 'a' -- important for sort stability */ if ((*cmp)(priv, a, b) <= 0) { tail->next = a; a->prev = tail; a = a->next; } else { tail->next = b; b->prev = tail; b = b->next; } tail = tail->next; } tail->next = a ? : b; do { /* * In worst cases this loop may run many iterations. * Continue callbacks to the client even though no * element comparison is needed, so the client's cmp() * routine can invoke cond_resched() periodically. */ if (unlikely(!(++count))) (*cmp)(priv, tail->next, tail->next); tail->next->prev = tail; tail = tail->next; } while (tail->next); tail->next = head; head->prev = tail; } /** * list_sort - sort a list * @priv: private data, opaque to list_sort(), passed to @cmp * @head: the list to sort * @cmp: the elements comparison function * * This function implements "merge sort", which has O(nlog(n)) * complexity. * * The comparison function @cmp must return a negative value if @a * should sort before @b, and a positive value if @a should sort after * @b. If @a and @b are equivalent, and their original relative * ordering is to be preserved, @cmp must return 0. */ void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, struct list_head *a, struct list_head *b)) { struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists -- last slot is a sentinel */ int lev; /* index into part[] */ int max_lev = 0; struct list_head *list; if (list_empty(head)) return; memset(part, 0, sizeof(part)); head->prev->next = NULL; list = head->next; while (list) { struct list_head *cur = list; list = list->next; cur->next = NULL; for (lev = 0; part[lev]; lev++) { cur = merge(priv, cmp, part[lev], cur); part[lev] = NULL; } if (lev > max_lev) { if (unlikely(lev >= ARRAY_SIZE(part)-1)) { lev--; } max_lev = lev; } part[lev] = cur; } for (lev = 0; lev < max_lev; lev++) if (part[lev]) list = merge(priv, cmp, part[lev], list); merge_and_restore_back_links(priv, cmp, head, part[max_lev], list); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/logitem.c0000644000000000000000000001103613063067171015566 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_inode.h" #include "xfs_trans.h" kmem_zone_t *xfs_buf_item_zone; kmem_zone_t *xfs_ili_zone; /* inode log item zone */ /* * Following functions from fs/xfs/xfs_trans_buf.c */ /* * Check to see if a buffer matching the given parameters is already * a part of the given transaction. */ xfs_buf_t * xfs_trans_buf_item_match( xfs_trans_t *tp, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps) { struct xfs_log_item_desc *lidp; struct xfs_buf_log_item *blip; int len = 0; int i; for (i = 0; i < nmaps; i++) len += map[i].bm_len; list_for_each_entry(lidp, &tp->t_items, lid_trans) { blip = (struct xfs_buf_log_item *)lidp->lid_item; if (blip->bli_item.li_type == XFS_LI_BUF && blip->bli_buf->b_target->dev == btp->dev && XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn && blip->bli_buf->b_bcount == BBTOB(len)) { ASSERT(blip->bli_buf->b_map_count == nmaps); return blip->bli_buf; } } return NULL; } /* * The following are from fs/xfs/xfs_buf_item.c */ /* * Allocate a new buf log item to go with the given buffer. * Set the buffer's b_fsprivate field to point to the new * buf log item. If there are other item's attached to the * buffer (see xfs_buf_attach_iodone() below), then put the * buf log item at the front. */ void xfs_buf_item_init( xfs_buf_t *bp, xfs_mount_t *mp) { xfs_log_item_t *lip; xfs_buf_log_item_t *bip; #ifdef LI_DEBUG fprintf(stderr, "buf_item_init for buffer %p\n", bp); #endif /* * Check to see if there is already a buf log item for * this buffer. If there is, it is guaranteed to be * the first. If we do already have one, there is * nothing to do here so return. */ if (XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *) != mp) XFS_BUF_SET_FSPRIVATE3(bp, mp); XFS_BUF_SET_BDSTRAT_FUNC(bp, xfs_bdstrat_cb); if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) { lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); if (lip->li_type == XFS_LI_BUF) { #ifdef LI_DEBUG fprintf(stderr, "reused buf item %p for pre-logged buffer %p\n", lip, bp); #endif return; } } bip = (xfs_buf_log_item_t *)kmem_zone_zalloc(xfs_buf_item_zone, KM_SLEEP); #ifdef LI_DEBUG fprintf(stderr, "adding buf item %p for not-logged buffer %p\n", bip, bp); #endif bip->bli_item.li_type = XFS_LI_BUF; bip->bli_item.li_mountp = mp; bip->bli_buf = bp; bip->bli_format.blf_type = XFS_LI_BUF; bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp); bip->bli_format.blf_len = (unsigned short)BTOBB(XFS_BUF_COUNT(bp)); XFS_BUF_SET_FSPRIVATE(bp, bip); } /* * Mark bytes first through last inclusive as dirty in the buf * item's bitmap. */ void xfs_buf_item_log( xfs_buf_log_item_t *bip, uint first, uint last) { /* * Mark the item as having some dirty data for * quick reference in xfs_buf_item_dirty. */ bip->bli_flags |= XFS_BLI_DIRTY; } /* * Initialize the inode log item for a newly allocated (in-core) inode. */ void xfs_inode_item_init( xfs_inode_t *ip, xfs_mount_t *mp) { xfs_inode_log_item_t *iip; ASSERT(ip->i_itemp == NULL); iip = ip->i_itemp = (xfs_inode_log_item_t *) kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP); #ifdef LI_DEBUG fprintf(stderr, "inode_item_init for inode %llu, iip=%p\n", ip->i_ino, iip); #endif iip->ili_item.li_type = XFS_LI_INODE; iip->ili_item.li_mountp = mp; iip->ili_inode = ip; iip->ili_format.ilf_type = XFS_LI_INODE; iip->ili_format.ilf_ino = ip->i_ino; iip->ili_format.ilf_blkno = ip->i_imap.im_blkno; iip->ili_format.ilf_len = ip->i_imap.im_len; iip->ili_format.ilf_boffset = ip->i_imap.im_boffset; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/radix-tree.c0000644000000000000000000004624613063067171016205 0ustar /* * Copyright (C) 2001 Momchil Velikov * Portions Copyright (C) 2001 Christoph Hellwig * Copyright (C) 2005 SGI, Christoph Lameter * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "platform_defs.h" #include "xfs.h" #include "radix-tree.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif #define RADIX_TREE_MAP_SHIFT 6 #define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT) #define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1) #ifdef RADIX_TREE_TAGS #define RADIX_TREE_TAG_LONGS \ ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG) #endif struct radix_tree_node { unsigned int count; void *slots[RADIX_TREE_MAP_SIZE]; #ifdef RADIX_TREE_TAGS unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS]; #endif }; struct radix_tree_path { struct radix_tree_node *node; int offset; }; #define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2) static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH]; /* * Radix tree node cache. */ #define radix_tree_node_alloc(r) ((struct radix_tree_node *) \ calloc(1, sizeof(struct radix_tree_node))) #define radix_tree_node_free(n) free(n) #ifdef RADIX_TREE_TAGS static inline void tag_set(struct radix_tree_node *node, unsigned int tag, int offset) { *((__uint32_t *)node->tags[tag] + (offset >> 5)) |= (1 << (offset & 31)); } static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, int offset) { __uint32_t *p = (__uint32_t*)node->tags[tag] + (offset >> 5); __uint32_t m = 1 << (offset & 31); *p &= ~m; } static inline int tag_get(struct radix_tree_node *node, unsigned int tag, int offset) { return 1 & (((const __uint32_t *)node->tags[tag])[offset >> 5] >> (offset & 31)); } /* * Returns 1 if any slot in the node has this tag set. * Otherwise returns 0. */ static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag) { int idx; for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { if (node->tags[tag][idx]) return 1; } return 0; } #endif /* * Return the maximum key which can be store into a * radix tree with height HEIGHT. */ static inline unsigned long radix_tree_maxindex(unsigned int height) { return height_to_maxindex[height]; } /* * Extend a radix tree so it can store key @index. */ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) { struct radix_tree_node *node; unsigned int height; #ifdef RADIX_TREE_TAGS char tags[RADIX_TREE_MAX_TAGS]; int tag; #endif /* Figure out what the height should be. */ height = root->height + 1; while (index > radix_tree_maxindex(height)) height++; if (root->rnode == NULL) { root->height = height; goto out; } #ifdef RADIX_TREE_TAGS /* * Prepare the tag status of the top-level node for propagation * into the newly-pushed top-level node(s) */ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { tags[tag] = 0; if (any_tag_set(root->rnode, tag)) tags[tag] = 1; } #endif do { if (!(node = radix_tree_node_alloc(root))) return -ENOMEM; /* Increase the height. */ node->slots[0] = root->rnode; #ifdef RADIX_TREE_TAGS /* Propagate the aggregated tag info into the new root */ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { if (tags[tag]) tag_set(node, tag, 0); } #endif node->count = 1; root->rnode = node; root->height++; } while (height > root->height); out: return 0; } /** * radix_tree_insert - insert into a radix tree * @root: radix tree root * @index: index key * @item: item to insert * * Insert an item into the radix tree at position @index. */ int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item) { struct radix_tree_node *node = NULL, *slot; unsigned int height, shift; int offset; int error; /* Make sure the tree is high enough. */ if ((!index && !root->rnode) || index > radix_tree_maxindex(root->height)) { error = radix_tree_extend(root, index); if (error) return error; } slot = root->rnode; height = root->height; shift = (height-1) * RADIX_TREE_MAP_SHIFT; offset = 0; /* uninitialised var warning */ do { if (slot == NULL) { /* Have to add a child node. */ if (!(slot = radix_tree_node_alloc(root))) return -ENOMEM; if (node) { node->slots[offset] = slot; node->count++; } else root->rnode = slot; } /* Go a level down */ offset = (index >> shift) & RADIX_TREE_MAP_MASK; node = slot; slot = node->slots[offset]; shift -= RADIX_TREE_MAP_SHIFT; height--; } while (height > 0); if (slot != NULL) return -EEXIST; ASSERT(node); node->count++; node->slots[offset] = item; #ifdef RADIX_TREE_TAGS ASSERT(!tag_get(node, 0, offset)); ASSERT(!tag_get(node, 1, offset)); #endif return 0; } static inline void **__lookup_slot(struct radix_tree_root *root, unsigned long index) { unsigned int height, shift; struct radix_tree_node **slot; height = root->height; if (index > radix_tree_maxindex(height)) return NULL; shift = (height-1) * RADIX_TREE_MAP_SHIFT; slot = &root->rnode; while (height > 0) { if (*slot == NULL) return NULL; slot = (struct radix_tree_node **) ((*slot)->slots + ((index >> shift) & RADIX_TREE_MAP_MASK)); shift -= RADIX_TREE_MAP_SHIFT; height--; } return (void **)slot; } /** * radix_tree_lookup_slot - lookup a slot in a radix tree * @root: radix tree root * @index: index key * * Lookup the slot corresponding to the position @index in the radix tree * @root. This is useful for update-if-exists operations. */ void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index) { return __lookup_slot(root, index); } /** * radix_tree_lookup - perform lookup operation on a radix tree * @root: radix tree root * @index: index key * * Lookup the item at the position @index in the radix tree @root. */ void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) { void **slot; slot = __lookup_slot(root, index); return slot != NULL ? *slot : NULL; } /** * raid_tree_first_key - find the first index key in the radix tree * @root: radix tree root * @index: where the first index will be placed * * Returns the first entry and index key in the radix tree @root. */ void *radix_tree_lookup_first(struct radix_tree_root *root, unsigned long *index) { unsigned int height, shift; struct radix_tree_node *slot; unsigned long i; height = root->height; *index = 0; if (height == 0) return NULL; shift = (height-1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; for (; height > 1; height--) { for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) { if (slot->slots[i] != NULL) break; } ASSERT(i < RADIX_TREE_MAP_SIZE); *index |= (i << shift); shift -= RADIX_TREE_MAP_SHIFT; slot = slot->slots[i]; } for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) { if (slot->slots[i] != NULL) { *index |= i; return slot->slots[i]; } } return NULL; } #ifdef RADIX_TREE_TAGS /** * radix_tree_tag_set - set a tag on a radix tree node * @root: radix tree root * @index: index key * @tag: tag index * * Set the search tag (which must be < RADIX_TREE_MAX_TAGS) * corresponding to @index in the radix tree. From * the root all the way down to the leaf node. * * Returns the address of the tagged item. Setting a tag on a not-present * item is a bug. */ void *radix_tree_tag_set(struct radix_tree_root *root, unsigned long index, unsigned int tag) { unsigned int height, shift; struct radix_tree_node *slot; height = root->height; if (index > radix_tree_maxindex(height)) return NULL; shift = (height - 1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; while (height > 0) { int offset; offset = (index >> shift) & RADIX_TREE_MAP_MASK; if (!tag_get(slot, tag, offset)) tag_set(slot, tag, offset); slot = slot->slots[offset]; ASSERT(slot != NULL); shift -= RADIX_TREE_MAP_SHIFT; height--; } return slot; } /** * radix_tree_tag_clear - clear a tag on a radix tree node * @root: radix tree root * @index: index key * @tag: tag index * * Clear the search tag (which must be < RADIX_TREE_MAX_TAGS) * corresponding to @index in the radix tree. If * this causes the leaf node to have no tags set then clear the tag in the * next-to-leaf node, etc. * * Returns the address of the tagged item on success, else NULL. ie: * has the same return value and semantics as radix_tree_lookup(). */ void *radix_tree_tag_clear(struct radix_tree_root *root, unsigned long index, unsigned int tag) { struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path; struct radix_tree_node *slot; unsigned int height, shift; void *ret = NULL; height = root->height; if (index > radix_tree_maxindex(height)) goto out; shift = (height - 1) * RADIX_TREE_MAP_SHIFT; pathp->node = NULL; slot = root->rnode; while (height > 0) { int offset; if (slot == NULL) goto out; offset = (index >> shift) & RADIX_TREE_MAP_MASK; pathp[1].offset = offset; pathp[1].node = slot; slot = slot->slots[offset]; pathp++; shift -= RADIX_TREE_MAP_SHIFT; height--; } ret = slot; if (ret == NULL) goto out; do { if (!tag_get(pathp->node, tag, pathp->offset)) goto out; tag_clear(pathp->node, tag, pathp->offset); if (any_tag_set(pathp->node, tag)) goto out; pathp--; } while (pathp->node); out: return ret; } #endif static unsigned int __lookup(struct radix_tree_root *root, void **results, unsigned long index, unsigned int max_items, unsigned long *next_index) { unsigned int nr_found = 0; unsigned int shift, height; struct radix_tree_node *slot; unsigned long i; height = root->height; if (height == 0) goto out; shift = (height-1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; for ( ; height > 1; height--) { for (i = (index >> shift) & RADIX_TREE_MAP_MASK ; i < RADIX_TREE_MAP_SIZE; i++) { if (slot->slots[i] != NULL) break; index &= ~((1UL << shift) - 1); index += 1UL << shift; if (index == 0) goto out; /* 32-bit wraparound */ } if (i == RADIX_TREE_MAP_SIZE) goto out; shift -= RADIX_TREE_MAP_SHIFT; slot = slot->slots[i]; } /* Bottom level: grab some items */ for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) { index++; if (slot->slots[i]) { results[nr_found++] = slot->slots[i]; if (nr_found == max_items) goto out; } } out: *next_index = index; return nr_found; } /** * radix_tree_gang_lookup - perform multiple lookup on a radix tree * @root: radix tree root * @results: where the results of the lookup are placed * @first_index: start the lookup from this key * @max_items: place up to this many items at *results * * Performs an index-ascending scan of the tree for present items. Places * them at *@results and returns the number of items which were placed at * *@results. * * The implementation is naive. */ unsigned int radix_tree_gang_lookup(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items) { const unsigned long max_index = radix_tree_maxindex(root->height); unsigned long cur_index = first_index; unsigned int ret = 0; while (ret < max_items) { unsigned int nr_found; unsigned long next_index; /* Index of next search */ if (cur_index > max_index) break; nr_found = __lookup(root, results + ret, cur_index, max_items - ret, &next_index); ret += nr_found; if (next_index == 0) break; cur_index = next_index; } return ret; } /** * radix_tree_gang_lookup_ex - perform multiple lookup on a radix tree * @root: radix tree root * @results: where the results of the lookup are placed * @first_index: start the lookup from this key * @last_index: don't lookup past this key * @max_items: place up to this many items at *results * * Performs an index-ascending scan of the tree for present items starting * @first_index until @last_index up to as many as @max_items. Places * them at *@results and returns the number of items which were placed * at *@results. * * The implementation is naive. */ unsigned int radix_tree_gang_lookup_ex(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned long last_index, unsigned int max_items) { const unsigned long max_index = radix_tree_maxindex(root->height); unsigned long cur_index = first_index; unsigned int ret = 0; while (ret < max_items && cur_index < last_index) { unsigned int nr_found; unsigned long next_index; /* Index of next search */ if (cur_index > max_index) break; nr_found = __lookup(root, results + ret, cur_index, max_items - ret, &next_index); ret += nr_found; if (next_index == 0) break; cur_index = next_index; } return ret; } #ifdef RADIX_TREE_TAGS static unsigned int __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, unsigned int max_items, unsigned long *next_index, unsigned int tag) { unsigned int nr_found = 0; unsigned int shift; unsigned int height = root->height; struct radix_tree_node *slot; shift = (height - 1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; while (height > 0) { unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK; for ( ; i < RADIX_TREE_MAP_SIZE; i++) { if (tag_get(slot, tag, i)) { ASSERT(slot->slots[i] != NULL); break; } index &= ~((1UL << shift) - 1); index += 1UL << shift; if (index == 0) goto out; /* 32-bit wraparound */ } if (i == RADIX_TREE_MAP_SIZE) goto out; height--; if (height == 0) { /* Bottom level: grab some items */ unsigned long j = index & RADIX_TREE_MAP_MASK; for ( ; j < RADIX_TREE_MAP_SIZE; j++) { index++; if (tag_get(slot, tag, j)) { ASSERT(slot->slots[j] != NULL); results[nr_found++] = slot->slots[j]; if (nr_found == max_items) goto out; } } } shift -= RADIX_TREE_MAP_SHIFT; slot = slot->slots[i]; } out: *next_index = index; return nr_found; } /** * radix_tree_gang_lookup_tag - perform multiple lookup on a radix tree * based on a tag * @root: radix tree root * @results: where the results of the lookup are placed * @first_index: start the lookup from this key * @max_items: place up to this many items at *results * @tag: the tag index (< RADIX_TREE_MAX_TAGS) * * Performs an index-ascending scan of the tree for present items which * have the tag indexed by @tag set. Places the items at *@results and * returns the number of items which were placed at *@results. */ unsigned int radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items, unsigned int tag) { const unsigned long max_index = radix_tree_maxindex(root->height); unsigned long cur_index = first_index; unsigned int ret = 0; while (ret < max_items) { unsigned int nr_found; unsigned long next_index; /* Index of next search */ if (cur_index > max_index) break; nr_found = __lookup_tag(root, results + ret, cur_index, max_items - ret, &next_index, tag); ret += nr_found; if (next_index == 0) break; cur_index = next_index; } return ret; } #endif /** * radix_tree_shrink - shrink height of a radix tree to minimal * @root radix tree root */ static inline void radix_tree_shrink(struct radix_tree_root *root) { /* try to shrink tree height */ while (root->height > 1 && root->rnode->count == 1 && root->rnode->slots[0]) { struct radix_tree_node *to_free = root->rnode; root->rnode = to_free->slots[0]; root->height--; /* must only free zeroed nodes into the slab */ #ifdef RADIX_TREE_TAGS tag_clear(to_free, 0, 0); tag_clear(to_free, 1, 0); #endif to_free->slots[0] = NULL; to_free->count = 0; radix_tree_node_free(to_free); } } /** * radix_tree_delete - delete an item from a radix tree * @root: radix tree root * @index: index key * * Remove the item at @index from the radix tree rooted at @root. * * Returns the address of the deleted item, or NULL if it was not present. */ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) { struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path; struct radix_tree_path *orig_pathp; struct radix_tree_node *slot; unsigned int height, shift; void *ret = NULL; #ifdef RADIX_TREE_TAGS char tags[RADIX_TREE_MAX_TAGS]; int nr_cleared_tags; int tag; #endif int offset; height = root->height; if (index > radix_tree_maxindex(height)) goto out; shift = (height - 1) * RADIX_TREE_MAP_SHIFT; pathp->node = NULL; slot = root->rnode; for ( ; height > 0; height--) { if (slot == NULL) goto out; pathp++; offset = (index >> shift) & RADIX_TREE_MAP_MASK; pathp->offset = offset; pathp->node = slot; slot = slot->slots[offset]; shift -= RADIX_TREE_MAP_SHIFT; } ret = slot; if (ret == NULL) goto out; orig_pathp = pathp; #ifdef RADIX_TREE_TAGS /* * Clear all tags associated with the just-deleted item */ nr_cleared_tags = 0; for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { tags[tag] = 1; if (tag_get(pathp->node, tag, pathp->offset)) { tag_clear(pathp->node, tag, pathp->offset); if (!any_tag_set(pathp->node, tag)) { tags[tag] = 0; nr_cleared_tags++; } } } for (pathp--; nr_cleared_tags && pathp->node; pathp--) { for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { if (tags[tag]) continue; tag_clear(pathp->node, tag, pathp->offset); if (any_tag_set(pathp->node, tag)) { tags[tag] = 1; nr_cleared_tags--; } } } #endif /* Now free the nodes we do not need anymore */ for (pathp = orig_pathp; pathp->node; pathp--) { pathp->node->slots[pathp->offset] = NULL; pathp->node->count--; if (pathp->node->count) { if (pathp->node == root->rnode) radix_tree_shrink(root); goto out; } /* Node with zero slots in use so free it */ radix_tree_node_free(pathp->node); } root->rnode = NULL; root->height = 0; out: return ret; } #ifdef RADIX_TREE_TAGS /** * radix_tree_tagged - test whether any items in the tree are tagged * @root: radix tree root * @tag: tag to test */ int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag) { struct radix_tree_node *rnode; rnode = root->rnode; if (!rnode) return 0; return any_tag_set(rnode, tag); } #endif static unsigned long __maxindex(unsigned int height) { unsigned int width = height * RADIX_TREE_MAP_SHIFT; int shift = RADIX_TREE_INDEX_BITS - width; if (shift < 0) return ~0UL; if (shift >= BITS_PER_LONG) return 0UL; return ~0UL >> shift; } static void radix_tree_init_maxindex(void) { unsigned int i; for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++) height_to_maxindex[i] = __maxindex(i); } void radix_tree_init(void) { radix_tree_init_maxindex(); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/rdwr.c0000644000000000000000000010554313063067170015112 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "init.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "libxfs.h" /* for LIBXFS_EXIT_ON_FAILURE */ /* * Important design/architecture note: * * The userspace code that uses the buffer cache is much less constrained than * the kernel code. The userspace code is pretty nasty in places, especially * when it comes to buffer error handling. Very little of the userspace code * outside libxfs clears bp->b_error - very little code even checks it - so the * libxfs code is tripping on stale errors left by the userspace code. * * We can't clear errors or zero buffer contents in libxfs_getbuf-* like we do * in the kernel, because those functions are used by the libxfs_readbuf_* * functions and hence need to leave the buffers unchanged on cache hits. This * is actually the only way to gather a write error from a libxfs_writebuf() * call - you need to get the buffer again so you can check bp->b_error field - * assuming that the buffer is still in the cache when you check, that is. * * This is very different to the kernel code which does not release buffers on a * write so we can wait on IO and check errors. The kernel buffer cache also * guarantees a buffer of a known initial state from xfs_buf_get() even on a * cache hit. * * IOWs, userspace is behaving quite differently to the kernel and as a result * it leaks errors from reads, invalidations and writes through * libxfs_getbuf/libxfs_readbuf. * * The result of this is that until the userspace code outside libxfs is cleaned * up, functions that release buffers from userspace control (i.e * libxfs_writebuf/libxfs_putbuf) need to zero bp->b_error to prevent * propagation of stale errors into future buffer operations. */ #define BDSTRAT_SIZE (256 * 1024) #define IO_BCOMPARE_CHECK /* XXX: (dgc) Propagate errors, only exit if fail-on-error flag set */ int libxfs_device_zero(struct xfs_buftarg *btp, xfs_daddr_t start, uint len) { xfs_off_t start_offset, end_offset, offset; ssize_t zsize, bytes; char *z; int fd; zsize = min(BDSTRAT_SIZE, BBTOB(len)); if ((z = memalign(libxfs_device_alignment(), zsize)) == NULL) { fprintf(stderr, _("%s: %s can't memalign %d bytes: %s\n"), progname, __FUNCTION__, (int)zsize, strerror(errno)); exit(1); } memset(z, 0, zsize); fd = libxfs_device_to_fd(btp->dev); start_offset = LIBXFS_BBTOOFF64(start); if ((lseek(fd, start_offset, SEEK_SET)) < 0) { fprintf(stderr, _("%s: %s seek to offset %llu failed: %s\n"), progname, __FUNCTION__, (unsigned long long)start_offset, strerror(errno)); exit(1); } end_offset = LIBXFS_BBTOOFF64(start + len) - start_offset; for (offset = 0; offset < end_offset; ) { bytes = min((ssize_t)(end_offset - offset), zsize); if ((bytes = write(fd, z, bytes)) < 0) { fprintf(stderr, _("%s: %s write failed: %s\n"), progname, __FUNCTION__, strerror(errno)); exit(1); } else if (bytes == 0) { fprintf(stderr, _("%s: %s not progressing?\n"), progname, __FUNCTION__); exit(1); } offset += bytes; } free(z); return 0; } static void unmount_record(void *p) { xlog_op_header_t *op = (xlog_op_header_t *)p; /* the data section must be 32 bit size aligned */ struct { __uint16_t magic; __uint16_t pad1; __uint32_t pad2; /* may as well make it 64 bits */ } magic = { XLOG_UNMOUNT_TYPE, 0, 0 }; memset(p, 0, BBSIZE); /* dummy tid to mark this as written from userspace */ op->oh_tid = cpu_to_be32(0xb0c0d0d0); op->oh_len = cpu_to_be32(sizeof(magic)); op->oh_clientid = XFS_LOG; op->oh_flags = XLOG_UNMOUNT_TRANS; op->oh_res2 = 0; /* and the data for this op */ memcpy((char *)p + sizeof(xlog_op_header_t), &magic, sizeof(magic)); } static char *next( char *ptr, int offset, void *private) { struct xfs_buf *buf = (struct xfs_buf *)private; if (buf && (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset)) abort(); return ptr + offset; } /* * Format the log. The caller provides either a buftarg which is used to access * the log via buffers or a direct pointer to a buffer that encapsulates the * entire log. */ int libxfs_log_clear( struct xfs_buftarg *btp, char *dptr, xfs_daddr_t start, uint length, /* basic blocks */ uuid_t *fs_uuid, int version, int sunit, /* bytes */ int fmt, int cycle, bool max) { struct xfs_buf *bp = NULL; int len; xfs_lsn_t lsn; xfs_lsn_t tail_lsn; xfs_daddr_t blk; xfs_daddr_t end_blk; char *ptr; if (((btp && dptr) || (!btp && !dptr)) || (btp && !btp->dev) || !fs_uuid) return -EINVAL; /* first zero the log */ if (btp) libxfs_device_zero(btp, start, length); else memset(dptr, 0, BBTOB(length)); /* * Initialize the log record length and LSNs. XLOG_INIT_CYCLE is a * special reset case where we only write a single record where the lsn * and tail_lsn match. Otherwise, the record lsn starts at block 0 of * the specified cycle and points tail_lsn at the last record of the * previous cycle. */ len = ((version == 2) && sunit) ? BTOBB(sunit) : 2; len = MAX(len, 2); lsn = xlog_assign_lsn(cycle, 0); if (cycle == XLOG_INIT_CYCLE) tail_lsn = lsn; else tail_lsn = xlog_assign_lsn(cycle - 1, length - len); /* write out the first log record */ ptr = dptr; if (btp) { bp = libxfs_getbufr(btp, start, len); ptr = XFS_BUF_PTR(bp); } libxfs_log_header(ptr, fs_uuid, version, sunit, fmt, lsn, tail_lsn, next, bp); if (bp) { bp->b_flags |= LIBXFS_B_DIRTY; libxfs_putbufr(bp); } /* * There's nothing else to do if this is a log reset. The kernel detects * the rest of the log is zeroed and starts at cycle 1. */ if (cycle == XLOG_INIT_CYCLE) return 0; /* * Bump the record size for a full log format if the caller allows it. * This is primarily for performance reasons and most callers don't care * about record size since the log is clean after we're done. */ if (max) len = BTOBB(BDSTRAT_SIZE); /* * Otherwise, fill everything beyond the initial record with records of * the previous cycle so the kernel head/tail detection works correctly. * * We don't particularly care about the record size or content here. * It's only important that the headers are in place such that the * kernel finds 1.) a clean log and 2.) the correct current cycle value. * Therefore, bump up the record size to the max to use larger I/Os and * improve performance. */ cycle--; blk = start + len; if (dptr) dptr += BBTOB(len); end_blk = start + length; len = min(end_blk - blk, len); while (blk < end_blk) { lsn = xlog_assign_lsn(cycle, blk - start); tail_lsn = xlog_assign_lsn(cycle, blk - start - len); ptr = dptr; if (btp) { bp = libxfs_getbufr(btp, blk, len); ptr = XFS_BUF_PTR(bp); } /* * Note: pass the full buffer length as the sunit to initialize * the entire buffer. */ libxfs_log_header(ptr, fs_uuid, version, BBTOB(len), fmt, lsn, tail_lsn, next, bp); if (bp) { bp->b_flags |= LIBXFS_B_DIRTY; libxfs_putbufr(bp); } blk += len; if (dptr) dptr += BBTOB(len); len = min(end_blk - blk, len); } return 0; } int libxfs_log_header( char *caddr, uuid_t *fs_uuid, int version, int sunit, int fmt, xfs_lsn_t lsn, xfs_lsn_t tail_lsn, libxfs_get_block_t *nextfunc, void *private) { xlog_rec_header_t *head = (xlog_rec_header_t *)caddr; char *p = caddr; __be32 cycle_lsn; int i, len; int hdrs = 1; if (lsn == NULLCOMMITLSN) lsn = xlog_assign_lsn(XLOG_INIT_CYCLE, 0); if (tail_lsn == NULLCOMMITLSN) tail_lsn = lsn; len = ((version == 2) && sunit) ? BTOBB(sunit) : 1; memset(p, 0, BBSIZE); head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM); head->h_cycle = cpu_to_be32(CYCLE_LSN(lsn)); head->h_version = cpu_to_be32(version); head->h_crc = cpu_to_le32(0); head->h_prev_block = cpu_to_be32(-1); head->h_num_logops = cpu_to_be32(1); head->h_fmt = cpu_to_be32(fmt); head->h_size = cpu_to_be32(MAX(sunit, XLOG_BIG_RECORD_BSIZE)); head->h_lsn = cpu_to_be64(lsn); head->h_tail_lsn = cpu_to_be64(tail_lsn); memcpy(&head->h_fs_uuid, fs_uuid, sizeof(uuid_t)); /* * The kernel expects to see either a log record header magic value or * the LSN cycle at the top of every log block. The first word of each * non-header block is copied to the record headers and replaced with * the cycle value (see xlog_[un]pack_data() and xlog_get_cycle() for * details). * * Even though we only ever write an unmount record (one block), we * support writing log records up to the max log buffer size of 256k to * improve log format performance. This means a record can require up * to 8 headers (1 rec. header + 7 ext. headers) for the packed cycle * data (each header supports 32k of data). */ cycle_lsn = CYCLE_LSN_DISK(head->h_lsn); if (version == 2 && sunit > XLOG_HEADER_CYCLE_SIZE) { hdrs = sunit / XLOG_HEADER_CYCLE_SIZE; if (sunit % XLOG_HEADER_CYCLE_SIZE) hdrs++; } /* * A fixed number of extended headers is expected based on h_size. If * required, format those now so the unmount record is located * correctly. * * Since we only write an unmount record, we only need one h_cycle_data * entry for the unmount record block. The subsequent record data * blocks are zeroed, which means we can stamp them directly with the * cycle and zero the rest of the cycle data in the extended headers. */ if (hdrs > 1) { for (i = 1; i < hdrs; i++) { p = nextfunc(p, BBSIZE, private); memset(p, 0, BBSIZE); /* xlog_rec_ext_header.xh_cycle */ *(__be32 *)p = cycle_lsn; } } /* * The total length is the max of the stripe unit or 2 basic block * minimum (1 hdr blk + 1 data blk). The record length is the total * minus however many header blocks are required. */ head->h_len = cpu_to_be32(MAX(BBTOB(2), sunit) - hdrs * BBSIZE); /* * Write out the unmount record, pack the first word into the record * header and stamp the block with the cycle. */ p = nextfunc(p, BBSIZE, private); unmount_record(p); head->h_cycle_data[0] = *(__be32 *)p; *(__be32 *)p = cycle_lsn; /* * Finally, zero all remaining blocks in the record and stamp each with * the cycle. We don't need to pack any of these blocks because the * cycle data in the headers has already been zeroed. */ len = MAX(len, hdrs + 1); for (i = hdrs + 1; i < len; i++) { p = nextfunc(p, BBSIZE, private); memset(p, 0, BBSIZE); *(__be32 *)p = cycle_lsn; } return BBTOB(len); } /* * Simple I/O (buffer cache) interface */ #ifdef XFS_BUF_TRACING #undef libxfs_readbuf #undef libxfs_readbuf_map #undef libxfs_writebuf #undef libxfs_getbuf #undef libxfs_getbuf_map #undef libxfs_getbuf_flags #undef libxfs_putbuf xfs_buf_t *libxfs_readbuf(struct xfs_buftarg *, xfs_daddr_t, int, int, const struct xfs_buf_ops *); xfs_buf_t *libxfs_readbuf_map(struct xfs_buftarg *, struct xfs_buf_map *, int, int, const struct xfs_buf_ops *); int libxfs_writebuf(xfs_buf_t *, int); xfs_buf_t *libxfs_getbuf(struct xfs_buftarg *, xfs_daddr_t, int); xfs_buf_t *libxfs_getbuf_map(struct xfs_buftarg *, struct xfs_buf_map *, int, int); xfs_buf_t *libxfs_getbuf_flags(struct xfs_buftarg *, xfs_daddr_t, int, unsigned int); void libxfs_putbuf (xfs_buf_t *); #define __add_trace(bp, func, file, line) \ do { \ if (bp) { \ (bp)->b_func = (func); \ (bp)->b_file = (file); \ (bp)->b_line = (line); \ } \ } while (0) xfs_buf_t * libxfs_trace_readbuf(const char *func, const char *file, int line, struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, int flags, const struct xfs_buf_ops *ops) { xfs_buf_t *bp = libxfs_readbuf(btp, blkno, len, flags, ops); __add_trace(bp, func, file, line); return bp; } xfs_buf_t * libxfs_trace_readbuf_map(const char *func, const char *file, int line, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, int flags, const struct xfs_buf_ops *ops) { xfs_buf_t *bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops); __add_trace(bp, func, file, line); return bp; } int libxfs_trace_writebuf(const char *func, const char *file, int line, xfs_buf_t *bp, int flags) { __add_trace(bp, func, file, line); return libxfs_writebuf(bp, flags); } xfs_buf_t * libxfs_trace_getbuf(const char *func, const char *file, int line, struct xfs_buftarg *btp, xfs_daddr_t blkno, int len) { xfs_buf_t *bp = libxfs_getbuf(btp, blkno, len); __add_trace(bp, func, file, line); return bp; } xfs_buf_t * libxfs_trace_getbuf_map(const char *func, const char *file, int line, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, int flags) { xfs_buf_t *bp = libxfs_getbuf_map(btp, map, nmaps, flags); __add_trace(bp, func, file, line); return bp; } xfs_buf_t * libxfs_trace_getbuf_flags(const char *func, const char *file, int line, struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, unsigned int flags) { xfs_buf_t *bp = libxfs_getbuf_flags(btp, blkno, len, flags); __add_trace(bp, func, file, line); return bp; } void libxfs_trace_putbuf(const char *func, const char *file, int line, xfs_buf_t *bp) { __add_trace(bp, func, file, line); libxfs_putbuf(bp); } #endif xfs_buf_t * libxfs_getsb(xfs_mount_t *mp, int flags) { return libxfs_readbuf(mp->m_ddev_targp, XFS_SB_DADDR, XFS_FSS_TO_BB(mp, 1), flags, &xfs_sb_buf_ops); } kmem_zone_t *xfs_buf_zone; static struct cache_mru xfs_buf_freelist = {{&xfs_buf_freelist.cm_list, &xfs_buf_freelist.cm_list}, 0, PTHREAD_MUTEX_INITIALIZER }; /* * The bufkey is used to pass the new buffer information to the cache object * allocation routine. Because discontiguous buffers need to pass different * information, we need fields to pass that information. However, because the * blkno and bblen is needed for the initial cache entry lookup (i.e. for * bcompare) the fact that the map/nmaps is non-null to switch to discontiguous * buffer initialisation instead of a contiguous buffer. */ struct xfs_bufkey { struct xfs_buftarg *buftarg; xfs_daddr_t blkno; unsigned int bblen; struct xfs_buf_map *map; int nmaps; }; /* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */ #define GOLDEN_RATIO_PRIME 0x9e37fffffffc0001UL #define CACHE_LINE_SIZE 64 static unsigned int libxfs_bhash(cache_key_t key, unsigned int hashsize, unsigned int hashshift) { uint64_t hashval = ((struct xfs_bufkey *)key)->blkno; uint64_t tmp; tmp = hashval ^ (GOLDEN_RATIO_PRIME + hashval) / CACHE_LINE_SIZE; tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> hashshift); return tmp % hashsize; } static int libxfs_bcompare(struct cache_node *node, cache_key_t key) { struct xfs_buf *bp = (struct xfs_buf *)node; struct xfs_bufkey *bkey = (struct xfs_bufkey *)key; if (bp->b_target->dev == bkey->buftarg->dev && bp->b_bn == bkey->blkno) { if (bp->b_bcount == BBTOB(bkey->bblen)) return CACHE_HIT; #ifdef IO_BCOMPARE_CHECK if (!(libxfs_bcache->c_flags & CACHE_MISCOMPARE_PURGE)) { fprintf(stderr, "%lx: Badness in key lookup (length)\n" "bp=(bno 0x%llx, len %u bytes) key=(bno 0x%llx, len %u bytes)\n", pthread_self(), (unsigned long long)bp->b_bn, (int)bp->b_bcount, (unsigned long long)bkey->blkno, BBTOB(bkey->bblen)); } #endif return CACHE_PURGE; } return CACHE_MISS; } void libxfs_bprint(xfs_buf_t *bp) { fprintf(stderr, "Buffer 0x%p blkno=%llu bytes=%u flags=0x%x count=%u\n", bp, (unsigned long long)bp->b_bn, (unsigned)bp->b_bcount, bp->b_flags, bp->b_node.cn_count); } static void __initbuf(xfs_buf_t *bp, struct xfs_buftarg *btp, xfs_daddr_t bno, unsigned int bytes) { bp->b_flags = 0; bp->b_bn = bno; bp->b_bcount = bytes; bp->b_length = BTOBB(bytes); bp->b_target = btp; bp->b_error = 0; if (!bp->b_addr) bp->b_addr = memalign(libxfs_device_alignment(), bytes); if (!bp->b_addr) { fprintf(stderr, _("%s: %s can't memalign %u bytes: %s\n"), progname, __FUNCTION__, bytes, strerror(errno)); exit(1); } memset(bp->b_addr, 0, bytes); #ifdef XFS_BUF_TRACING list_head_init(&bp->b_lock_list); #endif pthread_mutex_init(&bp->b_lock, NULL); bp->b_holder = 0; bp->b_recur = 0; bp->b_ops = NULL; } static void libxfs_initbuf(xfs_buf_t *bp, struct xfs_buftarg *btp, xfs_daddr_t bno, unsigned int bytes) { __initbuf(bp, btp, bno, bytes); } static void libxfs_initbuf_map(xfs_buf_t *bp, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps) { unsigned int bytes = 0; int i; bytes = sizeof(struct xfs_buf_map) * nmaps; bp->b_maps = malloc(bytes); if (!bp->b_maps) { fprintf(stderr, _("%s: %s can't malloc %u bytes: %s\n"), progname, __FUNCTION__, bytes, strerror(errno)); exit(1); } bp->b_nmaps = nmaps; bytes = 0; for ( i = 0; i < nmaps; i++) { bp->b_maps[i].bm_bn = map[i].bm_bn; bp->b_maps[i].bm_len = map[i].bm_len; bytes += BBTOB(map[i].bm_len); } __initbuf(bp, btp, map[0].bm_bn, bytes); bp->b_flags |= LIBXFS_B_DISCONTIG; } xfs_buf_t * __libxfs_getbufr(int blen) { xfs_buf_t *bp; /* * first look for a buffer that can be used as-is, * if one cannot be found, see if there is a buffer, * and if so, free its buffer and set b_addr to NULL * before calling libxfs_initbuf. */ pthread_mutex_lock(&xfs_buf_freelist.cm_mutex); if (!list_empty(&xfs_buf_freelist.cm_list)) { list_for_each_entry(bp, &xfs_buf_freelist.cm_list, b_node.cn_mru) { if (bp->b_bcount == blen) { list_del_init(&bp->b_node.cn_mru); break; } } if (&bp->b_node.cn_mru == &xfs_buf_freelist.cm_list) { bp = list_entry(xfs_buf_freelist.cm_list.next, xfs_buf_t, b_node.cn_mru); list_del_init(&bp->b_node.cn_mru); free(bp->b_addr); bp->b_addr = NULL; free(bp->b_maps); bp->b_maps = NULL; } } else bp = kmem_zone_zalloc(xfs_buf_zone, 0); pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex); bp->b_ops = NULL; if (bp->b_flags & LIBXFS_B_DIRTY) fprintf(stderr, "found dirty buffer (bulk) on free list!"); return bp; } xfs_buf_t * libxfs_getbufr(struct xfs_buftarg *btp, xfs_daddr_t blkno, int bblen) { xfs_buf_t *bp; int blen = BBTOB(bblen); bp =__libxfs_getbufr(blen); if (bp) libxfs_initbuf(bp, btp, blkno, blen); #ifdef IO_DEBUG printf("%lx: %s: allocated %u bytes buffer, key=0x%llx(0x%llx), %p\n", pthread_self(), __FUNCTION__, blen, (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp); #endif return bp; } xfs_buf_t * libxfs_getbufr_map(struct xfs_buftarg *btp, xfs_daddr_t blkno, int bblen, struct xfs_buf_map *map, int nmaps) { xfs_buf_t *bp; int blen = BBTOB(bblen); if (!map || !nmaps) { fprintf(stderr, _("%s: %s invalid map %p or nmaps %d\n"), progname, __FUNCTION__, map, nmaps); exit(1); } if (blkno != map[0].bm_bn) { fprintf(stderr, _("%s: %s map blkno 0x%llx doesn't match key 0x%llx\n"), progname, __FUNCTION__, (long long)map[0].bm_bn, (long long)blkno); exit(1); } bp =__libxfs_getbufr(blen); if (bp) libxfs_initbuf_map(bp, btp, map, nmaps); #ifdef IO_DEBUG printf("%lx: %s: allocated %u bytes buffer, key=0x%llx(0x%llx), %p\n", pthread_self(), __FUNCTION__, blen, (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp); #endif return bp; } #ifdef XFS_BUF_TRACING struct list_head lock_buf_list = {&lock_buf_list, &lock_buf_list}; int lock_buf_count = 0; #endif extern int use_xfs_buf_lock; static struct xfs_buf * __cache_lookup(struct xfs_bufkey *key, unsigned int flags) { struct xfs_buf *bp; cache_node_get(libxfs_bcache, key, (struct cache_node **)&bp); if (!bp) return NULL; if (use_xfs_buf_lock) { int ret; ret = pthread_mutex_trylock(&bp->b_lock); if (ret) { ASSERT(ret == EAGAIN); if (flags & LIBXFS_GETBUF_TRYLOCK) goto out_put; if (pthread_equal(bp->b_holder, pthread_self())) { fprintf(stderr, _("Warning: recursive buffer locking at block %" PRIu64 " detected\n"), key->blkno); bp->b_recur++; return bp; } else { pthread_mutex_lock(&bp->b_lock); } } bp->b_holder = pthread_self(); } cache_node_set_priority(libxfs_bcache, (struct cache_node *)bp, cache_node_get_priority((struct cache_node *)bp) - CACHE_PREFETCH_PRIORITY); #ifdef XFS_BUF_TRACING pthread_mutex_lock(&libxfs_bcache->c_mutex); lock_buf_count++; list_add(&bp->b_lock_list, &lock_buf_list); pthread_mutex_unlock(&libxfs_bcache->c_mutex); #endif #ifdef IO_DEBUG printf("%lx %s: hit buffer %p for bno = 0x%llx/0x%llx\n", pthread_self(), __FUNCTION__, bp, bp->b_bn, (long long)LIBXFS_BBTOOFF64(key->blkno)); #endif return bp; out_put: cache_node_put(libxfs_bcache, (struct cache_node *)bp); return NULL; } struct xfs_buf * libxfs_getbuf_flags(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, unsigned int flags) { struct xfs_bufkey key = {0}; key.buftarg = btp; key.blkno = blkno; key.bblen = len; return __cache_lookup(&key, flags); } /* * Clean the buffer flags for libxfs_getbuf*(), which wants to return * an unused buffer with clean state. This prevents CRC errors on a * re-read of a corrupt block that was prefetched and freed. This * can happen with a massively corrupt directory that is discarded, * but whose blocks are then recycled into expanding lost+found. * * Note however that if the buffer's dirty (prefetch calls getbuf) * we'll leave the state alone because we don't want to discard blocks * that have been fixed. */ static void reset_buf_state( struct xfs_buf *bp) { if (bp && !(bp->b_flags & LIBXFS_B_DIRTY)) bp->b_flags &= ~(LIBXFS_B_UNCHECKED | LIBXFS_B_STALE | LIBXFS_B_UPTODATE); } struct xfs_buf * libxfs_getbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len) { struct xfs_buf *bp; bp = libxfs_getbuf_flags(btp, blkno, len, 0); reset_buf_state(bp); return bp; } static struct xfs_buf * __libxfs_getbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, int flags) { struct xfs_bufkey key = {0}; int i; if (nmaps == 1) return libxfs_getbuf_flags(btp, map[0].bm_bn, map[0].bm_len, flags); key.buftarg = btp; key.blkno = map[0].bm_bn; for (i = 0; i < nmaps; i++) { key.bblen += map[i].bm_len; } key.map = map; key.nmaps = nmaps; return __cache_lookup(&key, flags); } struct xfs_buf * libxfs_getbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, int flags) { struct xfs_buf *bp; bp = __libxfs_getbuf_map(btp, map, nmaps, flags); reset_buf_state(bp); return bp; } void libxfs_putbuf(xfs_buf_t *bp) { /* * ensure that any errors on this use of the buffer don't carry * over to the next user. */ bp->b_error = 0; #ifdef XFS_BUF_TRACING pthread_mutex_lock(&libxfs_bcache->c_mutex); lock_buf_count--; ASSERT(lock_buf_count >= 0); list_del_init(&bp->b_lock_list); pthread_mutex_unlock(&libxfs_bcache->c_mutex); #endif if (use_xfs_buf_lock) { if (bp->b_recur) { bp->b_recur--; } else { bp->b_holder = 0; pthread_mutex_unlock(&bp->b_lock); } } cache_node_put(libxfs_bcache, (struct cache_node *)bp); } void libxfs_purgebuf(xfs_buf_t *bp) { struct xfs_bufkey key = {0}; key.buftarg = bp->b_target; key.blkno = bp->b_bn; key.bblen = bp->b_length; cache_node_purge(libxfs_bcache, &key, (struct cache_node *)bp); } static struct cache_node * libxfs_balloc(cache_key_t key) { struct xfs_bufkey *bufkey = (struct xfs_bufkey *)key; if (bufkey->map) return (struct cache_node *) libxfs_getbufr_map(bufkey->buftarg, bufkey->blkno, bufkey->bblen, bufkey->map, bufkey->nmaps); return (struct cache_node *)libxfs_getbufr(bufkey->buftarg, bufkey->blkno, bufkey->bblen); } static int __read_buf(int fd, void *buf, int len, off64_t offset, int flags) { int sts; sts = pread(fd, buf, len, offset); if (sts < 0) { int error = errno; fprintf(stderr, _("%s: read failed: %s\n"), progname, strerror(error)); if (flags & LIBXFS_EXIT_ON_FAILURE) exit(1); return -error; } else if (sts != len) { fprintf(stderr, _("%s: error - read only %d of %d bytes\n"), progname, sts, len); if (flags & LIBXFS_EXIT_ON_FAILURE) exit(1); return -EIO; } return 0; } int libxfs_readbufr(struct xfs_buftarg *btp, xfs_daddr_t blkno, xfs_buf_t *bp, int len, int flags) { int fd = libxfs_device_to_fd(btp->dev); int bytes = BBTOB(len); int error; ASSERT(BBTOB(len) <= bp->b_bcount); error = __read_buf(fd, bp->b_addr, bytes, LIBXFS_BBTOOFF64(blkno), flags); if (!error && bp->b_target->dev == btp->dev && bp->b_bn == blkno && bp->b_bcount == bytes) bp->b_flags |= LIBXFS_B_UPTODATE; #ifdef IO_DEBUG printf("%lx: %s: read %u bytes, error %d, blkno=0x%llx(0x%llx), %p\n", pthread_self(), __FUNCTION__, bytes, error, (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp); #endif return error; } void libxfs_readbuf_verify(struct xfs_buf *bp, const struct xfs_buf_ops *ops) { if (!ops) return; bp->b_ops = ops; bp->b_ops->verify_read(bp); bp->b_flags &= ~LIBXFS_B_UNCHECKED; } xfs_buf_t * libxfs_readbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, int flags, const struct xfs_buf_ops *ops) { xfs_buf_t *bp; int error; bp = libxfs_getbuf_flags(btp, blkno, len, 0); if (!bp) return NULL; /* * if the buffer was prefetched, it is likely that it was not validated. * Hence if we are supplied an ops function and the buffer is marked as * unchecked, we need to validate it now. * * We do this verification even if the buffer is dirty - the * verification is almost certainly going to fail the CRC check in this * case as a dirty buffer has not had the CRC recalculated. However, we * should not be dirtying unchecked buffers and therefore failing it * here because it's dirty and unchecked indicates we've screwed up * somewhere else. */ bp->b_error = 0; if ((bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY))) { if (bp->b_flags & LIBXFS_B_UNCHECKED) libxfs_readbuf_verify(bp, ops); return bp; } /* * Set the ops on a cache miss (i.e. first physical read) as the * verifier may change the ops to match the type of buffer it contains. * A cache hit might reset the verifier to the original type if we set * it again, but it won't get called again and set to match the buffer * contents. *cough* xfs_da_node_buf_ops *cough*. */ error = libxfs_readbufr(btp, blkno, bp, len, flags); if (error) bp->b_error = error; else libxfs_readbuf_verify(bp, ops); return bp; } int libxfs_readbufr_map(struct xfs_buftarg *btp, struct xfs_buf *bp, int flags) { int fd; int error = 0; char *buf; int i; fd = libxfs_device_to_fd(btp->dev); buf = bp->b_addr; for (i = 0; i < bp->b_nmaps; i++) { off64_t offset = LIBXFS_BBTOOFF64(bp->b_maps[i].bm_bn); int len = BBTOB(bp->b_maps[i].bm_len); error = __read_buf(fd, buf, len, offset, flags); if (error) { bp->b_error = error; break; } buf += len; } if (!error) bp->b_flags |= LIBXFS_B_UPTODATE; #ifdef IO_DEBUG printf("%lx: %s: read %lu bytes, error %d, blkno=%llu(%llu), %p\n", pthread_self(), __FUNCTION__, buf - (char *)bp->b_addr, error, (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn, bp); #endif return error; } struct xfs_buf * libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, int flags, const struct xfs_buf_ops *ops) { struct xfs_buf *bp; int error = 0; if (nmaps == 1) return libxfs_readbuf(btp, map[0].bm_bn, map[0].bm_len, flags, ops); bp = __libxfs_getbuf_map(btp, map, nmaps, 0); if (!bp) return NULL; bp->b_error = 0; if ((bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY))) { if (bp->b_flags & LIBXFS_B_UNCHECKED) libxfs_readbuf_verify(bp, ops); return bp; } error = libxfs_readbufr_map(btp, bp, flags); if (!error) libxfs_readbuf_verify(bp, ops); #ifdef IO_DEBUGX printf("%lx: %s: read %lu bytes, error %d, blkno=%llu(%llu), %p\n", pthread_self(), __FUNCTION__, buf - (char *)bp->b_addr, error, (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn, bp); #endif return bp; } static int __write_buf(int fd, void *buf, int len, off64_t offset, int flags) { int sts; sts = pwrite(fd, buf, len, offset); if (sts < 0) { int error = errno; fprintf(stderr, _("%s: pwrite failed: %s\n"), progname, strerror(error)); if (flags & LIBXFS_B_EXIT) exit(1); return -error; } else if (sts != len) { fprintf(stderr, _("%s: error - pwrite only %d of %d bytes\n"), progname, sts, len); if (flags & LIBXFS_B_EXIT) exit(1); return -EIO; } return 0; } int libxfs_writebufr(xfs_buf_t *bp) { int fd = libxfs_device_to_fd(bp->b_target->dev); /* * we never write buffers that are marked stale. This indicates they * contain data that has been invalidated, and even if the buffer is * dirty it must *never* be written. Verifiers are wonderful for finding * bugs like this. Make sure the error is obvious as to the cause. */ if (bp->b_flags & LIBXFS_B_STALE) { bp->b_error = -ESTALE; return bp->b_error; } /* * clear any pre-existing error status on the buffer. This can occur if * the buffer is corrupt on disk and the repair process doesn't clear * the error before fixing and writing it back. */ bp->b_error = 0; if (bp->b_ops) { bp->b_ops->verify_write(bp); if (bp->b_error) { fprintf(stderr, _("%s: write verifer failed on %s bno 0x%llx/0x%x\n"), __func__, bp->b_ops->name, (long long)bp->b_bn, bp->b_bcount); return bp->b_error; } } if (!(bp->b_flags & LIBXFS_B_DISCONTIG)) { bp->b_error = __write_buf(fd, bp->b_addr, bp->b_bcount, LIBXFS_BBTOOFF64(bp->b_bn), bp->b_flags); } else { int i; char *buf = bp->b_addr; for (i = 0; i < bp->b_nmaps; i++) { off64_t offset = LIBXFS_BBTOOFF64(bp->b_maps[i].bm_bn); int len = BBTOB(bp->b_maps[i].bm_len); bp->b_error = __write_buf(fd, buf, len, offset, bp->b_flags); if (bp->b_error) break; buf += len; } } #ifdef IO_DEBUG printf("%lx: %s: wrote %u bytes, blkno=%llu(%llu), %p, error %d\n", pthread_self(), __FUNCTION__, bp->b_bcount, (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn, bp, bp->b_error); #endif if (!bp->b_error) { bp->b_flags |= LIBXFS_B_UPTODATE; bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_EXIT | LIBXFS_B_UNCHECKED); } return bp->b_error; } int libxfs_writebuf_int(xfs_buf_t *bp, int flags) { /* * Clear any error hanging over from reading the buffer. This prevents * subsequent reads after this write from seeing stale errors. */ bp->b_error = 0; bp->b_flags &= ~LIBXFS_B_STALE; bp->b_flags |= (LIBXFS_B_DIRTY | flags); return 0; } int libxfs_writebuf(xfs_buf_t *bp, int flags) { #ifdef IO_DEBUG printf("%lx: %s: dirty blkno=%llu(%llu)\n", pthread_self(), __FUNCTION__, (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn); #endif /* * Clear any error hanging over from reading the buffer. This prevents * subsequent reads after this write from seeing stale errors. */ bp->b_error = 0; bp->b_flags &= ~LIBXFS_B_STALE; bp->b_flags |= (LIBXFS_B_DIRTY | flags); libxfs_putbuf(bp); return 0; } void libxfs_iomove(xfs_buf_t *bp, uint boff, int len, void *data, int flags) { #ifdef IO_DEBUG if (boff + len > bp->b_bcount) { printf("Badness, iomove out of range!\n" "bp=(bno 0x%llx, bytes %u) range=(boff %u, bytes %u)\n", (long long)bp->b_bn, bp->b_bcount, boff, len); abort(); } #endif switch (flags) { case LIBXFS_BZERO: memset(bp->b_addr + boff, 0, len); break; case LIBXFS_BREAD: memcpy(data, bp->b_addr + boff, len); break; case LIBXFS_BWRITE: memcpy(bp->b_addr + boff, data, len); break; } } static void libxfs_brelse( struct cache_node *node) { struct xfs_buf *bp = (struct xfs_buf *)node; if (!bp) return; if (bp->b_flags & LIBXFS_B_DIRTY) fprintf(stderr, "releasing dirty buffer to free list!"); pthread_mutex_lock(&xfs_buf_freelist.cm_mutex); list_add(&bp->b_node.cn_mru, &xfs_buf_freelist.cm_list); pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex); } static unsigned int libxfs_bulkrelse( struct cache *cache, struct list_head *list) { xfs_buf_t *bp; int count = 0; if (list_empty(list)) return 0 ; list_for_each_entry(bp, list, b_node.cn_mru) { if (bp->b_flags & LIBXFS_B_DIRTY) fprintf(stderr, "releasing dirty buffer (bulk) to free list!"); count++; } pthread_mutex_lock(&xfs_buf_freelist.cm_mutex); list_splice(list, &xfs_buf_freelist.cm_list); pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex); return count; } /* * When a buffer is marked dirty, the error is cleared. Hence if we are trying * to flush a buffer prior to cache reclaim that has an error on it it means * we've already tried to flush it and it failed. Prevent repeated corruption * errors from being reported by skipping such buffers - when the corruption is * fixed the buffer will be marked dirty again and we can write it again. */ static int libxfs_bflush( struct cache_node *node) { struct xfs_buf *bp = (struct xfs_buf *)node; if (!bp->b_error && bp->b_flags & LIBXFS_B_DIRTY) return libxfs_writebufr(bp); return bp->b_error; } void libxfs_putbufr(xfs_buf_t *bp) { if (bp->b_flags & LIBXFS_B_DIRTY) libxfs_writebufr(bp); libxfs_brelse((struct cache_node *)bp); } void libxfs_bcache_purge(void) { cache_purge(libxfs_bcache); } void libxfs_bcache_flush(void) { cache_flush(libxfs_bcache); } int libxfs_bcache_overflowed(void) { return cache_overflowed(libxfs_bcache); } struct cache_operations libxfs_bcache_operations = { .hash = libxfs_bhash, .alloc = libxfs_balloc, .flush = libxfs_bflush, .relse = libxfs_brelse, .compare = libxfs_bcompare, .bulkrelse = libxfs_bulkrelse }; /* * Inode cache stubs. */ extern kmem_zone_t *xfs_ili_zone; extern kmem_zone_t *xfs_inode_zone; int libxfs_iget(xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint lock_flags, xfs_inode_t **ipp) { xfs_inode_t *ip; int error = 0; ip = kmem_zone_zalloc(xfs_inode_zone, 0); if (!ip) return -ENOMEM; ip->i_ino = ino; ip->i_mount = mp; error = xfs_iread(mp, tp, ip, 0); if (error) { kmem_zone_free(xfs_inode_zone, ip); *ipp = NULL; return error; } /* * set up the inode ops structure that the libxfs code relies on */ if (XFS_ISDIR(ip)) ip->d_ops = mp->m_dir_inode_ops; else ip->d_ops = mp->m_nondir_inode_ops; *ipp = ip; return 0; } static void libxfs_idestroy(xfs_inode_t *ip) { switch (VFS_I(ip)->i_mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFLNK: libxfs_idestroy_fork(ip, XFS_DATA_FORK); break; } if (ip->i_afp) libxfs_idestroy_fork(ip, XFS_ATTR_FORK); if (ip->i_cowfp) xfs_idestroy_fork(ip, XFS_COW_FORK); } void libxfs_iput(xfs_inode_t *ip) { if (ip->i_itemp) kmem_zone_free(xfs_ili_zone, ip->i_itemp); ip->i_itemp = NULL; libxfs_idestroy(ip); kmem_zone_free(xfs_inode_zone, ip); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/trans.c0000644000000000000000000004640513063067171015265 0ustar /* * Copyright (c) 2000-2001,2005-2006 Silicon Graphics, Inc. * Copyright (C) 2010 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_sb.h" static void xfs_trans_free_items(struct xfs_trans *tp); /* * Simple transaction interface */ kmem_zone_t *xfs_log_item_desc_zone; /* * Initialize the precomputed transaction reservation values * in the mount structure. */ void libxfs_trans_init( struct xfs_mount *mp) { xfs_trans_resv_calc(mp, &mp->m_resv); } /* * Add the given log item to the transaction's list of log items. * * The log item will now point to its new descriptor with its li_desc field. */ void libxfs_trans_add_item( struct xfs_trans *tp, struct xfs_log_item *lip) { struct xfs_log_item_desc *lidp; ASSERT(lip->li_mountp == tp->t_mountp); ASSERT(lip->li_ailp == tp->t_mountp->m_ail); lidp = calloc(sizeof(struct xfs_log_item_desc), 1); if (!lidp) { fprintf(stderr, _("%s: lidp calloc failed (%d bytes): %s\n"), progname, (int)sizeof(struct xfs_log_item_desc), strerror(errno)); exit(1); } lidp->lid_item = lip; lidp->lid_flags = 0; list_add_tail(&lidp->lid_trans, &tp->t_items); lip->li_desc = lidp; } /* * Unlink and free the given descriptor. */ void libxfs_trans_del_item( struct xfs_log_item *lip) { list_del_init(&lip->li_desc->lid_trans); free(lip->li_desc); lip->li_desc = NULL; } /* * Roll from one trans in the sequence of PERMANENT transactions to * the next: permanent transactions are only flushed out when * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon * as possible to let chunks of it go to the log. So we commit the * chunk we've been working on and get a new transaction to continue. */ int libxfs_trans_roll( struct xfs_trans **tpp, struct xfs_inode *dp) { struct xfs_mount *mp; struct xfs_trans *trans; struct xfs_trans_res tres; int error; /* * Ensure that the inode is always logged. */ trans = *tpp; if (dp) xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); /* * Copy the critical parameters from one trans to the next. */ mp = trans->t_mountp; tres.tr_logres = trans->t_log_res; tres.tr_logcount = trans->t_log_count; /* * Commit the current transaction. * If this commit failed, then it'd just unlock those items that * are marked to be released. That also means that a filesystem shutdown * is in progress. The caller takes the responsibility to cancel * the duplicate transaction that gets returned. */ error = xfs_trans_commit(trans); if (error) return error; /* * Reserve space in the log for th next transaction. * This also pushes items in the "AIL", the list of logged items, * out to disk if they are taking up space at the tail of the log * that we want to use. This requires that either nothing be locked * across this call, or that anything that is locked be logged in * the prior and the next transactions. */ tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; error = libxfs_trans_alloc(mp, &tres, 0, 0, 0, tpp); trans = *tpp; /* * Ensure that the inode is in the new transaction and locked. */ if (error) return error; if (dp) xfs_trans_ijoin(trans, dp, 0); return 0; } int libxfs_trans_alloc( struct xfs_mount *mp, struct xfs_trans_res *resp, unsigned int blocks, unsigned int rtextents, unsigned int flags, struct xfs_trans **tpp) { struct xfs_sb *sb = &mp->m_sb; struct xfs_trans *ptr; /* * Attempt to reserve the needed disk blocks by decrementing * the number needed from the number available. This will * fail if the count would go below zero. */ if (blocks > 0) { if (sb->sb_fdblocks < blocks) return -ENOSPC; } if ((ptr = calloc(sizeof(xfs_trans_t), 1)) == NULL) { fprintf(stderr, _("%s: xact calloc failed (%d bytes): %s\n"), progname, (int)sizeof(xfs_trans_t), strerror(errno)); exit(1); } ptr->t_mountp = mp; INIT_LIST_HEAD(&ptr->t_items); #ifdef XACT_DEBUG fprintf(stderr, "allocated new transaction %p\n", ptr); #endif *tpp = ptr; return 0; } void libxfs_trans_cancel( xfs_trans_t *tp) { #ifdef XACT_DEBUG xfs_trans_t *otp = tp; #endif if (tp != NULL) { xfs_trans_free_items(tp); free(tp); tp = NULL; } #ifdef XACT_DEBUG fprintf(stderr, "## cancelled transaction %p\n", otp); #endif } int libxfs_trans_iget( xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint flags, uint lock_flags, xfs_inode_t **ipp) { int error; xfs_inode_t *ip; xfs_inode_log_item_t *iip; if (tp == NULL) return libxfs_iget(mp, tp, ino, lock_flags, ipp); error = libxfs_iget(mp, tp, ino, lock_flags, &ip); if (error) return error; ASSERT(ip != NULL); if (ip->i_itemp == NULL) xfs_inode_item_init(ip, mp); iip = ip->i_itemp; xfs_trans_add_item(tp, (xfs_log_item_t *)(iip)); /* initialize i_transp so we can find it incore */ ip->i_transp = tp; *ipp = ip; return 0; } void libxfs_trans_ijoin( xfs_trans_t *tp, xfs_inode_t *ip, uint lock_flags) { xfs_inode_log_item_t *iip; ASSERT(ip->i_transp == NULL); if (ip->i_itemp == NULL) xfs_inode_item_init(ip, ip->i_mount); iip = ip->i_itemp; ASSERT(iip->ili_flags == 0); ASSERT(iip->ili_inode != NULL); xfs_trans_add_item(tp, (xfs_log_item_t *)(iip)); ip->i_transp = tp; #ifdef XACT_DEBUG fprintf(stderr, "ijoin'd inode %llu, transaction %p\n", ip->i_ino, tp); #endif } void libxfs_trans_ijoin_ref( xfs_trans_t *tp, xfs_inode_t *ip, int lock_flags) { ASSERT(ip->i_transp == tp); ASSERT(ip->i_itemp != NULL); xfs_trans_ijoin(tp, ip, lock_flags); #ifdef XACT_DEBUG fprintf(stderr, "ijoin_ref'd inode %llu, transaction %p\n", ip->i_ino, tp); #endif } void libxfs_trans_inode_alloc_buf( xfs_trans_t *tp, xfs_buf_t *bp) { xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); } /* * This is called to mark the fields indicated in fieldmask as needing * to be logged when the transaction is committed. The inode must * already be associated with the given transaction. * * The values for fieldmask are defined in xfs_log_format.h. We always * log all of the core inode if any of it has changed, and we always log * all of the inline data/extents/b-tree root if any of them has changed. */ void xfs_trans_log_inode( xfs_trans_t *tp, xfs_inode_t *ip, uint flags) { ASSERT(ip->i_transp == tp); ASSERT(ip->i_itemp != NULL); #ifdef XACT_DEBUG fprintf(stderr, "dirtied inode %llu, transaction %p\n", ip->i_ino, tp); #endif tp->t_flags |= XFS_TRANS_DIRTY; ip->i_itemp->ili_item.li_desc->lid_flags |= XFS_LID_DIRTY; /* * Always OR in the bits from the ili_last_fields field. * This is to coordinate with the xfs_iflush() and xfs_iflush_done() * routines in the eventual clearing of the ilf_fields bits. * See the big comment in xfs_iflush() for an explanation of * this coordination mechanism. */ flags |= ip->i_itemp->ili_last_fields; ip->i_itemp->ili_fields |= flags; } /* * This is called to mark bytes first through last inclusive of the given * buffer as needing to be logged when the transaction is committed. * The buffer must already be associated with the given transaction. * * First and last are numbers relative to the beginning of this buffer, * so the first byte in the buffer is numbered 0 regardless of the * value of b_blkno. */ void libxfs_trans_log_buf( xfs_trans_t *tp, xfs_buf_t *bp, uint first, uint last) { xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp))); #ifdef XACT_DEBUG fprintf(stderr, "dirtied buffer %p, transaction %p\n", bp, tp); #endif bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); tp->t_flags |= XFS_TRANS_DIRTY; bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; xfs_buf_item_log(bip, first, last); } void libxfs_trans_brelse( xfs_trans_t *tp, xfs_buf_t *bp) { xfs_buf_log_item_t *bip; #ifdef XACT_DEBUG fprintf(stderr, "released buffer %p, transaction %p\n", bp, tp); #endif if (tp == NULL) { ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); libxfs_putbuf(bp); return; } ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(bip->bli_item.li_type == XFS_LI_BUF); if (bip->bli_recur > 0) { bip->bli_recur--; return; } /* If dirty/stale, can't release till transaction committed */ if (bip->bli_flags & XFS_BLI_STALE) return; if (bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY) return; xfs_trans_del_item(&bip->bli_item); if (bip->bli_flags & XFS_BLI_HOLD) bip->bli_flags &= ~XFS_BLI_HOLD; XFS_BUF_SET_FSPRIVATE2(bp, NULL); libxfs_putbuf(bp); } void libxfs_trans_binval( xfs_trans_t *tp, xfs_buf_t *bp) { xfs_buf_log_item_t *bip; #ifdef XACT_DEBUG fprintf(stderr, "binval'd buffer %p, transaction %p\n", bp, tp); #endif ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); if (bip->bli_flags & XFS_BLI_STALE) return; XFS_BUF_UNDELAYWRITE(bp); xfs_buf_stale(bp); bip->bli_flags |= XFS_BLI_STALE; bip->bli_flags &= ~XFS_BLI_DIRTY; bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; bip->bli_format.blf_flags |= XFS_BLF_CANCEL; bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; tp->t_flags |= XFS_TRANS_DIRTY; } void libxfs_trans_bjoin( xfs_trans_t *tp, xfs_buf_t *bp) { xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); #ifdef XACT_DEBUG fprintf(stderr, "bjoin'd buffer %p, transaction %p\n", bp, tp); #endif xfs_buf_item_init(bp, tp->t_mountp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); xfs_trans_add_item(tp, (xfs_log_item_t *)bip); XFS_BUF_SET_FSPRIVATE2(bp, tp); } void libxfs_trans_bhold( xfs_trans_t *tp, xfs_buf_t *bp) { xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); #ifdef XACT_DEBUG fprintf(stderr, "bhold'd buffer %p, transaction %p\n", bp, tp); #endif bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); bip->bli_flags |= XFS_BLI_HOLD; } xfs_buf_t * libxfs_trans_get_buf_map( xfs_trans_t *tp, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, uint f) { xfs_buf_t *bp; xfs_buf_log_item_t *bip; if (tp == NULL) return libxfs_getbuf_map(btp, map, nmaps, 0); bp = xfs_trans_buf_item_match(tp, btp, map, nmaps); if (bp != NULL) { ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(bip != NULL); bip->bli_recur++; return bp; } bp = libxfs_getbuf_map(btp, map, nmaps, 0); if (bp == NULL) return NULL; #ifdef XACT_DEBUG fprintf(stderr, "trans_get_buf buffer %p, transaction %p\n", bp, tp); #endif xfs_buf_item_init(bp, tp->t_mountp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); bip->bli_recur = 0; xfs_trans_add_item(tp, (xfs_log_item_t *)bip); /* initialize b_fsprivate2 so we can find it incore */ XFS_BUF_SET_FSPRIVATE2(bp, tp); return bp; } xfs_buf_t * libxfs_trans_getsb( xfs_trans_t *tp, xfs_mount_t *mp, int flags) { xfs_buf_t *bp; xfs_buf_log_item_t *bip; int len = XFS_FSS_TO_BB(mp, 1); DEFINE_SINGLE_BUF_MAP(map, XFS_SB_DADDR, len); if (tp == NULL) return libxfs_getsb(mp, flags); bp = xfs_trans_buf_item_match(tp, mp->m_dev, &map, 1); if (bp != NULL) { ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(bip != NULL); bip->bli_recur++; return bp; } bp = libxfs_getsb(mp, flags); #ifdef XACT_DEBUG fprintf(stderr, "trans_get_sb buffer %p, transaction %p\n", bp, tp); #endif xfs_buf_item_init(bp, mp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); bip->bli_recur = 0; xfs_trans_add_item(tp, (xfs_log_item_t *)bip); /* initialize b_fsprivate2 so we can find it incore */ XFS_BUF_SET_FSPRIVATE2(bp, tp); return bp; } int libxfs_trans_read_buf_map( xfs_mount_t *mp, xfs_trans_t *tp, struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, uint flags, xfs_buf_t **bpp, const struct xfs_buf_ops *ops) { xfs_buf_t *bp; xfs_buf_log_item_t *bip; int error; *bpp = NULL; if (tp == NULL) { bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops); if (!bp) { return (flags & XBF_TRYLOCK) ? -EAGAIN : -ENOMEM; } if (bp->b_error) goto out_relse; goto done; } bp = xfs_trans_buf_item_match(tp, btp, map, nmaps); if (bp != NULL) { ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); bip->bli_recur++; goto done; } bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops); if (!bp) { return (flags & XBF_TRYLOCK) ? -EAGAIN : -ENOMEM; } if (bp->b_error) goto out_relse; #ifdef XACT_DEBUG fprintf(stderr, "trans_read_buf buffer %p, transaction %p\n", bp, tp); #endif xfs_buf_item_init(bp, tp->t_mountp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); bip->bli_recur = 0; xfs_trans_add_item(tp, (xfs_log_item_t *)bip); /* initialise b_fsprivate2 so we can find it incore */ XFS_BUF_SET_FSPRIVATE2(bp, tp); done: *bpp = bp; return 0; out_relse: error = bp->b_error; xfs_buf_relse(bp); return error; } /* * Record the indicated change to the given field for application * to the file system's superblock when the transaction commits. * For now, just store the change in the transaction structure. * Mark the transaction structure to indicate that the superblock * needs to be updated before committing. * * Originally derived from xfs_trans_mod_sb(). */ void libxfs_trans_mod_sb( xfs_trans_t *tp, uint field, long delta) { switch (field) { case XFS_TRANS_SB_RES_FDBLOCKS: return; case XFS_TRANS_SB_FDBLOCKS: tp->t_fdblocks_delta += delta; break; case XFS_TRANS_SB_ICOUNT: ASSERT(delta > 0); tp->t_icount_delta += delta; break; case XFS_TRANS_SB_IFREE: tp->t_ifree_delta += delta; break; case XFS_TRANS_SB_FREXTENTS: tp->t_frextents_delta += delta; break; default: ASSERT(0); return; } tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY); } /* * Transaction commital code follows (i.e. write to disk in libxfs) */ static void inode_item_done( xfs_inode_log_item_t *iip) { xfs_dinode_t *dip; xfs_inode_t *ip; xfs_mount_t *mp; xfs_buf_t *bp; int error; ip = iip->ili_inode; mp = iip->ili_item.li_mountp; ASSERT(ip != NULL); if (!(iip->ili_fields & XFS_ILOG_ALL)) { ip->i_transp = NULL; /* disassociate from transaction */ iip->ili_flags = 0; /* reset all flags */ return; } /* * Get the buffer containing the on-disk inode. */ error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, 0, 0); if (error) { fprintf(stderr, _("%s: warning - imap_to_bp failed (%d)\n"), progname, error); return; } XFS_BUF_SET_FSPRIVATE(bp, iip); error = libxfs_iflush_int(ip, bp); if (error) { fprintf(stderr, _("%s: warning - iflush_int failed (%d)\n"), progname, error); return; } ip->i_transp = NULL; /* disassociate from transaction */ XFS_BUF_SET_FSPRIVATE(bp, NULL); /* remove log item */ XFS_BUF_SET_FSPRIVATE2(bp, NULL); /* remove xact ptr */ libxfs_writebuf(bp, 0); #ifdef XACT_DEBUG fprintf(stderr, "flushing dirty inode %llu, buffer %p\n", ip->i_ino, bp); #endif } static void buf_item_done( xfs_buf_log_item_t *bip) { xfs_buf_t *bp; int hold; extern kmem_zone_t *xfs_buf_item_zone; bp = bip->bli_buf; ASSERT(bp != NULL); XFS_BUF_SET_FSPRIVATE(bp, NULL); /* remove log item */ XFS_BUF_SET_FSPRIVATE2(bp, NULL); /* remove xact ptr */ hold = (bip->bli_flags & XFS_BLI_HOLD); if (bip->bli_flags & XFS_BLI_DIRTY) { #ifdef XACT_DEBUG fprintf(stderr, "flushing/staling buffer %p (hold=%d)\n", bp, hold); #endif libxfs_writebuf_int(bp, 0); } if (hold) bip->bli_flags &= ~XFS_BLI_HOLD; else libxfs_putbuf(bp); /* release the buf item */ kmem_zone_free(xfs_buf_item_zone, bip); } static void trans_committed( xfs_trans_t *tp) { struct xfs_log_item_desc *lidp, *next; list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) { struct xfs_log_item *lip = lidp->lid_item; xfs_trans_del_item(lip); if (lip->li_type == XFS_LI_BUF) buf_item_done((xfs_buf_log_item_t *)lip); else if (lip->li_type == XFS_LI_INODE) inode_item_done((xfs_inode_log_item_t *)lip); else { fprintf(stderr, _("%s: unrecognised log item type\n"), progname); ASSERT(0); } } } static void buf_item_unlock( xfs_buf_log_item_t *bip) { xfs_buf_t *bp = bip->bli_buf; uint hold; /* Clear the buffer's association with this transaction. */ XFS_BUF_SET_FSPRIVATE2(bip->bli_buf, NULL); hold = bip->bli_flags & XFS_BLI_HOLD; bip->bli_flags &= ~XFS_BLI_HOLD; if (!hold) libxfs_putbuf(bp); } static void inode_item_unlock( xfs_inode_log_item_t *iip) { xfs_inode_t *ip = iip->ili_inode; /* Clear the transaction pointer in the inode. */ ip->i_transp = NULL; iip->ili_flags = 0; } /* * Unlock all of the items of a transaction and free all the descriptors * of that transaction. */ static void xfs_trans_free_items( struct xfs_trans *tp) { struct xfs_log_item_desc *lidp, *next; list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) { struct xfs_log_item *lip = lidp->lid_item; xfs_trans_del_item(lip); if (lip->li_type == XFS_LI_BUF) buf_item_unlock((xfs_buf_log_item_t *)lip); else if (lip->li_type == XFS_LI_INODE) inode_item_unlock((xfs_inode_log_item_t *)lip); else { fprintf(stderr, _("%s: unrecognised log item type\n"), progname); ASSERT(0); } } } /* * Commit the changes represented by this transaction */ int libxfs_trans_commit( xfs_trans_t *tp) { xfs_sb_t *sbp; if (tp == NULL) return 0; if (!(tp->t_flags & XFS_TRANS_DIRTY)) { #ifdef XACT_DEBUG fprintf(stderr, "committed clean transaction %p\n", tp); #endif xfs_trans_free_items(tp); free(tp); tp = NULL; return 0; } if (tp->t_flags & XFS_TRANS_SB_DIRTY) { sbp = &(tp->t_mountp->m_sb); if (tp->t_icount_delta) sbp->sb_icount += tp->t_icount_delta; if (tp->t_ifree_delta) sbp->sb_ifree += tp->t_ifree_delta; if (tp->t_fdblocks_delta) sbp->sb_fdblocks += tp->t_fdblocks_delta; if (tp->t_frextents_delta) sbp->sb_frextents += tp->t_frextents_delta; xfs_log_sb(tp); } #ifdef XACT_DEBUG fprintf(stderr, "committing dirty transaction %p\n", tp); #endif trans_committed(tp); /* That's it for the transaction structure. Free it. */ free(tp); tp = NULL; return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/util.c0000644000000000000000000004740513063067171015114 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "libxfs_io.h" #include "init.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_bmap_btree.h" #include "xfs_trans_space.h" #include "xfs_ialloc.h" #include "xfs_alloc.h" #include "xfs_bit.h" /* * Calculate the worst case log unit reservation for a given superblock * configuration. Copied and munged from the kernel code, and assumes a * worse case header usage (maximum log buffer sizes) */ int xfs_log_calc_unit_res( struct xfs_mount *mp, int unit_bytes) { int iclog_space; int iclog_header_size; int iclog_size; uint num_headers; if (xfs_sb_version_haslogv2(&mp->m_sb)) { iclog_size = XLOG_MAX_RECORD_BSIZE; iclog_header_size = BBTOB(iclog_size / XLOG_HEADER_CYCLE_SIZE); } else { iclog_size = XLOG_BIG_RECORD_BSIZE; iclog_header_size = BBSIZE; } /* * Permanent reservations have up to 'cnt'-1 active log operations * in the log. A unit in this case is the amount of space for one * of these log operations. Normal reservations have a cnt of 1 * and their unit amount is the total amount of space required. * * The following lines of code account for non-transaction data * which occupy space in the on-disk log. * * Normal form of a transaction is: * ... * and then there are LR hdrs, split-recs and roundoff at end of syncs. * * We need to account for all the leadup data and trailer data * around the transaction data. * And then we need to account for the worst case in terms of using * more space. * The worst case will happen if: * - the placement of the transaction happens to be such that the * roundoff is at its maximum * - the transaction data is synced before the commit record is synced * i.e. | * Therefore the commit record is in its own Log Record. * This can happen as the commit record is called with its * own region to xlog_write(). * This then means that in the worst case, roundoff can happen for * the commit-rec as well. * The commit-rec is smaller than padding in this scenario and so it is * not added separately. */ /* for trans header */ unit_bytes += sizeof(xlog_op_header_t); unit_bytes += sizeof(xfs_trans_header_t); /* for start-rec */ unit_bytes += sizeof(xlog_op_header_t); /* * for LR headers - the space for data in an iclog is the size minus * the space used for the headers. If we use the iclog size, then we * undercalculate the number of headers required. * * Furthermore - the addition of op headers for split-recs might * increase the space required enough to require more log and op * headers, so take that into account too. * * IMPORTANT: This reservation makes the assumption that if this * transaction is the first in an iclog and hence has the LR headers * accounted to it, then the remaining space in the iclog is * exclusively for this transaction. i.e. if the transaction is larger * than the iclog, it will be the only thing in that iclog. * Fundamentally, this means we must pass the entire log vector to * xlog_write to guarantee this. */ iclog_space = iclog_size - iclog_header_size; num_headers = howmany(unit_bytes, iclog_space); /* for split-recs - ophdrs added when data split over LRs */ unit_bytes += sizeof(xlog_op_header_t) * num_headers; /* add extra header reservations if we overrun */ while (!num_headers || howmany(unit_bytes, iclog_space) > num_headers) { unit_bytes += sizeof(xlog_op_header_t); num_headers++; } unit_bytes += iclog_header_size * num_headers; /* for commit-rec LR header - note: padding will subsume the ophdr */ unit_bytes += iclog_header_size; /* for roundoff padding for transaction data and one for commit record */ if (xfs_sb_version_haslogv2(&mp->m_sb) && mp->m_sb.sb_logsunit > 1) { /* log su roundoff */ unit_bytes += 2 * mp->m_sb.sb_logsunit; } else { /* BB roundoff */ unit_bytes += 2 * BBSIZE; } return unit_bytes; } /* * Change the requested timestamp in the given inode. * * This was once shared with the kernel, but has diverged to the point * where it's no longer worth the hassle of maintaining common code. */ void libxfs_trans_ichgtime( struct xfs_trans *tp, struct xfs_inode *ip, int flags) { struct timespec tv; struct timeval stv; gettimeofday(&stv, (struct timezone *)0); tv.tv_sec = stv.tv_sec; tv.tv_nsec = stv.tv_usec * 1000; if (flags & XFS_ICHGTIME_MOD) VFS_I(ip)->i_mtime = tv; if (flags & XFS_ICHGTIME_CHG) VFS_I(ip)->i_ctime = tv; if (flags & XFS_ICHGTIME_CREATE) { ip->i_d.di_crtime.t_sec = (__int32_t)tv.tv_sec; ip->i_d.di_crtime.t_nsec = (__int32_t)tv.tv_nsec; } } /* * Allocate an inode on disk and return a copy of its in-core version. * Set mode, nlink, and rdev appropriately within the inode. * The uid and gid for the inode are set according to the contents of * the given cred structure. * * This was once shared with the kernel, but has diverged to the point * where it's no longer worth the hassle of maintaining common code. */ int libxfs_ialloc( xfs_trans_t *tp, xfs_inode_t *pip, mode_t mode, nlink_t nlink, xfs_dev_t rdev, struct cred *cr, struct fsxattr *fsx, int okalloc, xfs_buf_t **ialloc_context, xfs_inode_t **ipp) { xfs_ino_t ino; xfs_inode_t *ip; uint flags; int error; /* * Call the space management code to pick * the on-disk inode to be allocated. */ error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, ialloc_context, &ino); if (error != 0) return error; if (*ialloc_context || ino == NULLFSINO) { *ipp = NULL; return 0; } ASSERT(*ialloc_context == NULL); error = xfs_trans_iget(tp->t_mountp, tp, ino, 0, 0, &ip); if (error != 0) return error; ASSERT(ip != NULL); VFS_I(ip)->i_mode = mode; set_nlink(VFS_I(ip), nlink); ip->i_d.di_uid = cr->cr_uid; ip->i_d.di_gid = cr->cr_gid; xfs_set_projid(&ip->i_d, pip ? 0 : fsx->fsx_projid); xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD); /* * We only support filesystems that understand v2 format inodes. So if * this is currently an old format inode, then change the inode version * number now. This way we only do the conversion here rather than here * and in the flush/logging code. */ if (ip->i_d.di_version == 1) { ip->i_d.di_version = 2; /* * old link count, projid_lo/hi field, pad field * already zeroed */ } if (pip && (VFS_I(pip)->i_mode & S_ISGID)) { ip->i_d.di_gid = pip->i_d.di_gid; if ((VFS_I(pip)->i_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) VFS_I(ip)->i_mode |= S_ISGID; } ip->i_d.di_size = 0; ip->i_d.di_nextents = 0; ASSERT(ip->i_d.di_nblocks == 0); ip->i_d.di_extsize = pip ? 0 : fsx->fsx_extsize; ip->i_d.di_dmevmask = 0; ip->i_d.di_dmstate = 0; ip->i_d.di_flags = pip ? 0 : fsx->fsx_xflags; if (ip->i_d.di_version == 3) { ASSERT(ip->i_d.di_ino == ino); ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid)); VFS_I(ip)->i_version = 1; ip->i_d.di_flags2 = 0; ip->i_d.di_crtime.t_sec = (__int32_t)VFS_I(ip)->i_mtime.tv_sec; ip->i_d.di_crtime.t_nsec = (__int32_t)VFS_I(ip)->i_mtime.tv_nsec; } flags = XFS_ILOG_CORE; switch (mode & S_IFMT) { case S_IFIFO: case S_IFSOCK: /* doesn't make sense to set an rdev for these */ rdev = 0; /* FALLTHROUGH */ case S_IFCHR: case S_IFBLK: ip->i_d.di_format = XFS_DINODE_FMT_DEV; ip->i_df.if_u2.if_rdev = rdev; flags |= XFS_ILOG_DEV; break; case S_IFREG: case S_IFDIR: if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { uint di_flags = 0; if ((mode & S_IFMT) == S_IFDIR) { if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) di_flags |= XFS_DIFLAG_RTINHERIT; if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { di_flags |= XFS_DIFLAG_EXTSZINHERIT; ip->i_d.di_extsize = pip->i_d.di_extsize; } } else { if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) { di_flags |= XFS_DIFLAG_REALTIME; } if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { di_flags |= XFS_DIFLAG_EXTSIZE; ip->i_d.di_extsize = pip->i_d.di_extsize; } } if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) di_flags |= XFS_DIFLAG_PROJINHERIT; ip->i_d.di_flags |= di_flags; } /* FALLTHROUGH */ case S_IFLNK: ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; ip->i_df.if_flags = XFS_IFEXTENTS; ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0; ip->i_df.if_u1.if_extents = NULL; break; default: ASSERT(0); } /* Attribute fork settings for new inode. */ ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; ip->i_d.di_anextents = 0; /* * set up the inode ops structure that the libxfs code relies on */ if (XFS_ISDIR(ip)) ip->d_ops = ip->i_mount->m_dir_inode_ops; else ip->d_ops = ip->i_mount->m_nondir_inode_ops; /* * Log the new values stuffed into the inode. */ xfs_trans_log_inode(tp, ip, flags); *ipp = ip; return 0; } void libxfs_iprint( xfs_inode_t *ip) { struct xfs_icdinode *dip; xfs_bmbt_rec_host_t *ep; xfs_extnum_t i; xfs_extnum_t nextents; printf("Inode %lx\n", (unsigned long)ip); printf(" i_ino %llx\n", (unsigned long long)ip->i_ino); if (ip->i_df.if_flags & XFS_IFEXTENTS) printf("EXTENTS "); printf("\n"); printf(" i_df.if_bytes %d\n", ip->i_df.if_bytes); printf(" i_df.if_u1.if_extents/if_data %lx\n", (unsigned long)ip->i_df.if_u1.if_extents); if (ip->i_df.if_flags & XFS_IFEXTENTS) { nextents = ip->i_df.if_bytes / (uint)sizeof(*ep); for (ep = ip->i_df.if_u1.if_extents, i = 0; i < nextents; i++, ep++) { xfs_bmbt_irec_t rec; xfs_bmbt_get_all(ep, &rec); printf("\t%d: startoff %llu, startblock 0x%llx," " blockcount %llu, state %d\n", i, (unsigned long long)rec.br_startoff, (unsigned long long)rec.br_startblock, (unsigned long long)rec.br_blockcount, (int)rec.br_state); } } printf(" i_df.if_broot %lx\n", (unsigned long)ip->i_df.if_broot); printf(" i_df.if_broot_bytes %x\n", ip->i_df.if_broot_bytes); dip = &ip->i_d; printf("\nOn disk portion\n"); printf(" di_mode %o\n", VFS_I(ip)->i_mode); printf(" di_version %x\n", (uint)dip->di_version); switch (ip->i_d.di_format) { case XFS_DINODE_FMT_LOCAL: printf(" Inline inode\n"); break; case XFS_DINODE_FMT_EXTENTS: printf(" Extents inode\n"); break; case XFS_DINODE_FMT_BTREE: printf(" B-tree inode\n"); break; default: printf(" Other inode\n"); break; } printf(" di_nlink %x\n", VFS_I(ip)->i_nlink); printf(" di_uid %d\n", dip->di_uid); printf(" di_gid %d\n", dip->di_gid); printf(" di_nextents %d\n", dip->di_nextents); printf(" di_size %llu\n", (unsigned long long)dip->di_size); printf(" di_gen %x\n", VFS_I(ip)->i_generation); printf(" di_extsize %d\n", dip->di_extsize); printf(" di_flags %x\n", dip->di_flags); printf(" di_nblocks %llu\n", (unsigned long long)dip->di_nblocks); } /* * Writes a modified inode's changes out to the inode's on disk home. * Originally based on xfs_iflush_int() from xfs_inode.c in the kernel. */ int libxfs_iflush_int(xfs_inode_t *ip, xfs_buf_t *bp) { xfs_inode_log_item_t *iip; xfs_dinode_t *dip; xfs_mount_t *mp; ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents > ip->i_df.if_ext_max); ASSERT(ip->i_d.di_version > 1); iip = ip->i_itemp; mp = ip->i_mount; /* set *dip = inode's place in the buffer */ dip = xfs_buf_offset(bp, ip->i_imap.im_boffset); ASSERT(ip->i_d.di_magic == XFS_DINODE_MAGIC); if (XFS_ISREG(ip)) { ASSERT( (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS) || (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) ); } else if (XFS_ISDIR(ip)) { ASSERT( (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS) || (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) || (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) ); } ASSERT(ip->i_d.di_nextents+ip->i_d.di_anextents <= ip->i_d.di_nblocks); ASSERT(ip->i_d.di_forkoff <= mp->m_sb.sb_inodesize); /* bump the change count on v3 inodes */ if (ip->i_d.di_version == 3) VFS_I(ip)->i_version++; /* * Copy the dirty parts of the inode into the on-disk * inode. We always copy out the core of the inode, * because if the inode is dirty at all the core must * be. */ xfs_inode_to_disk(ip, dip, iip->ili_item.li_lsn); xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK); if (XFS_IFORK_Q(ip)) xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK); /* generate the checksum. */ xfs_dinode_calc_crc(mp, dip); return 0; } int libxfs_mod_incore_sb( struct xfs_mount *mp, int field, int64_t delta, int rsvd) { long long lcounter; /* long counter for 64 bit fields */ switch (field) { case XFS_TRANS_SB_FDBLOCKS: lcounter = (long long)mp->m_sb.sb_fdblocks; lcounter += delta; if (lcounter < 0) return -ENOSPC; mp->m_sb.sb_fdblocks = lcounter; return 0; default: ASSERT(0); return -EINVAL; } } /* * This routine allocates disk space for the given file. * Originally derived from xfs_alloc_file_space(). */ int libxfs_alloc_file_space( xfs_inode_t *ip, xfs_off_t offset, xfs_off_t len, int alloc_type, int attr_flags) { xfs_mount_t *mp; xfs_off_t count; xfs_filblks_t datablocks; xfs_filblks_t allocated_fsb; xfs_filblks_t allocatesize_fsb; xfs_fsblock_t firstfsb; struct xfs_defer_ops free_list; xfs_bmbt_irec_t *imapp; xfs_bmbt_irec_t imaps[1]; int reccount; uint resblks; xfs_fileoff_t startoffset_fsb; xfs_trans_t *tp; int xfs_bmapi_flags; int error; if (len <= 0) return -EINVAL; count = len; error = 0; imapp = &imaps[0]; reccount = 1; xfs_bmapi_flags = alloc_type ? XFS_BMAPI_PREALLOC : 0; mp = ip->i_mount; startoffset_fsb = XFS_B_TO_FSBT(mp, offset); allocatesize_fsb = XFS_B_TO_FSB(mp, count); /* allocate file space until done or until there is an error */ while (allocatesize_fsb && !error) { datablocks = allocatesize_fsb; resblks = (uint)XFS_DIOSTRAT_SPACE_RES(mp, datablocks); error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); /* * Check for running out of space */ if (error) { ASSERT(error == -ENOSPC); break; } xfs_trans_ijoin(tp, ip, 0); xfs_defer_init(&free_list, &firstfsb); error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb, xfs_bmapi_flags, &firstfsb, 0, imapp, &reccount, &free_list); if (error) goto error0; /* complete the transaction */ error = xfs_defer_finish(&tp, &free_list, ip); if (error) goto error0; error = xfs_trans_commit(tp); if (error) break; allocated_fsb = imapp->br_blockcount; if (reccount == 0) return -ENOSPC; startoffset_fsb += allocated_fsb; allocatesize_fsb -= allocated_fsb; } return error; error0: /* Cancel bmap, cancel trans */ xfs_defer_cancel(&free_list); xfs_trans_cancel(tp); return error; } unsigned int libxfs_log2_roundup(unsigned int i) { unsigned int rval; for (rval = 0; rval < NBBY * sizeof(i); rval++) { if ((1 << rval) >= i) break; } return rval; } /* * Wrapper around call to libxfs_ialloc. Takes care of committing and * allocating a new transaction as needed. * * Originally there were two copies of this code - one in mkfs, the * other in repair - now there is just the one. */ int libxfs_inode_alloc( xfs_trans_t **tp, xfs_inode_t *pip, mode_t mode, nlink_t nlink, xfs_dev_t rdev, struct cred *cr, struct fsxattr *fsx, xfs_inode_t **ipp) { xfs_buf_t *ialloc_context; xfs_inode_t *ip; int error; ialloc_context = (xfs_buf_t *)0; error = libxfs_ialloc(*tp, pip, mode, nlink, rdev, cr, fsx, 1, &ialloc_context, &ip); if (error) { *ipp = NULL; return error; } if (!ialloc_context && !ip) { *ipp = NULL; return -ENOSPC; } if (ialloc_context) { xfs_trans_bhold(*tp, ialloc_context); error = xfs_trans_roll(tp, NULL); if (error) { fprintf(stderr, _("%s: cannot duplicate transaction: %s\n"), progname, strerror(error)); exit(1); } xfs_trans_bjoin(*tp, ialloc_context); error = libxfs_ialloc(*tp, pip, mode, nlink, rdev, cr, fsx, 1, &ialloc_context, &ip); if (!ip) error = -ENOSPC; if (error) return error; } *ipp = ip; return error; } /* * Userspace versions of common diagnostic routines (varargs fun). */ void libxfs_fs_repair_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fprintf(stderr, " This is a bug.\n"); fprintf(stderr, "%s version %s\n", progname, VERSION); fprintf(stderr, "Please capture the filesystem metadata with xfs_metadump and\n" "report it to linux-xfs@vger.kernel.org\n"); va_end(ap); } void libxfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fputs("\n", stderr); va_end(ap); } void cmn_err(int level, char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fputs("\n", stderr); va_end(ap); } /* * Warnings specifically for verifier errors. Differentiate CRC vs. invalid * values, and omit the stack trace unless the error level is tuned high. */ void xfs_verifier_error( struct xfs_buf *bp) { xfs_alert(NULL, "Metadata %s detected at %s block 0x%llx/0x%x", bp->b_error == -EFSBADCRC ? "CRC error" : "corruption", bp->b_ops->name, bp->b_bn, BBTOB(bp->b_length)); } /* * This is called from I/O verifiers on v5 superblock filesystems. In the * kernel, it validates the metadata LSN parameter against the current LSN of * the active log. We don't have an active log in userspace so this kind of * validation is not required. Therefore, this function always returns true in * userspace. * * xfs_repair piggybacks off this mechanism to help track the largest metadata * LSN in use on a filesystem. Keep a record of the largest LSN seen such that * repair can validate it against the state of the log. */ xfs_lsn_t libxfs_max_lsn = 0; pthread_mutex_t libxfs_max_lsn_lock = PTHREAD_MUTEX_INITIALIZER; bool xfs_log_check_lsn( struct xfs_mount *mp, xfs_lsn_t lsn) { int cycle = CYCLE_LSN(lsn); int block = BLOCK_LSN(lsn); int max_cycle; int max_block; if (lsn == NULLCOMMITLSN) return true; pthread_mutex_lock(&libxfs_max_lsn_lock); max_cycle = CYCLE_LSN(libxfs_max_lsn); max_block = BLOCK_LSN(libxfs_max_lsn); if ((cycle > max_cycle) || (cycle == max_cycle && block > max_block)) libxfs_max_lsn = lsn; pthread_mutex_unlock(&libxfs_max_lsn_lock); return true; } static struct xfs_buftarg * xfs_find_bdev_for_inode( struct xfs_inode *ip) { struct xfs_mount *mp = ip->i_mount; if (XFS_IS_REALTIME_INODE(ip)) return mp->m_rtdev_targp; return mp->m_ddev_targp; } static xfs_daddr_t xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb) { if (XFS_IS_REALTIME_INODE(ip)) return XFS_FSB_TO_BB(ip->i_mount, fsb); return XFS_FSB_TO_DADDR(ip->i_mount, (fsb)); } int libxfs_zero_extent( struct xfs_inode *ip, xfs_fsblock_t start_fsb, xfs_off_t count_fsb) { xfs_daddr_t sector = xfs_fsb_to_db(ip, start_fsb); ssize_t size = XFS_FSB_TO_BB(ip->i_mount, count_fsb); return libxfs_device_zero(xfs_find_bdev_for_inode(ip), sector, size); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_ag_resv.c0000644000000000000000000002270213033541503016427 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_alloc.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_bit.h" #include "xfs_bmap.h" #include "xfs_bmap_btree.h" #include "xfs_ag_resv.h" #include "xfs_trans_space.h" #include "xfs_rmap_btree.h" #include "xfs_btree.h" #include "xfs_refcount_btree.h" /* * Per-AG Block Reservations * * For some kinds of allocation group metadata structures, it is advantageous * to reserve a small number of blocks in each AG so that future expansions of * that data structure do not encounter ENOSPC because errors during a btree * split cause the filesystem to go offline. * * Prior to the introduction of reflink, this wasn't an issue because the free * space btrees maintain a reserve of space (the AGFL) to handle any expansion * that may be necessary; and allocations of other metadata (inodes, BMBT, * dir/attr) aren't restricted to a single AG. However, with reflink it is * possible to allocate all the space in an AG, have subsequent reflink/CoW * activity expand the refcount btree, and discover that there's no space left * to handle that expansion. Since we can calculate the maximum size of the * refcount btree, we can reserve space for it and avoid ENOSPC. * * Handling per-AG reservations consists of three changes to the allocator's * behavior: First, because these reservations are always needed, we decrease * the ag_max_usable counter to reflect the size of the AG after the reserved * blocks are taken. Second, the reservations must be reflected in the * fdblocks count to maintain proper accounting. Third, each AG must maintain * its own reserved block counter so that we can calculate the amount of space * that must remain free to maintain the reservations. Fourth, the "remaining * reserved blocks" count must be used when calculating the length of the * longest free extent in an AG and to clamp maxlen in the per-AG allocation * functions. In other words, we maintain a virtual allocation via in-core * accounting tricks so that we don't have to clean up after a crash. :) * * Reserved blocks can be managed by passing one of the enum xfs_ag_resv_type * values via struct xfs_alloc_arg or directly to the xfs_free_extent * function. It might seem a little funny to maintain a reservoir of blocks * to feed another reservoir, but the AGFL only holds enough blocks to get * through the next transaction. The per-AG reservation is to ensure (we * hope) that each AG never runs out of blocks. Each data structure wanting * to use the reservation system should update ask/used in xfs_ag_resv_init. */ /* * Are we critically low on blocks? For now we'll define that as the number * of blocks we can get our hands on being less than 10% of what we reserved * or less than some arbitrary number (maximum btree height). */ bool xfs_ag_resv_critical( struct xfs_perag *pag, enum xfs_ag_resv_type type) { xfs_extlen_t avail; xfs_extlen_t orig; switch (type) { case XFS_AG_RESV_METADATA: avail = pag->pagf_freeblks - pag->pag_agfl_resv.ar_reserved; orig = pag->pag_meta_resv.ar_asked; break; case XFS_AG_RESV_AGFL: avail = pag->pagf_freeblks + pag->pagf_flcount - pag->pag_meta_resv.ar_reserved; orig = pag->pag_agfl_resv.ar_asked; break; default: ASSERT(0); return false; } trace_xfs_ag_resv_critical(pag, type, avail); /* Critically low if less than 10% or max btree height remains. */ return XFS_TEST_ERROR(avail < orig / 10 || avail < XFS_BTREE_MAXLEVELS, pag->pag_mount, XFS_ERRTAG_AG_RESV_CRITICAL, XFS_RANDOM_AG_RESV_CRITICAL); } /* * How many blocks are reserved but not used, and therefore must not be * allocated away? */ xfs_extlen_t xfs_ag_resv_needed( struct xfs_perag *pag, enum xfs_ag_resv_type type) { xfs_extlen_t len; len = pag->pag_meta_resv.ar_reserved + pag->pag_agfl_resv.ar_reserved; switch (type) { case XFS_AG_RESV_METADATA: case XFS_AG_RESV_AGFL: len -= xfs_perag_resv(pag, type)->ar_reserved; break; case XFS_AG_RESV_NONE: /* empty */ break; default: ASSERT(0); } trace_xfs_ag_resv_needed(pag, type, len); return len; } /* Clean out a reservation */ static int __xfs_ag_resv_free( struct xfs_perag *pag, enum xfs_ag_resv_type type) { struct xfs_ag_resv *resv; xfs_extlen_t oldresv; int error; trace_xfs_ag_resv_free(pag, type, 0); resv = xfs_perag_resv(pag, type); pag->pag_mount->m_ag_max_usable += resv->ar_asked; /* * AGFL blocks are always considered "free", so whatever * was reserved at mount time must be given back at umount. */ if (type == XFS_AG_RESV_AGFL) oldresv = resv->ar_orig_reserved; else oldresv = resv->ar_reserved; error = xfs_mod_fdblocks(pag->pag_mount, oldresv, true); resv->ar_reserved = 0; resv->ar_asked = 0; if (error) trace_xfs_ag_resv_free_error(pag->pag_mount, pag->pag_agno, error, _RET_IP_); return error; } /* Free a per-AG reservation. */ int xfs_ag_resv_free( struct xfs_perag *pag) { int error; int err2; error = __xfs_ag_resv_free(pag, XFS_AG_RESV_AGFL); err2 = __xfs_ag_resv_free(pag, XFS_AG_RESV_METADATA); if (err2 && !error) error = err2; return error; } static int __xfs_ag_resv_init( struct xfs_perag *pag, enum xfs_ag_resv_type type, xfs_extlen_t ask, xfs_extlen_t used) { struct xfs_mount *mp = pag->pag_mount; struct xfs_ag_resv *resv; int error; resv = xfs_perag_resv(pag, type); if (used > ask) ask = used; resv->ar_asked = ask; resv->ar_reserved = resv->ar_orig_reserved = ask - used; mp->m_ag_max_usable -= ask; trace_xfs_ag_resv_init(pag, type, ask); error = xfs_mod_fdblocks(mp, -(int64_t)resv->ar_reserved, true); if (error) trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno, error, _RET_IP_); return error; } /* Create a per-AG block reservation. */ int xfs_ag_resv_init( struct xfs_perag *pag) { xfs_extlen_t ask; xfs_extlen_t used; int error = 0; /* Create the metadata reservation. */ if (pag->pag_meta_resv.ar_asked == 0) { ask = used = 0; error = xfs_refcountbt_calc_reserves(pag->pag_mount, pag->pag_agno, &ask, &used); if (error) goto out; error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, ask, used); if (error) goto out; } /* Create the AGFL metadata reservation */ if (pag->pag_agfl_resv.ar_asked == 0) { ask = used = 0; error = xfs_rmapbt_calc_reserves(pag->pag_mount, pag->pag_agno, &ask, &used); if (error) goto out; error = __xfs_ag_resv_init(pag, XFS_AG_RESV_AGFL, ask, used); if (error) goto out; } out: return error; } /* Allocate a block from the reservation. */ void xfs_ag_resv_alloc_extent( struct xfs_perag *pag, enum xfs_ag_resv_type type, struct xfs_alloc_arg *args) { struct xfs_ag_resv *resv; xfs_extlen_t len; uint field; trace_xfs_ag_resv_alloc_extent(pag, type, args->len); switch (type) { case XFS_AG_RESV_METADATA: case XFS_AG_RESV_AGFL: resv = xfs_perag_resv(pag, type); break; default: ASSERT(0); /* fall through */ case XFS_AG_RESV_NONE: field = args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : XFS_TRANS_SB_FDBLOCKS; xfs_trans_mod_sb(args->tp, field, -(int64_t)args->len); return; } len = min_t(xfs_extlen_t, args->len, resv->ar_reserved); resv->ar_reserved -= len; if (type == XFS_AG_RESV_AGFL) return; /* Allocations of reserved blocks only need on-disk sb updates... */ xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_RES_FDBLOCKS, -(int64_t)len); /* ...but non-reserved blocks need in-core and on-disk updates. */ if (args->len > len) xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_FDBLOCKS, -((int64_t)args->len - len)); } /* Free a block to the reservation. */ void xfs_ag_resv_free_extent( struct xfs_perag *pag, enum xfs_ag_resv_type type, struct xfs_trans *tp, xfs_extlen_t len) { xfs_extlen_t leftover; struct xfs_ag_resv *resv; trace_xfs_ag_resv_free_extent(pag, type, len); switch (type) { case XFS_AG_RESV_METADATA: case XFS_AG_RESV_AGFL: resv = xfs_perag_resv(pag, type); break; default: ASSERT(0); /* fall through */ case XFS_AG_RESV_NONE: xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (int64_t)len); return; } leftover = min_t(xfs_extlen_t, len, resv->ar_asked - resv->ar_reserved); resv->ar_reserved += leftover; if (type == XFS_AG_RESV_AGFL) return; /* Freeing into the reserved pool only requires on-disk update... */ xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FDBLOCKS, len); /* ...but freeing beyond that requires in-core and on-disk update. */ if (len > leftover) xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, len - leftover); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_ag_resv.h0000644000000000000000000000260013033541503016427 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __XFS_AG_RESV_H__ #define __XFS_AG_RESV_H__ int xfs_ag_resv_free(struct xfs_perag *pag); int xfs_ag_resv_init(struct xfs_perag *pag); bool xfs_ag_resv_critical(struct xfs_perag *pag, enum xfs_ag_resv_type type); xfs_extlen_t xfs_ag_resv_needed(struct xfs_perag *pag, enum xfs_ag_resv_type type); void xfs_ag_resv_alloc_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, struct xfs_alloc_arg *args); void xfs_ag_resv_free_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, struct xfs_trans *tp, xfs_extlen_t len); #endif /* __XFS_AG_RESV_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_alloc.c0000644000000000000000000024257313063067171016114 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_shared.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_rmap.h" #include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_trans.h" #include "xfs_ag_resv.h" struct workqueue_struct *xfs_alloc_wq; #define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b))) #define XFSA_FIXUP_BNO_OK 1 #define XFSA_FIXUP_CNT_OK 2 STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); unsigned int xfs_refc_block( struct xfs_mount *mp) { if (xfs_sb_version_hasrmapbt(&mp->m_sb)) return XFS_RMAP_BLOCK(mp) + 1; if (xfs_sb_version_hasfinobt(&mp->m_sb)) return XFS_FIBT_BLOCK(mp) + 1; return XFS_IBT_BLOCK(mp) + 1; } xfs_extlen_t xfs_prealloc_blocks( struct xfs_mount *mp) { if (xfs_sb_version_hasreflink(&mp->m_sb)) return xfs_refc_block(mp) + 1; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) return XFS_RMAP_BLOCK(mp) + 1; if (xfs_sb_version_hasfinobt(&mp->m_sb)) return XFS_FIBT_BLOCK(mp) + 1; return XFS_IBT_BLOCK(mp) + 1; } /* * In order to avoid ENOSPC-related deadlock caused by out-of-order locking of * AGF buffer (PV 947395), we place constraints on the relationship among * actual allocations for data blocks, freelist blocks, and potential file data * bmap btree blocks. However, these restrictions may result in no actual space * allocated for a delayed extent, for example, a data block in a certain AG is * allocated but there is no additional block for the additional bmap btree * block due to a split of the bmap btree of the file. The result of this may * lead to an infinite loop when the file gets flushed to disk and all delayed * extents need to be actually allocated. To get around this, we explicitly set * aside a few blocks which will not be reserved in delayed allocation. * * We need to reserve 4 fsbs _per AG_ for the freelist and 4 more to handle a * potential split of the file's bmap btree. */ unsigned int xfs_alloc_set_aside( struct xfs_mount *mp) { unsigned int blocks; blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE); return blocks; } /* * When deciding how much space to allocate out of an AG, we limit the * allocation maximum size to the size the AG. However, we cannot use all the * blocks in the AG - some are permanently used by metadata. These * blocks are generally: * - the AG superblock, AGF, AGI and AGFL * - the AGF (bno and cnt) and AGI btree root blocks, and optionally * the AGI free inode and rmap btree root blocks. * - blocks on the AGFL according to xfs_alloc_set_aside() limits * - the rmapbt root block * * The AG headers are sector sized, so the amount of space they take up is * dependent on filesystem geometry. The others are all single blocks. */ unsigned int xfs_alloc_ag_max_usable( struct xfs_mount *mp) { unsigned int blocks; blocks = XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)); /* ag headers */ blocks += XFS_ALLOC_AGFL_RESERVE; blocks += 3; /* AGF, AGI btree root blocks */ if (xfs_sb_version_hasfinobt(&mp->m_sb)) blocks++; /* finobt root block */ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) blocks++; /* rmap root block */ if (xfs_sb_version_hasreflink(&mp->m_sb)) blocks++; /* refcount root block */ return mp->m_sb.sb_agblocks - blocks; } /* * Lookup the record equal to [bno, len] in the btree given by cur. */ STATIC int /* error */ xfs_alloc_lookup_eq( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); } /* * Lookup the first record greater than or equal to [bno, len] * in the btree given by cur. */ int /* error */ xfs_alloc_lookup_ge( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); } /* * Lookup the first record less than or equal to [bno, len] * in the btree given by cur. */ static int /* error */ xfs_alloc_lookup_le( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); } /* * Update the record referred to by cur to the value given * by [bno, len]. * This either works (return 0) or gets an EFSCORRUPTED error. */ STATIC int /* error */ xfs_alloc_update( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len) /* length of extent */ { union xfs_btree_rec rec; rec.alloc.ar_startblock = cpu_to_be32(bno); rec.alloc.ar_blockcount = cpu_to_be32(len); return xfs_btree_update(cur, &rec); } /* * Get the data from the pointed-to record. */ int /* error */ xfs_alloc_get_rec( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t *bno, /* output: starting block of extent */ xfs_extlen_t *len, /* output: length of extent */ int *stat) /* output: success/failure */ { union xfs_btree_rec *rec; int error; error = xfs_btree_get_rec(cur, &rec, stat); if (!error && *stat == 1) { *bno = be32_to_cpu(rec->alloc.ar_startblock); *len = be32_to_cpu(rec->alloc.ar_blockcount); } return error; } /* * Compute aligned version of the found extent. * Takes alignment and min length into account. */ STATIC void xfs_alloc_compute_aligned( xfs_alloc_arg_t *args, /* allocation argument structure */ xfs_agblock_t foundbno, /* starting block in found extent */ xfs_extlen_t foundlen, /* length in found extent */ xfs_agblock_t *resbno, /* result block number */ xfs_extlen_t *reslen) /* result length */ { xfs_agblock_t bno; xfs_extlen_t len; xfs_extlen_t diff; /* Trim busy sections out of found extent */ xfs_extent_busy_trim(args, foundbno, foundlen, &bno, &len); /* * If we have a largish extent that happens to start before min_agbno, * see if we can shift it into range... */ if (bno < args->min_agbno && bno + len > args->min_agbno) { diff = args->min_agbno - bno; if (len > diff) { bno += diff; len -= diff; } } if (args->alignment > 1 && len >= args->minlen) { xfs_agblock_t aligned_bno = roundup(bno, args->alignment); diff = aligned_bno - bno; *resbno = aligned_bno; *reslen = diff >= len ? 0 : len - diff; } else { *resbno = bno; *reslen = len; } } /* * Compute best start block and diff for "near" allocations. * freelen >= wantlen already checked by caller. */ STATIC xfs_extlen_t /* difference value (absolute) */ xfs_alloc_compute_diff( xfs_agblock_t wantbno, /* target starting block */ xfs_extlen_t wantlen, /* target length */ xfs_extlen_t alignment, /* target alignment */ int datatype, /* are we allocating data? */ xfs_agblock_t freebno, /* freespace's starting block */ xfs_extlen_t freelen, /* freespace's length */ xfs_agblock_t *newbnop) /* result: best start block from free */ { xfs_agblock_t freeend; /* end of freespace extent */ xfs_agblock_t newbno1; /* return block number */ xfs_agblock_t newbno2; /* other new block number */ xfs_extlen_t newlen1=0; /* length with newbno1 */ xfs_extlen_t newlen2=0; /* length with newbno2 */ xfs_agblock_t wantend; /* end of target extent */ bool userdata = xfs_alloc_is_userdata(datatype); ASSERT(freelen >= wantlen); freeend = freebno + freelen; wantend = wantbno + wantlen; /* * We want to allocate from the start of a free extent if it is past * the desired block or if we are allocating user data and the free * extent is before desired block. The second case is there to allow * for contiguous allocation from the remaining free space if the file * grows in the short term. */ if (freebno >= wantbno || (userdata && freeend < wantend)) { if ((newbno1 = roundup(freebno, alignment)) >= freeend) newbno1 = NULLAGBLOCK; } else if (freeend >= wantend && alignment > 1) { newbno1 = roundup(wantbno, alignment); newbno2 = newbno1 - alignment; if (newbno1 >= freeend) newbno1 = NULLAGBLOCK; else newlen1 = XFS_EXTLEN_MIN(wantlen, freeend - newbno1); if (newbno2 < freebno) newbno2 = NULLAGBLOCK; else newlen2 = XFS_EXTLEN_MIN(wantlen, freeend - newbno2); if (newbno1 != NULLAGBLOCK && newbno2 != NULLAGBLOCK) { if (newlen1 < newlen2 || (newlen1 == newlen2 && XFS_ABSDIFF(newbno1, wantbno) > XFS_ABSDIFF(newbno2, wantbno))) newbno1 = newbno2; } else if (newbno2 != NULLAGBLOCK) newbno1 = newbno2; } else if (freeend >= wantend) { newbno1 = wantbno; } else if (alignment > 1) { newbno1 = roundup(freeend - wantlen, alignment); if (newbno1 > freeend - wantlen && newbno1 - alignment >= freebno) newbno1 -= alignment; else if (newbno1 >= freeend) newbno1 = NULLAGBLOCK; } else newbno1 = freeend - wantlen; *newbnop = newbno1; return newbno1 == NULLAGBLOCK ? 0 : XFS_ABSDIFF(newbno1, wantbno); } /* * Fix up the length, based on mod and prod. * len should be k * prod + mod for some k. * If len is too small it is returned unchanged. * If len hits maxlen it is left alone. */ STATIC void xfs_alloc_fix_len( xfs_alloc_arg_t *args) /* allocation argument structure */ { xfs_extlen_t k; xfs_extlen_t rlen; ASSERT(args->mod < args->prod); rlen = args->len; ASSERT(rlen >= args->minlen); ASSERT(rlen <= args->maxlen); if (args->prod <= 1 || rlen < args->mod || rlen == args->maxlen || (args->mod == 0 && rlen < args->prod)) return; k = rlen % args->prod; if (k == args->mod) return; if (k > args->mod) rlen = rlen - (k - args->mod); else rlen = rlen - args->prod + (args->mod - k); /* casts to (int) catch length underflows */ if ((int)rlen < (int)args->minlen) return; ASSERT(rlen >= args->minlen && rlen <= args->maxlen); ASSERT(rlen % args->prod == args->mod); args->len = rlen; } /* * Fix up length if there is too little space left in the a.g. * Return 1 if ok, 0 if too little, should give up. */ STATIC int xfs_alloc_fix_minleft( xfs_alloc_arg_t *args) /* allocation argument structure */ { xfs_agf_t *agf; /* a.g. freelist header */ int diff; /* free space difference */ if (args->minleft == 0) return 1; agf = XFS_BUF_TO_AGF(args->agbp); diff = be32_to_cpu(agf->agf_freeblks) - args->len - args->minleft; if (diff >= 0) return 1; args->len += diff; /* shrink the allocated space */ /* casts to (int) catch length underflows */ if ((int)args->len >= (int)args->minlen) return 1; args->agbno = NULLAGBLOCK; return 0; } /* * Update the two btrees, logically removing from freespace the extent * starting at rbno, rlen blocks. The extent is contained within the * actual (current) free extent fbno for flen blocks. * Flags are passed in indicating whether the cursors are set to the * relevant records. */ STATIC int /* error code */ xfs_alloc_fixup_trees( xfs_btree_cur_t *cnt_cur, /* cursor for by-size btree */ xfs_btree_cur_t *bno_cur, /* cursor for by-block btree */ xfs_agblock_t fbno, /* starting block of free extent */ xfs_extlen_t flen, /* length of free extent */ xfs_agblock_t rbno, /* starting block of returned extent */ xfs_extlen_t rlen, /* length of returned extent */ int flags) /* flags, XFSA_FIXUP_... */ { int error; /* error code */ int i; /* operation results */ xfs_agblock_t nfbno1; /* first new free startblock */ xfs_agblock_t nfbno2; /* second new free startblock */ xfs_extlen_t nflen1=0; /* first new free length */ xfs_extlen_t nflen2=0; /* second new free length */ struct xfs_mount *mp; mp = cnt_cur->bc_mp; /* * Look up the record in the by-size tree if necessary. */ if (flags & XFSA_FIXUP_CNT_OK) { #ifdef DEBUG if ((error = xfs_alloc_get_rec(cnt_cur, &nfbno1, &nflen1, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1 && nfbno1 == fbno && nflen1 == flen); #endif } else { if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); } /* * Look up the record in the by-block tree if necessary. */ if (flags & XFSA_FIXUP_BNO_OK) { #ifdef DEBUG if ((error = xfs_alloc_get_rec(bno_cur, &nfbno1, &nflen1, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1 && nfbno1 == fbno && nflen1 == flen); #endif } else { if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); } #ifdef DEBUG if (bno_cur->bc_nlevels == 1 && cnt_cur->bc_nlevels == 1) { struct xfs_btree_block *bnoblock; struct xfs_btree_block *cntblock; bnoblock = XFS_BUF_TO_BLOCK(bno_cur->bc_bufs[0]); cntblock = XFS_BUF_TO_BLOCK(cnt_cur->bc_bufs[0]); XFS_WANT_CORRUPTED_RETURN(mp, bnoblock->bb_numrecs == cntblock->bb_numrecs); } #endif /* * Deal with all four cases: the allocated record is contained * within the freespace record, so we can have new freespace * at either (or both) end, or no freespace remaining. */ if (rbno == fbno && rlen == flen) nfbno1 = nfbno2 = NULLAGBLOCK; else if (rbno == fbno) { nfbno1 = rbno + rlen; nflen1 = flen - rlen; nfbno2 = NULLAGBLOCK; } else if (rbno + rlen == fbno + flen) { nfbno1 = fbno; nflen1 = flen - rlen; nfbno2 = NULLAGBLOCK; } else { nfbno1 = fbno; nflen1 = rbno - fbno; nfbno2 = rbno + rlen; nflen2 = (fbno + flen) - nfbno2; } /* * Delete the entry from the by-size btree. */ if ((error = xfs_btree_delete(cnt_cur, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); /* * Add new by-size btree entry(s). */ if (nfbno1 != NULLAGBLOCK) { if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 0); if ((error = xfs_btree_insert(cnt_cur, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); } if (nfbno2 != NULLAGBLOCK) { if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 0); if ((error = xfs_btree_insert(cnt_cur, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); } /* * Fix up the by-block btree entry(s). */ if (nfbno1 == NULLAGBLOCK) { /* * No remaining freespace, just delete the by-block tree entry. */ if ((error = xfs_btree_delete(bno_cur, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); } else { /* * Update the by-block entry to start later|be shorter. */ if ((error = xfs_alloc_update(bno_cur, nfbno1, nflen1))) return error; } if (nfbno2 != NULLAGBLOCK) { /* * 2 resulting free entries, need to add one. */ if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 0); if ((error = xfs_btree_insert(bno_cur, &i))) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); } return 0; } static bool xfs_agfl_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); int i; if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC) return false; /* * during growfs operations, the perag is not fully initialised, * so we can't use it for any useful checking. growfs ensures we can't * use it by using uncached buffers that don't have the perag attached * so we can detect and avoid this problem. */ if (bp->b_pag && be32_to_cpu(agfl->agfl_seqno) != bp->b_pag->pag_agno) return false; for (i = 0; i < XFS_AGFL_SIZE(mp); i++) { if (be32_to_cpu(agfl->agfl_bno[i]) != NULLAGBLOCK && be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks) return false; } return xfs_log_check_lsn(mp, be64_to_cpu(XFS_BUF_TO_AGFL(bp)->agfl_lsn)); } static void xfs_agfl_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; /* * There is no verification of non-crc AGFLs because mkfs does not * initialise the AGFL to zero or NULL. Hence the only valid part of the * AGFL is what the AGF says is active. We can't get to the AGF, so we * can't verify just those entries are valid. */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (!xfs_buf_verify_cksum(bp, XFS_AGFL_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_agfl_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void xfs_agfl_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; /* no verification of non-crc AGFLs */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (!xfs_agfl_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (bip) XFS_BUF_TO_AGFL(bp)->agfl_lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_AGFL_CRC_OFF); } const struct xfs_buf_ops xfs_agfl_buf_ops = { .name = "xfs_agfl", .verify_read = xfs_agfl_read_verify, .verify_write = xfs_agfl_write_verify, }; /* * Read in the allocation group free block array. */ STATIC int /* error */ xfs_alloc_read_agfl( xfs_mount_t *mp, /* mount point structure */ xfs_trans_t *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ xfs_buf_t **bpp) /* buffer for the ag free block array */ { xfs_buf_t *bp; /* return value */ int error; ASSERT(agno != NULLAGNUMBER); error = xfs_trans_read_buf( mp, tp, mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops); if (error) return error; xfs_buf_set_ref(bp, XFS_AGFL_REF); *bpp = bp; return 0; } STATIC int xfs_alloc_update_counters( struct xfs_trans *tp, struct xfs_perag *pag, struct xfs_buf *agbp, long len) { struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); pag->pagf_freeblks += len; be32_add_cpu(&agf->agf_freeblks, len); xfs_trans_agblocks_delta(tp, len); if (unlikely(be32_to_cpu(agf->agf_freeblks) > be32_to_cpu(agf->agf_length))) return -EFSCORRUPTED; xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); return 0; } /* * Allocation group level functions. */ /* * Allocate a variable extent in the allocation group agno. * Type and bno are used to determine where in the allocation group the * extent will start. * Extent's length (returned in *len) will be between minlen and maxlen, * and of the form k * prod + mod unless there's nothing that large. * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. */ STATIC int /* error */ xfs_alloc_ag_vextent( xfs_alloc_arg_t *args) /* argument structure for allocation */ { int error=0; xfs_extlen_t reservation; xfs_extlen_t oldmax; ASSERT(args->minlen > 0); ASSERT(args->maxlen > 0); ASSERT(args->minlen <= args->maxlen); ASSERT(args->mod < args->prod); ASSERT(args->alignment > 0); /* * Clamp maxlen to the amount of free space minus any reservations * that have been made. */ oldmax = args->maxlen; reservation = xfs_ag_resv_needed(args->pag, args->resv); if (args->maxlen > args->pag->pagf_freeblks - reservation) args->maxlen = args->pag->pagf_freeblks - reservation; if (args->maxlen == 0) { args->agbno = NULLAGBLOCK; args->maxlen = oldmax; return 0; } /* * Branch to correct routine based on the type. */ args->wasfromfl = 0; switch (args->type) { case XFS_ALLOCTYPE_THIS_AG: error = xfs_alloc_ag_vextent_size(args); break; case XFS_ALLOCTYPE_NEAR_BNO: error = xfs_alloc_ag_vextent_near(args); break; case XFS_ALLOCTYPE_THIS_BNO: error = xfs_alloc_ag_vextent_exact(args); break; default: ASSERT(0); /* NOTREACHED */ } args->maxlen = oldmax; if (error || args->agbno == NULLAGBLOCK) return error; ASSERT(args->len >= args->minlen); ASSERT(args->len <= args->maxlen); ASSERT(!args->wasfromfl || args->resv != XFS_AG_RESV_AGFL); ASSERT(args->agbno % args->alignment == 0); /* if not file data, insert new block into the reverse map btree */ if (args->oinfo.oi_owner != XFS_RMAP_OWN_UNKNOWN) { error = xfs_rmap_alloc(args->tp, args->agbp, args->agno, args->agbno, args->len, &args->oinfo); if (error) return error; } if (!args->wasfromfl) { error = xfs_alloc_update_counters(args->tp, args->pag, args->agbp, -((long)(args->len))); if (error) return error; ASSERT(!xfs_extent_busy_search(args->mp, args->agno, args->agbno, args->len)); } xfs_ag_resv_alloc_extent(args->pag, args->resv, args); XFS_STATS_INC(args->mp, xs_allocx); XFS_STATS_ADD(args->mp, xs_allocb, args->len); return error; } /* * Allocate a variable extent at exactly agno/bno. * Extent's length (returned in *len) will be between minlen and maxlen, * and of the form k * prod + mod unless there's nothing that large. * Return the starting a.g. block (bno), or NULLAGBLOCK if we can't do it. */ STATIC int /* error */ xfs_alloc_ag_vextent_exact( xfs_alloc_arg_t *args) /* allocation argument structure */ { xfs_btree_cur_t *bno_cur;/* by block-number btree cursor */ xfs_btree_cur_t *cnt_cur;/* by count btree cursor */ int error; xfs_agblock_t fbno; /* start block of found extent */ xfs_extlen_t flen; /* length of found extent */ xfs_agblock_t tbno; /* start block of trimmed extent */ xfs_extlen_t tlen; /* length of trimmed extent */ xfs_agblock_t tend; /* end block of trimmed extent */ int i; /* success/failure of operation */ ASSERT(args->alignment == 1); /* * Allocate/initialize a cursor for the by-number freespace btree. */ bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_BNO); /* * Lookup bno and minlen in the btree (minlen is irrelevant, really). * Look for the closest free block <= bno, it must contain bno * if any free block does. */ error = xfs_alloc_lookup_le(bno_cur, args->agbno, args->minlen, &i); if (error) goto error0; if (!i) goto not_found; /* * Grab the freespace record. */ error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); ASSERT(fbno <= args->agbno); /* * Check for overlapping busy extents. */ xfs_extent_busy_trim(args, fbno, flen, &tbno, &tlen); /* * Give up if the start of the extent is busy, or the freespace isn't * long enough for the minimum request. */ if (tbno > args->agbno) goto not_found; if (tlen < args->minlen) goto not_found; tend = tbno + tlen; if (tend < args->agbno + args->minlen) goto not_found; /* * End of extent will be smaller of the freespace end and the * maximal requested end. * * Fix the length according to mod and prod if given. */ args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen) - args->agbno; xfs_alloc_fix_len(args); if (!xfs_alloc_fix_minleft(args)) goto not_found; ASSERT(args->agbno + args->len <= tend); /* * We are allocating agbno for args->len * Allocate/initialize a cursor for the by-size btree. */ cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_CNT); ASSERT(args->agbno + args->len <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno, args->len, XFSA_FIXUP_BNO_OK); if (error) { xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); goto error0; } xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); args->wasfromfl = 0; trace_xfs_alloc_exact_done(args); return 0; not_found: /* Didn't find it, return null. */ xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); args->agbno = NULLAGBLOCK; trace_xfs_alloc_exact_notfound(args); return 0; error0: xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); trace_xfs_alloc_exact_error(args); return error; } /* * Search the btree in a given direction via the search cursor and compare * the records found against the good extent we've already found. */ STATIC int xfs_alloc_find_best_extent( struct xfs_alloc_arg *args, /* allocation argument structure */ struct xfs_btree_cur **gcur, /* good cursor */ struct xfs_btree_cur **scur, /* searching cursor */ xfs_agblock_t gdiff, /* difference for search comparison */ xfs_agblock_t *sbno, /* extent found by search */ xfs_extlen_t *slen, /* extent length */ xfs_agblock_t *sbnoa, /* aligned extent found by search */ xfs_extlen_t *slena, /* aligned extent length */ int dir) /* 0 = search right, 1 = search left */ { xfs_agblock_t new; xfs_agblock_t sdiff; int error; int i; /* The good extent is perfect, no need to search. */ if (!gdiff) goto out_use_good; /* * Look until we find a better one, run out of space or run off the end. */ do { error = xfs_alloc_get_rec(*scur, sbno, slen, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, *sbno, *slen, sbnoa, slena); /* * The good extent is closer than this one. */ if (!dir) { if (*sbnoa > args->max_agbno) goto out_use_good; if (*sbnoa >= args->agbno + gdiff) goto out_use_good; } else { if (*sbnoa < args->min_agbno) goto out_use_good; if (*sbnoa <= args->agbno - gdiff) goto out_use_good; } /* * Same distance, compare length and pick the best. */ if (*slena >= args->minlen) { args->len = XFS_EXTLEN_MIN(*slena, args->maxlen); xfs_alloc_fix_len(args); sdiff = xfs_alloc_compute_diff(args->agbno, args->len, args->alignment, args->datatype, *sbnoa, *slena, &new); /* * Choose closer size and invalidate other cursor. */ if (sdiff < gdiff) goto out_use_search; goto out_use_good; } if (!dir) error = xfs_btree_increment(*scur, 0, &i); else error = xfs_btree_decrement(*scur, 0, &i); if (error) goto error0; } while (i); out_use_good: xfs_btree_del_cursor(*scur, XFS_BTREE_NOERROR); *scur = NULL; return 0; out_use_search: xfs_btree_del_cursor(*gcur, XFS_BTREE_NOERROR); *gcur = NULL; return 0; error0: /* caller invalidates cursors */ return error; } /* * Allocate a variable extent near bno in the allocation group agno. * Extent's length (returned in len) will be between minlen and maxlen, * and of the form k * prod + mod unless there's nothing that large. * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. */ STATIC int /* error */ xfs_alloc_ag_vextent_near( xfs_alloc_arg_t *args) /* allocation argument structure */ { xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */ xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */ xfs_btree_cur_t *cnt_cur; /* cursor for count btree */ xfs_agblock_t gtbno; /* start bno of right side entry */ xfs_agblock_t gtbnoa; /* aligned ... */ xfs_extlen_t gtdiff; /* difference to right side entry */ xfs_extlen_t gtlen; /* length of right side entry */ xfs_extlen_t gtlena; /* aligned ... */ xfs_agblock_t gtnew; /* useful start bno of right side */ int error; /* error code */ int i; /* result code, temporary */ int j; /* result code, temporary */ xfs_agblock_t ltbno; /* start bno of left side entry */ xfs_agblock_t ltbnoa; /* aligned ... */ xfs_extlen_t ltdiff; /* difference to left side entry */ xfs_extlen_t ltlen; /* length of left side entry */ xfs_extlen_t ltlena; /* aligned ... */ xfs_agblock_t ltnew; /* useful start bno of left side */ xfs_extlen_t rlen; /* length of returned extent */ int forced = 0; #ifdef DEBUG /* * Randomly don't execute the first algorithm. */ int dofirst; /* set to do first algorithm */ dofirst = prandom_u32() & 1; #endif /* handle unitialized agbno range so caller doesn't have to */ if (!args->min_agbno && !args->max_agbno) args->max_agbno = args->mp->m_sb.sb_agblocks - 1; ASSERT(args->min_agbno <= args->max_agbno); /* clamp agbno to the range if it's outside */ if (args->agbno < args->min_agbno) args->agbno = args->min_agbno; if (args->agbno > args->max_agbno) args->agbno = args->max_agbno; restart: bno_cur_lt = NULL; bno_cur_gt = NULL; ltlen = 0; gtlena = 0; ltlena = 0; /* * Get a cursor for the by-size btree. */ cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_CNT); /* * See if there are any free extents as big as maxlen. */ if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, args->maxlen, &i))) goto error0; /* * If none, then pick up the last entry in the tree unless the * tree is empty. */ if (!i) { if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, <bno, <len, &i))) goto error0; if (i == 0 || ltlen == 0) { xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_near_noentry(args); return 0; } ASSERT(i == 1); } args->wasfromfl = 0; /* * First algorithm. * If the requested extent is large wrt the freespaces available * in this a.g., then the cursor will be pointing to a btree entry * near the right edge of the tree. If it's in the last btree leaf * block, then we just examine all the entries in that block * that are big enough, and pick the best one. * This is written as a while loop so we can break out of it, * but we never loop back to the top. */ while (xfs_btree_islastblock(cnt_cur, 0)) { xfs_extlen_t bdiff; int besti=0; xfs_extlen_t blen=0; xfs_agblock_t bnew=0; #ifdef DEBUG if (dofirst) break; #endif /* * Start from the entry that lookup found, sequence through * all larger free blocks. If we're actually pointing at a * record smaller than maxlen, go to the start of this block, * and skip all those smaller than minlen. */ if (ltlen || args->alignment > 1) { cnt_cur->bc_ptrs[0] = 1; do { if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); if (ltlen >= args->minlen) break; if ((error = xfs_btree_increment(cnt_cur, 0, &i))) goto error0; } while (i); ASSERT(ltlen >= args->minlen); if (!i) break; } i = cnt_cur->bc_ptrs[0]; for (j = 1, blen = 0, bdiff = 0; !error && j && (blen < args->maxlen || bdiff > 0); error = xfs_btree_increment(cnt_cur, 0, &j)) { /* * For each entry, decide if it's better than * the previous best entry. */ if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, ltbno, ltlen, <bnoa, <lena); if (ltlena < args->minlen) continue; if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno) continue; args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); xfs_alloc_fix_len(args); ASSERT(args->len >= args->minlen); if (args->len < blen) continue; ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, args->alignment, args->datatype, ltbnoa, ltlena, <new); if (ltnew != NULLAGBLOCK && (args->len > blen || ltdiff < bdiff)) { bdiff = ltdiff; bnew = ltnew; blen = args->len; besti = cnt_cur->bc_ptrs[0]; } } /* * It didn't work. We COULD be in a case where * there's a good record somewhere, so try again. */ if (blen == 0) break; /* * Point at the best entry, and retrieve it again. */ cnt_cur->bc_ptrs[0] = besti; if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); args->len = blen; if (!xfs_alloc_fix_minleft(args)) { xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_near_nominleft(args); return 0; } blen = args->len; /* * We are allocating starting at bnew for blen blocks. */ args->agbno = bnew; ASSERT(bnew >= ltbno); ASSERT(bnew + blen <= ltbno + ltlen); /* * Set up a cursor for the by-bno tree. */ bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_BNO); /* * Fix up the btree entries. */ if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, bnew, blen, XFSA_FIXUP_CNT_OK))) goto error0; xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); trace_xfs_alloc_near_first(args); return 0; } /* * Second algorithm. * Search in the by-bno tree to the left and to the right * simultaneously, until in each case we find a space big enough, * or run into the edge of the tree. When we run into the edge, * we deallocate that cursor. * If both searches succeed, we compare the two spaces and pick * the better one. * With alignment, it's possible for both to fail; the upper * level algorithm that picks allocation groups for allocations * is not supposed to do this. */ /* * Allocate and initialize the cursor for the leftward search. */ bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_BNO); /* * Lookup <= bno to find the leftward search's starting point. */ if ((error = xfs_alloc_lookup_le(bno_cur_lt, args->agbno, args->maxlen, &i))) goto error0; if (!i) { /* * Didn't find anything; use this cursor for the rightward * search. */ bno_cur_gt = bno_cur_lt; bno_cur_lt = NULL; } /* * Found something. Duplicate the cursor for the rightward search. */ else if ((error = xfs_btree_dup_cursor(bno_cur_lt, &bno_cur_gt))) goto error0; /* * Increment the cursor, so we will point at the entry just right * of the leftward entry if any, or to the leftmost entry. */ if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) goto error0; if (!i) { /* * It failed, there are no rightward entries. */ xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR); bno_cur_gt = NULL; } /* * Loop going left with the leftward cursor, right with the * rightward cursor, until either both directions give up or * we find an entry at least as big as minlen. */ do { if (bno_cur_lt) { if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, ltbno, ltlen, <bnoa, <lena); if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) break; if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) goto error0; if (!i || ltbnoa < args->min_agbno) { xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); bno_cur_lt = NULL; } } if (bno_cur_gt) { if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, gtbno, gtlen, >bnoa, >lena); if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) break; if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) goto error0; if (!i || gtbnoa > args->max_agbno) { xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR); bno_cur_gt = NULL; } } } while (bno_cur_lt || bno_cur_gt); /* * Got both cursors still active, need to find better entry. */ if (bno_cur_lt && bno_cur_gt) { if (ltlena >= args->minlen) { /* * Left side is good, look for a right side entry. */ args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); xfs_alloc_fix_len(args); ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, args->alignment, args->datatype, ltbnoa, ltlena, <new); error = xfs_alloc_find_best_extent(args, &bno_cur_lt, &bno_cur_gt, ltdiff, >bno, >len, >bnoa, >lena, 0 /* search right */); } else { ASSERT(gtlena >= args->minlen); /* * Right side is good, look for a left side entry. */ args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen); xfs_alloc_fix_len(args); gtdiff = xfs_alloc_compute_diff(args->agbno, args->len, args->alignment, args->datatype, gtbnoa, gtlena, >new); error = xfs_alloc_find_best_extent(args, &bno_cur_gt, &bno_cur_lt, gtdiff, <bno, <len, <bnoa, <lena, 1 /* search left */); } if (error) goto error0; } /* * If we couldn't get anything, give up. */ if (bno_cur_lt == NULL && bno_cur_gt == NULL) { xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); if (!forced++) { trace_xfs_alloc_near_busy(args); xfs_log_force(args->mp, XFS_LOG_SYNC); goto restart; } trace_xfs_alloc_size_neither(args); args->agbno = NULLAGBLOCK; return 0; } /* * At this point we have selected a freespace entry, either to the * left or to the right. If it's on the right, copy all the * useful variables to the "left" set so we only have one * copy of this code. */ if (bno_cur_gt) { bno_cur_lt = bno_cur_gt; bno_cur_gt = NULL; ltbno = gtbno; ltbnoa = gtbnoa; ltlen = gtlen; ltlena = gtlena; j = 1; } else j = 0; /* * Fix up the length and compute the useful address. */ args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); xfs_alloc_fix_len(args); if (!xfs_alloc_fix_minleft(args)) { trace_xfs_alloc_near_nominleft(args); xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); return 0; } rlen = args->len; (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, args->datatype, ltbnoa, ltlena, <new); ASSERT(ltnew >= ltbno); ASSERT(ltnew + rlen <= ltbnoa + ltlena); ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); ASSERT(ltnew >= args->min_agbno && ltnew <= args->max_agbno); args->agbno = ltnew; if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, ltnew, rlen, XFSA_FIXUP_BNO_OK))) goto error0; if (j) trace_xfs_alloc_near_greater(args); else trace_xfs_alloc_near_lesser(args); xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); return 0; error0: trace_xfs_alloc_near_error(args); if (cnt_cur != NULL) xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); if (bno_cur_lt != NULL) xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_ERROR); if (bno_cur_gt != NULL) xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_ERROR); return error; } /* * Allocate a variable extent anywhere in the allocation group agno. * Extent's length (returned in len) will be between minlen and maxlen, * and of the form k * prod + mod unless there's nothing that large. * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. */ STATIC int /* error */ xfs_alloc_ag_vextent_size( xfs_alloc_arg_t *args) /* allocation argument structure */ { xfs_btree_cur_t *bno_cur; /* cursor for bno btree */ xfs_btree_cur_t *cnt_cur; /* cursor for cnt btree */ int error; /* error result */ xfs_agblock_t fbno; /* start of found freespace */ xfs_extlen_t flen; /* length of found freespace */ int i; /* temp status variable */ xfs_agblock_t rbno; /* returned block number */ xfs_extlen_t rlen; /* length of returned extent */ int forced = 0; restart: /* * Allocate and initialize a cursor for the by-size btree. */ cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_CNT); bno_cur = NULL; /* * Look for an entry >= maxlen+alignment-1 blocks. */ if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, args->maxlen + args->alignment - 1, &i))) goto error0; /* * If none or we have busy extents that we cannot allocate from, then * we have to settle for a smaller extent. In the case that there are * no large extents, this will return the last entry in the tree unless * the tree is empty. In the case that there are only busy large * extents, this will return the largest small extent unless there * are no smaller extents available. */ if (!i || forced > 1) { error = xfs_alloc_ag_vextent_small(args, cnt_cur, &fbno, &flen, &i); if (error) goto error0; if (i == 0 || flen == 0) { xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_size_noentry(args); return 0; } ASSERT(i == 1); xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen); } else { /* * Search for a non-busy extent that is large enough. * If we are at low space, don't check, or if we fall of * the end of the btree, turn off the busy check and * restart. */ for (;;) { error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen); if (rlen >= args->maxlen) break; error = xfs_btree_increment(cnt_cur, 0, &i); if (error) goto error0; if (i == 0) { /* * Our only valid extents must have been busy. * Make it unbusy by forcing the log out and * retrying. If we've been here before, forcing * the log isn't making the extents available, * which means they have probably been freed in * this transaction. In that case, we have to * give up on them and we'll attempt a minlen * allocation the next time around. */ xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_size_busy(args); if (!forced++) xfs_log_force(args->mp, XFS_LOG_SYNC); goto restart; } } } /* * In the first case above, we got the last entry in the * by-size btree. Now we check to see if the space hits maxlen * once aligned; if not, we search left for something better. * This can't happen in the second case above. */ rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || (rlen <= flen && rbno + rlen <= fbno + flen), error0); if (rlen < args->maxlen) { xfs_agblock_t bestfbno; xfs_extlen_t bestflen; xfs_agblock_t bestrbno; xfs_extlen_t bestrlen; bestrlen = rlen; bestrbno = rbno; bestflen = flen; bestfbno = fbno; for (;;) { if ((error = xfs_btree_decrement(cnt_cur, 0, &i))) goto error0; if (i == 0) break; if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); if (flen < bestrlen) break; xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen); rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || (rlen <= flen && rbno + rlen <= fbno + flen), error0); if (rlen > bestrlen) { bestrlen = rlen; bestrbno = rbno; bestflen = flen; bestfbno = fbno; if (rlen == args->maxlen) break; } } if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); rlen = bestrlen; rbno = bestrbno; flen = bestflen; fbno = bestfbno; } args->wasfromfl = 0; /* * Fix up the length. */ args->len = rlen; if (rlen < args->minlen) { if (!forced++) { xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_size_busy(args); xfs_log_force(args->mp, XFS_LOG_SYNC); goto restart; } goto out_nominleft; } xfs_alloc_fix_len(args); if (!xfs_alloc_fix_minleft(args)) goto out_nominleft; rlen = args->len; XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0); /* * Allocate and initialize a cursor for the by-block tree. */ bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_BNO); if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, rbno, rlen, XFSA_FIXUP_CNT_OK))) goto error0; xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); cnt_cur = bno_cur = NULL; args->len = rlen; args->agbno = rbno; XFS_WANT_CORRUPTED_GOTO(args->mp, args->agbno + args->len <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), error0); trace_xfs_alloc_size_done(args); return 0; error0: trace_xfs_alloc_size_error(args); if (cnt_cur) xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); if (bno_cur) xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); return error; out_nominleft: xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_size_nominleft(args); args->agbno = NULLAGBLOCK; return 0; } /* * Deal with the case where only small freespaces remain. * Either return the contents of the last freespace record, * or allocate space from the freelist if there is nothing in the tree. */ STATIC int /* error */ xfs_alloc_ag_vextent_small( xfs_alloc_arg_t *args, /* allocation argument structure */ xfs_btree_cur_t *ccur, /* by-size cursor */ xfs_agblock_t *fbnop, /* result block number */ xfs_extlen_t *flenp, /* result length */ int *stat) /* status: 0-freelist, 1-normal/none */ { struct xfs_owner_info oinfo; struct xfs_perag *pag; int error; xfs_agblock_t fbno; xfs_extlen_t flen; int i; if ((error = xfs_btree_decrement(ccur, 0, &i))) goto error0; if (i) { if ((error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); } /* * Nothing in the btree, try the freelist. Make sure * to respect minleft even when pulling from the * freelist. */ else if (args->minlen == 1 && args->alignment == 1 && args->resv != XFS_AG_RESV_AGFL && (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) > args->minleft)) { error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); if (error) goto error0; if (fbno != NULLAGBLOCK) { xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, xfs_alloc_allow_busy_reuse(args->datatype)); if (xfs_alloc_is_userdata(args->datatype)) { xfs_buf_t *bp; bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno, 0); xfs_trans_binval(args->tp, bp); } args->len = 1; args->agbno = fbno; XFS_WANT_CORRUPTED_GOTO(args->mp, args->agbno + args->len <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), error0); args->wasfromfl = 1; trace_xfs_alloc_small_freelist(args); /* * If we're feeding an AGFL block to something that * doesn't live in the free space, we need to clear * out the OWN_AG rmap and add the block back to * the AGFL per-AG reservation. */ xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG); error = xfs_rmap_free(args->tp, args->agbp, args->agno, fbno, 1, &oinfo); if (error) goto error0; pag = xfs_perag_get(args->mp, args->agno); xfs_ag_resv_free_extent(pag, XFS_AG_RESV_AGFL, args->tp, 1); xfs_perag_put(pag); *stat = 0; return 0; } /* * Nothing in the freelist. */ else flen = 0; } /* * Can't allocate from the freelist for some reason. */ else { fbno = NULLAGBLOCK; flen = 0; } /* * Can't do the allocation, give up. */ if (flen < args->minlen) { args->agbno = NULLAGBLOCK; trace_xfs_alloc_small_notenough(args); flen = 0; } *fbnop = fbno; *flenp = flen; *stat = 1; trace_xfs_alloc_small_done(args); return 0; error0: trace_xfs_alloc_small_error(args); return error; } /* * Free the extent starting at agno/bno for length. */ STATIC int xfs_free_ag_extent( xfs_trans_t *tp, xfs_buf_t *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type) { xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */ int error; /* error return value */ xfs_agblock_t gtbno; /* start of right neighbor block */ xfs_extlen_t gtlen; /* length of right neighbor block */ int haveleft; /* have a left neighbor block */ int haveright; /* have a right neighbor block */ int i; /* temp, result code */ xfs_agblock_t ltbno; /* start of left neighbor block */ xfs_extlen_t ltlen; /* length of left neighbor block */ xfs_mount_t *mp; /* mount point struct for filesystem */ xfs_agblock_t nbno; /* new starting block of freespace */ xfs_extlen_t nlen; /* new length of freespace */ xfs_perag_t *pag; /* per allocation group data */ bno_cur = cnt_cur = NULL; mp = tp->t_mountp; if (oinfo->oi_owner != XFS_RMAP_OWN_UNKNOWN) { error = xfs_rmap_free(tp, agbp, agno, bno, len, oinfo); if (error) goto error0; } /* * Allocate and initialize a cursor for the by-block btree. */ bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO); /* * Look for a neighboring block on the left (lower block numbers) * that is contiguous with this space. */ if ((error = xfs_alloc_lookup_le(bno_cur, bno, len, &haveleft))) goto error0; if (haveleft) { /* * There is a block to our left. */ if ((error = xfs_alloc_get_rec(bno_cur, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * It's not contiguous, though. */ if (ltbno + ltlen < bno) haveleft = 0; else { /* * If this failure happens the request to free this * space was invalid, it's (partly) already free. * Very bad. */ XFS_WANT_CORRUPTED_GOTO(mp, ltbno + ltlen <= bno, error0); } } /* * Look for a neighboring block on the right (higher block numbers) * that is contiguous with this space. */ if ((error = xfs_btree_increment(bno_cur, 0, &haveright))) goto error0; if (haveright) { /* * There is a block to our right. */ if ((error = xfs_alloc_get_rec(bno_cur, >bno, >len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * It's not contiguous, though. */ if (bno + len < gtbno) haveright = 0; else { /* * If this failure happens the request to free this * space was invalid, it's (partly) already free. * Very bad. */ XFS_WANT_CORRUPTED_GOTO(mp, gtbno >= bno + len, error0); } } /* * Now allocate and initialize a cursor for the by-size tree. */ cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT); /* * Have both left and right contiguous neighbors. * Merge all three into a single free block. */ if (haveleft && haveright) { /* * Delete the old by-size entry on the left. */ if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * Delete the old by-size entry on the right. */ if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * Delete the old by-block entry for the right block. */ if ((error = xfs_btree_delete(bno_cur, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * Move the by-block cursor back to the left neighbor. */ if ((error = xfs_btree_decrement(bno_cur, 0, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); #ifdef DEBUG /* * Check that this is the right record: delete didn't * mangle the cursor. */ { xfs_agblock_t xxbno; xfs_extlen_t xxlen; if ((error = xfs_alloc_get_rec(bno_cur, &xxbno, &xxlen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1 && xxbno == ltbno && xxlen == ltlen, error0); } #endif /* * Update remaining by-block entry to the new, joined block. */ nbno = ltbno; nlen = len + ltlen + gtlen; if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) goto error0; } /* * Have only a left contiguous neighbor. * Merge it together with the new freespace. */ else if (haveleft) { /* * Delete the old by-size entry on the left. */ if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * Back up the by-block cursor to the left neighbor, and * update its length. */ if ((error = xfs_btree_decrement(bno_cur, 0, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); nbno = ltbno; nlen = len + ltlen; if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) goto error0; } /* * Have only a right contiguous neighbor. * Merge it together with the new freespace. */ else if (haveright) { /* * Delete the old by-size entry on the right. */ if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * Update the starting block and length of the right * neighbor in the by-block tree. */ nbno = bno; nlen = len + gtlen; if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) goto error0; } /* * No contiguous neighbors. * Insert the new freespace into the by-block tree. */ else { nbno = bno; nlen = len; if ((error = xfs_btree_insert(bno_cur, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); } xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); bno_cur = NULL; /* * In all cases we need to insert the new freespace in the by-size tree. */ if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, error0); if ((error = xfs_btree_insert(cnt_cur, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); cnt_cur = NULL; /* * Update the freespace totals in the ag and superblock. */ pag = xfs_perag_get(mp, agno); error = xfs_alloc_update_counters(tp, pag, agbp, len); xfs_ag_resv_free_extent(pag, type, tp, len); xfs_perag_put(pag); if (error) goto error0; XFS_STATS_INC(mp, xs_freex); XFS_STATS_ADD(mp, xs_freeb, len); trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL, haveleft, haveright); return 0; error0: trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL, -1, -1); if (bno_cur) xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); if (cnt_cur) xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); return error; } /* * Visible (exported) allocation/free functions. * Some of these are used just by xfs_alloc_btree.c and this file. */ /* * Compute and fill in value of m_ag_maxlevels. */ void xfs_alloc_compute_maxlevels( xfs_mount_t *mp) /* file system mount structure */ { mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr, (mp->m_sb.sb_agblocks + 1) / 2); } /* * Find the length of the longest extent in an AG. The 'need' parameter * specifies how much space we're going to need for the AGFL and the * 'reserved' parameter tells us how many blocks in this AG are reserved for * other callers. */ xfs_extlen_t xfs_alloc_longest_free_extent( struct xfs_mount *mp, struct xfs_perag *pag, xfs_extlen_t need, xfs_extlen_t reserved) { xfs_extlen_t delta = 0; /* * If the AGFL needs a recharge, we'll have to subtract that from the * longest extent. */ if (need > pag->pagf_flcount) delta = need - pag->pagf_flcount; /* * If we cannot maintain others' reservations with space from the * not-longest freesp extents, we'll have to subtract /that/ from * the longest extent too. */ if (pag->pagf_freeblks - pag->pagf_longest < reserved) delta += reserved - (pag->pagf_freeblks - pag->pagf_longest); /* * If the longest extent is long enough to satisfy all the * reservations and AGFL rules in place, we can return this extent. */ if (pag->pagf_longest > delta) return pag->pagf_longest - delta; /* Otherwise, let the caller try for 1 block if there's space. */ return pag->pagf_flcount > 0 || pag->pagf_longest > 0; } unsigned int xfs_alloc_min_freelist( struct xfs_mount *mp, struct xfs_perag *pag) { unsigned int min_free; /* space needed by-bno freespace btree */ min_free = min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_BNOi] + 1, mp->m_ag_maxlevels); /* space needed by-size freespace btree */ min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1, mp->m_ag_maxlevels); /* space needed reverse mapping used space btree */ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_RMAPi] + 1, mp->m_rmap_maxlevels); return min_free; } /* * Check if the operation we are fixing up the freelist for should go ahead or * not. If we are freeing blocks, we always allow it, otherwise the allocation * is dependent on whether the size and shape of free space available will * permit the requested allocation to take place. */ static bool xfs_alloc_space_available( struct xfs_alloc_arg *args, xfs_extlen_t min_free, int flags) { struct xfs_perag *pag = args->pag; xfs_extlen_t longest; xfs_extlen_t reservation; /* blocks that are still reserved */ int available; if (flags & XFS_ALLOC_FLAG_FREEING) return true; reservation = xfs_ag_resv_needed(pag, args->resv); /* do we have enough contiguous free space for the allocation? */ longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free, reservation); if ((args->minlen + args->alignment + args->minalignslop - 1) > longest) return false; /* do we have enough free space remaining for the allocation? */ available = (int)(pag->pagf_freeblks + pag->pagf_flcount - reservation - min_free - args->total); if (available < (int)args->minleft || available <= 0) return false; return true; } /* * Decide whether to use this allocation group for this allocation. * If so, fix up the btree freelist's size. */ int /* error */ xfs_alloc_fix_freelist( struct xfs_alloc_arg *args, /* allocation argument structure */ int flags) /* XFS_ALLOC_FLAG_... */ { struct xfs_mount *mp = args->mp; struct xfs_perag *pag = args->pag; struct xfs_trans *tp = args->tp; struct xfs_buf *agbp = NULL; struct xfs_buf *agflbp = NULL; struct xfs_alloc_arg targs; /* local allocation arguments */ xfs_agblock_t bno; /* freelist block */ xfs_extlen_t need; /* total blocks needed in freelist */ int error = 0; if (!pag->pagf_init) { error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); if (error) goto out_no_agbp; if (!pag->pagf_init) { ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); goto out_agbp_relse; } } /* * If this is a metadata preferred pag and we are user data then try * somewhere else if we are not being asked to try harder at this * point */ if (pag->pagf_metadata && xfs_alloc_is_userdata(args->datatype) && (flags & XFS_ALLOC_FLAG_TRYLOCK)) { ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); goto out_agbp_relse; } need = xfs_alloc_min_freelist(mp, pag); if (!xfs_alloc_space_available(args, need, flags)) goto out_agbp_relse; /* * Get the a.g. freespace buffer. * Can fail if we're not blocking on locks, and it's held. */ if (!agbp) { error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); if (error) goto out_no_agbp; if (!agbp) { ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); goto out_no_agbp; } } /* If there isn't enough total space or single-extent, reject it. */ need = xfs_alloc_min_freelist(mp, pag); if (!xfs_alloc_space_available(args, need, flags)) goto out_agbp_relse; /* * Make the freelist shorter if it's too long. * * Note that from this point onwards, we will always release the agf and * agfl buffers on error. This handles the case where we error out and * the buffers are clean or may not have been joined to the transaction * and hence need to be released manually. If they have been joined to * the transaction, then xfs_trans_brelse() will handle them * appropriately based on the recursion count and dirty state of the * buffer. * * XXX (dgc): When we have lots of free space, does this buy us * anything other than extra overhead when we need to put more blocks * back on the free list? Maybe we should only do this when space is * getting low or the AGFL is more than half full? * * The NOSHRINK flag prevents the AGFL from being shrunk if it's too * big; the NORMAP flag prevents AGFL expand/shrink operations from * updating the rmapbt. Both flags are used in xfs_repair while we're * rebuilding the rmapbt, and neither are used by the kernel. They're * both required to ensure that rmaps are correctly recorded for the * regenerated AGFL, bnobt, and cntbt. See repair/phase5.c and * repair/rmap.c in xfsprogs for details. */ memset(&targs, 0, sizeof(targs)); if (flags & XFS_ALLOC_FLAG_NORMAP) xfs_rmap_skip_owner_update(&targs.oinfo); else xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) { struct xfs_buf *bp; error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); if (error) goto out_agbp_relse; error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, &targs.oinfo, XFS_AG_RESV_AGFL); if (error) goto out_agbp_relse; bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); xfs_trans_binval(tp, bp); } targs.tp = tp; targs.mp = mp; targs.agbp = agbp; targs.agno = args->agno; targs.alignment = targs.minlen = targs.prod = 1; targs.type = XFS_ALLOCTYPE_THIS_AG; targs.pag = pag; error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp); if (error) goto out_agbp_relse; /* Make the freelist longer if it's too short. */ while (pag->pagf_flcount < need) { targs.agbno = 0; targs.maxlen = need - pag->pagf_flcount; targs.resv = XFS_AG_RESV_AGFL; /* Allocate as many blocks as possible at once. */ error = xfs_alloc_ag_vextent(&targs); if (error) goto out_agflbp_relse; /* * Stop if we run out. Won't happen if callers are obeying * the restrictions correctly. Can happen for free calls * on a completely full ag. */ if (targs.agbno == NULLAGBLOCK) { if (flags & XFS_ALLOC_FLAG_FREEING) break; goto out_agflbp_relse; } /* * Put each allocated block on the list. */ for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) { error = xfs_alloc_put_freelist(tp, agbp, agflbp, bno, 0); if (error) goto out_agflbp_relse; } } xfs_trans_brelse(tp, agflbp); args->agbp = agbp; return 0; out_agflbp_relse: xfs_trans_brelse(tp, agflbp); out_agbp_relse: if (agbp) xfs_trans_brelse(tp, agbp); out_no_agbp: args->agbp = NULL; return error; } /* * Get a block from the freelist. * Returns with the buffer for the block gotten. */ int /* error */ xfs_alloc_get_freelist( xfs_trans_t *tp, /* transaction pointer */ xfs_buf_t *agbp, /* buffer containing the agf structure */ xfs_agblock_t *bnop, /* block address retrieved from freelist */ int btreeblk) /* destination is a AGF btree */ { xfs_agf_t *agf; /* a.g. freespace structure */ xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */ xfs_agblock_t bno; /* block number returned */ __be32 *agfl_bno; int error; int logflags; xfs_mount_t *mp = tp->t_mountp; xfs_perag_t *pag; /* per allocation group data */ /* * Freelist is empty, give up. */ agf = XFS_BUF_TO_AGF(agbp); if (!agf->agf_flcount) { *bnop = NULLAGBLOCK; return 0; } /* * Read the array of free blocks. */ error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno), &agflbp); if (error) return error; /* * Get the block number and update the data structures. */ agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); bno = be32_to_cpu(agfl_bno[be32_to_cpu(agf->agf_flfirst)]); be32_add_cpu(&agf->agf_flfirst, 1); xfs_trans_brelse(tp, agflbp); if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) agf->agf_flfirst = 0; pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); be32_add_cpu(&agf->agf_flcount, -1); xfs_trans_agflist_delta(tp, -1); pag->pagf_flcount--; xfs_perag_put(pag); logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT; if (btreeblk) { be32_add_cpu(&agf->agf_btreeblks, 1); pag->pagf_btreeblks++; logflags |= XFS_AGF_BTREEBLKS; } xfs_alloc_log_agf(tp, agbp, logflags); *bnop = bno; return 0; } /* * Log the given fields from the agf structure. */ void xfs_alloc_log_agf( xfs_trans_t *tp, /* transaction pointer */ xfs_buf_t *bp, /* buffer for a.g. freelist header */ int fields) /* mask of fields to be logged (XFS_AGF_...) */ { int first; /* first byte offset */ int last; /* last byte offset */ static const short offsets[] = { offsetof(xfs_agf_t, agf_magicnum), offsetof(xfs_agf_t, agf_versionnum), offsetof(xfs_agf_t, agf_seqno), offsetof(xfs_agf_t, agf_length), offsetof(xfs_agf_t, agf_roots[0]), offsetof(xfs_agf_t, agf_levels[0]), offsetof(xfs_agf_t, agf_flfirst), offsetof(xfs_agf_t, agf_fllast), offsetof(xfs_agf_t, agf_flcount), offsetof(xfs_agf_t, agf_freeblks), offsetof(xfs_agf_t, agf_longest), offsetof(xfs_agf_t, agf_btreeblks), offsetof(xfs_agf_t, agf_uuid), offsetof(xfs_agf_t, agf_rmap_blocks), offsetof(xfs_agf_t, agf_refcount_blocks), offsetof(xfs_agf_t, agf_refcount_root), offsetof(xfs_agf_t, agf_refcount_level), /* needed so that we don't log the whole rest of the structure: */ offsetof(xfs_agf_t, agf_spare64), sizeof(xfs_agf_t) }; trace_xfs_agf(tp->t_mountp, XFS_BUF_TO_AGF(bp), fields, _RET_IP_); xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGF_BUF); xfs_btree_offsets(fields, offsets, XFS_AGF_NUM_BITS, &first, &last); xfs_trans_log_buf(tp, bp, (uint)first, (uint)last); } /* * Interface for inode allocation to force the pag data to be initialized. */ int /* error */ xfs_alloc_pagf_init( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ int flags) /* XFS_ALLOC_FLAGS_... */ { xfs_buf_t *bp; int error; if ((error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp))) return error; if (bp) xfs_trans_brelse(tp, bp); return 0; } /* * Put the block on the freelist for the allocation group. */ int /* error */ xfs_alloc_put_freelist( xfs_trans_t *tp, /* transaction pointer */ xfs_buf_t *agbp, /* buffer for a.g. freelist header */ xfs_buf_t *agflbp,/* buffer for a.g. free block array */ xfs_agblock_t bno, /* block being freed */ int btreeblk) /* block came from a AGF btree */ { xfs_agf_t *agf; /* a.g. freespace structure */ __be32 *blockp;/* pointer to array entry */ int error; int logflags; xfs_mount_t *mp; /* mount structure */ xfs_perag_t *pag; /* per allocation group data */ __be32 *agfl_bno; int startoff; agf = XFS_BUF_TO_AGF(agbp); mp = tp->t_mountp; if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno), &agflbp))) return error; be32_add_cpu(&agf->agf_fllast, 1); if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp)) agf->agf_fllast = 0; pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); be32_add_cpu(&agf->agf_flcount, 1); xfs_trans_agflist_delta(tp, 1); pag->pagf_flcount++; logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT; if (btreeblk) { be32_add_cpu(&agf->agf_btreeblks, -1); pag->pagf_btreeblks--; logflags |= XFS_AGF_BTREEBLKS; } xfs_perag_put(pag); xfs_alloc_log_agf(tp, agbp, logflags); ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)); agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); blockp = &agfl_bno[be32_to_cpu(agf->agf_fllast)]; *blockp = cpu_to_be32(bno); startoff = (char *)blockp - (char *)agflbp->b_addr; xfs_alloc_log_agf(tp, agbp, logflags); xfs_trans_buf_set_type(tp, agflbp, XFS_BLFT_AGFL_BUF); xfs_trans_log_buf(tp, agflbp, startoff, startoff + sizeof(xfs_agblock_t) - 1); return 0; } static bool xfs_agf_verify( struct xfs_mount *mp, struct xfs_buf *bp) { struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); if (xfs_sb_version_hascrc(&mp->m_sb)) { if (!uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(XFS_BUF_TO_AGF(bp)->agf_lsn))) return false; } if (!(agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) && XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) && be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) && be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) && be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) && be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp))) return false; if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS || be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS) return false; if (xfs_sb_version_hasrmapbt(&mp->m_sb) && be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS) return false; /* * during growfs operations, the perag is not fully initialised, * so we can't use it for any useful checking. growfs ensures we can't * use it by using uncached buffers that don't have the perag attached * so we can detect and avoid this problem. */ if (bp->b_pag && be32_to_cpu(agf->agf_seqno) != bp->b_pag->pag_agno) return false; if (xfs_sb_version_haslazysbcount(&mp->m_sb) && be32_to_cpu(agf->agf_btreeblks) > be32_to_cpu(agf->agf_length)) return false; if (xfs_sb_version_hasreflink(&mp->m_sb) && be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS) return false; return true;; } static void xfs_agf_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&mp->m_sb) && !xfs_buf_verify_cksum(bp, XFS_AGF_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (XFS_TEST_ERROR(!xfs_agf_verify(mp, bp), mp, XFS_ERRTAG_ALLOC_READ_AGF, XFS_RANDOM_ALLOC_READ_AGF)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void xfs_agf_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; if (!xfs_agf_verify(mp, bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) XFS_BUF_TO_AGF(bp)->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_AGF_CRC_OFF); } const struct xfs_buf_ops xfs_agf_buf_ops = { .name = "xfs_agf", .verify_read = xfs_agf_read_verify, .verify_write = xfs_agf_write_verify, }; /* * Read in the allocation group header (free/alloc section). */ int /* error */ xfs_read_agf( struct xfs_mount *mp, /* mount point structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ int flags, /* XFS_BUF_ */ struct xfs_buf **bpp) /* buffer for the ag freelist header */ { int error; trace_xfs_read_agf(mp, agno); ASSERT(agno != NULLAGNUMBER); error = xfs_trans_read_buf( mp, tp, mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), flags, bpp, &xfs_agf_buf_ops); if (error) return error; if (!*bpp) return 0; ASSERT(!(*bpp)->b_error); xfs_buf_set_ref(*bpp, XFS_AGF_REF); return 0; } /* * Read in the allocation group header (free/alloc section). */ int /* error */ xfs_alloc_read_agf( struct xfs_mount *mp, /* mount point structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ int flags, /* XFS_ALLOC_FLAG_... */ struct xfs_buf **bpp) /* buffer for the ag freelist header */ { struct xfs_agf *agf; /* ag freelist header */ struct xfs_perag *pag; /* per allocation group data */ int error; trace_xfs_alloc_read_agf(mp, agno); ASSERT(agno != NULLAGNUMBER); error = xfs_read_agf(mp, tp, agno, (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, bpp); if (error) return error; if (!*bpp) return 0; ASSERT(!(*bpp)->b_error); agf = XFS_BUF_TO_AGF(*bpp); pag = xfs_perag_get(mp, agno); if (!pag->pagf_init) { pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks); pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks); pag->pagf_flcount = be32_to_cpu(agf->agf_flcount); pag->pagf_longest = be32_to_cpu(agf->agf_longest); pag->pagf_levels[XFS_BTNUM_BNOi] = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]); pag->pagf_levels[XFS_BTNUM_CNTi] = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); pag->pagf_levels[XFS_BTNUM_RMAPi] = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level); spin_lock_init(&pag->pagb_lock); pag->pagb_count = 0; /* XXX: pagb_tree doesn't exist in userspace */ //pag->pagb_tree = RB_ROOT; pag->pagf_init = 1; } #ifdef DEBUG else if (!XFS_FORCED_SHUTDOWN(mp)) { ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks)); ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks)); ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount)); ASSERT(pag->pagf_longest == be32_to_cpu(agf->agf_longest)); ASSERT(pag->pagf_levels[XFS_BTNUM_BNOi] == be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi])); ASSERT(pag->pagf_levels[XFS_BTNUM_CNTi] == be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); } #endif xfs_perag_put(pag); return 0; } /* * Allocate an extent (variable-size). * Depending on the allocation type, we either look in a single allocation * group or loop over the allocation groups to find the result. */ int /* error */ xfs_alloc_vextent( xfs_alloc_arg_t *args) /* allocation argument structure */ { xfs_agblock_t agsize; /* allocation group size */ int error; int flags; /* XFS_ALLOC_FLAG_... locking flags */ xfs_extlen_t minleft;/* minimum left value, temp copy */ xfs_mount_t *mp; /* mount structure pointer */ xfs_agnumber_t sagno; /* starting allocation group number */ xfs_alloctype_t type; /* input allocation type */ int bump_rotor = 0; int no_min = 0; xfs_agnumber_t rotorstep = xfs_rotorstep; /* inode32 agf stepper */ mp = args->mp; type = args->otype = args->type; args->agbno = NULLAGBLOCK; /* * Just fix this up, for the case where the last a.g. is shorter * (or there's only one a.g.) and the caller couldn't easily figure * that out (xfs_bmap_alloc). */ agsize = mp->m_sb.sb_agblocks; if (args->maxlen > agsize) args->maxlen = agsize; if (args->alignment == 0) args->alignment = 1; ASSERT(XFS_FSB_TO_AGNO(mp, args->fsbno) < mp->m_sb.sb_agcount); ASSERT(XFS_FSB_TO_AGBNO(mp, args->fsbno) < agsize); ASSERT(args->minlen <= args->maxlen); ASSERT(args->minlen <= agsize); ASSERT(args->mod < args->prod); if (XFS_FSB_TO_AGNO(mp, args->fsbno) >= mp->m_sb.sb_agcount || XFS_FSB_TO_AGBNO(mp, args->fsbno) >= agsize || args->minlen > args->maxlen || args->minlen > agsize || args->mod >= args->prod) { args->fsbno = NULLFSBLOCK; trace_xfs_alloc_vextent_badargs(args); return 0; } minleft = args->minleft; switch (type) { case XFS_ALLOCTYPE_THIS_AG: case XFS_ALLOCTYPE_NEAR_BNO: case XFS_ALLOCTYPE_THIS_BNO: /* * These three force us into a single a.g. */ args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno); args->pag = xfs_perag_get(mp, args->agno); args->minleft = 0; error = xfs_alloc_fix_freelist(args, 0); args->minleft = minleft; if (error) { trace_xfs_alloc_vextent_nofix(args); goto error0; } if (!args->agbp) { trace_xfs_alloc_vextent_noagbp(args); break; } args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno); if ((error = xfs_alloc_ag_vextent(args))) goto error0; break; case XFS_ALLOCTYPE_START_BNO: /* * Try near allocation first, then anywhere-in-ag after * the first a.g. fails. */ if ((args->datatype & XFS_ALLOC_INITIAL_USER_DATA) && (mp->m_flags & XFS_MOUNT_32BITINODES)) { args->fsbno = XFS_AGB_TO_FSB(mp, ((mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount), 0); bump_rotor = 1; } args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno); args->type = XFS_ALLOCTYPE_NEAR_BNO; /* FALLTHROUGH */ case XFS_ALLOCTYPE_ANY_AG: case XFS_ALLOCTYPE_START_AG: case XFS_ALLOCTYPE_FIRST_AG: /* * Rotate through the allocation groups looking for a winner. */ if (type == XFS_ALLOCTYPE_ANY_AG) { /* * Start with the last place we left off. */ args->agno = sagno = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount; args->type = XFS_ALLOCTYPE_THIS_AG; flags = XFS_ALLOC_FLAG_TRYLOCK; } else if (type == XFS_ALLOCTYPE_FIRST_AG) { /* * Start with allocation group given by bno. */ args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno); args->type = XFS_ALLOCTYPE_THIS_AG; sagno = 0; flags = 0; } else { if (type == XFS_ALLOCTYPE_START_AG) args->type = XFS_ALLOCTYPE_THIS_AG; /* * Start with the given allocation group. */ args->agno = sagno = XFS_FSB_TO_AGNO(mp, args->fsbno); flags = XFS_ALLOC_FLAG_TRYLOCK; } /* * Loop over allocation groups twice; first time with * trylock set, second time without. */ for (;;) { args->pag = xfs_perag_get(mp, args->agno); if (no_min) args->minleft = 0; error = xfs_alloc_fix_freelist(args, flags); args->minleft = minleft; if (error) { trace_xfs_alloc_vextent_nofix(args); goto error0; } /* * If we get a buffer back then the allocation will fly. */ if (args->agbp) { if ((error = xfs_alloc_ag_vextent(args))) goto error0; break; } trace_xfs_alloc_vextent_loopfailed(args); /* * Didn't work, figure out the next iteration. */ if (args->agno == sagno && type == XFS_ALLOCTYPE_START_BNO) args->type = XFS_ALLOCTYPE_THIS_AG; /* * For the first allocation, we can try any AG to get * space. However, if we already have allocated a * block, we don't want to try AGs whose number is below * sagno. Otherwise, we may end up with out-of-order * locking of AGF, which might cause deadlock. */ if (++(args->agno) == mp->m_sb.sb_agcount) { if (args->firstblock != NULLFSBLOCK) args->agno = sagno; else args->agno = 0; } /* * Reached the starting a.g., must either be done * or switch to non-trylock mode. */ if (args->agno == sagno) { if (no_min == 1) { args->agbno = NULLAGBLOCK; trace_xfs_alloc_vextent_allfailed(args); break; } if (flags == 0) { no_min = 1; } else { flags = 0; if (type == XFS_ALLOCTYPE_START_BNO) { args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno); args->type = XFS_ALLOCTYPE_NEAR_BNO; } } } xfs_perag_put(args->pag); } if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) { if (args->agno == sagno) mp->m_agfrotor = (mp->m_agfrotor + 1) % (mp->m_sb.sb_agcount * rotorstep); else mp->m_agfrotor = (args->agno * rotorstep + 1) % (mp->m_sb.sb_agcount * rotorstep); } break; default: ASSERT(0); /* NOTREACHED */ } if (args->agbno == NULLAGBLOCK) args->fsbno = NULLFSBLOCK; else { args->fsbno = XFS_AGB_TO_FSB(mp, args->agno, args->agbno); #ifdef DEBUG ASSERT(args->len >= args->minlen); ASSERT(args->len <= args->maxlen); ASSERT(args->agbno % args->alignment == 0); XFS_AG_CHECK_DADDR(mp, XFS_FSB_TO_DADDR(mp, args->fsbno), args->len); #endif /* Zero the extent if we were asked to do so */ if (args->datatype & XFS_ALLOC_USERDATA_ZERO) { error = xfs_zero_extent(args->ip, args->fsbno, args->len); if (error) goto error0; } } xfs_perag_put(args->pag); return 0; error0: xfs_perag_put(args->pag); return error; } /* Ensure that the freelist is at full capacity. */ int xfs_free_extent_fix_freelist( struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **agbp) { struct xfs_alloc_arg args; int error; memset(&args, 0, sizeof(struct xfs_alloc_arg)); args.tp = tp; args.mp = tp->t_mountp; args.agno = agno; /* * validate that the block number is legal - the enables us to detect * and handle a silent filesystem corruption rather than crashing. */ if (args.agno >= args.mp->m_sb.sb_agcount) return -EFSCORRUPTED; args.pag = xfs_perag_get(args.mp, args.agno); ASSERT(args.pag); error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); if (error) goto out; *agbp = args.agbp; out: xfs_perag_put(args.pag); return error; } /* * Free an extent. * Just break up the extent address and hand off to xfs_free_ag_extent * after fixing up the freelist. */ int /* error */ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ struct xfs_owner_info *oinfo, /* extent owner */ enum xfs_ag_resv_type type) /* block reservation type */ { struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *agbp; xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno); xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); int error; ASSERT(len != 0); ASSERT(type != XFS_AG_RESV_AGFL); if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_FREE_EXTENT, XFS_RANDOM_FREE_EXTENT)) return -EIO; error = xfs_free_extent_fix_freelist(tp, agno, &agbp); if (error) return error; XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err); /* validate the extent size is legal now we have the agf locked */ XFS_WANT_CORRUPTED_GOTO(mp, agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), err); error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type); if (error) goto err; xfs_extent_busy_insert(tp, agno, agbno, len, 0); return 0; err: xfs_trans_brelse(tp, agbp); return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_alloc.h0000644000000000000000000001762313063067171016115 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_ALLOC_H__ #define __XFS_ALLOC_H__ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; struct xfs_perag; struct xfs_trans; extern struct workqueue_struct *xfs_alloc_wq; /* * Freespace allocation types. Argument to xfs_alloc_[v]extent. */ #define XFS_ALLOCTYPE_ANY_AG 0x01 /* allocate anywhere, use rotor */ #define XFS_ALLOCTYPE_FIRST_AG 0x02 /* ... start at ag 0 */ #define XFS_ALLOCTYPE_START_AG 0x04 /* anywhere, start in this a.g. */ #define XFS_ALLOCTYPE_THIS_AG 0x08 /* anywhere in this a.g. */ #define XFS_ALLOCTYPE_START_BNO 0x10 /* near this block else anywhere */ #define XFS_ALLOCTYPE_NEAR_BNO 0x20 /* in this a.g. and near this block */ #define XFS_ALLOCTYPE_THIS_BNO 0x40 /* at exactly this block */ /* this should become an enum again when the tracing code is fixed */ typedef unsigned int xfs_alloctype_t; #define XFS_ALLOC_TYPES \ { XFS_ALLOCTYPE_ANY_AG, "ANY_AG" }, \ { XFS_ALLOCTYPE_FIRST_AG, "FIRST_AG" }, \ { XFS_ALLOCTYPE_START_AG, "START_AG" }, \ { XFS_ALLOCTYPE_THIS_AG, "THIS_AG" }, \ { XFS_ALLOCTYPE_START_BNO, "START_BNO" }, \ { XFS_ALLOCTYPE_NEAR_BNO, "NEAR_BNO" }, \ { XFS_ALLOCTYPE_THIS_BNO, "THIS_BNO" } /* * Flags for xfs_alloc_fix_freelist. */ #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ #define XFS_ALLOC_FLAG_NORMAP 0x00000004 /* don't modify the rmapbt */ #define XFS_ALLOC_FLAG_NOSHRINK 0x00000008 /* don't shrink the freelist */ /* * Argument structure for xfs_alloc routines. * This is turned into a structure to avoid having 20 arguments passed * down several levels of the stack. */ typedef struct xfs_alloc_arg { struct xfs_trans *tp; /* transaction pointer */ struct xfs_mount *mp; /* file system mount point */ struct xfs_buf *agbp; /* buffer for a.g. freelist header */ struct xfs_perag *pag; /* per-ag struct for this agno */ struct xfs_inode *ip; /* for userdata zeroing method */ xfs_fsblock_t fsbno; /* file system block number */ xfs_agnumber_t agno; /* allocation group number */ xfs_agblock_t agbno; /* allocation group-relative block # */ xfs_extlen_t minlen; /* minimum size of extent */ xfs_extlen_t maxlen; /* maximum size of extent */ xfs_extlen_t mod; /* mod value for extent size */ xfs_extlen_t prod; /* prod value for extent size */ xfs_extlen_t minleft; /* min blocks must be left after us */ xfs_extlen_t total; /* total blocks needed in xaction */ xfs_extlen_t alignment; /* align answer to multiple of this */ xfs_extlen_t minalignslop; /* slop for minlen+alignment calcs */ xfs_agblock_t min_agbno; /* set an agbno range for NEAR allocs */ xfs_agblock_t max_agbno; /* ... */ xfs_extlen_t len; /* output: actual size of extent */ xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */ xfs_alloctype_t otype; /* original allocation type */ int datatype; /* mask defining data type treatment */ char wasdel; /* set if allocation was prev delayed */ char wasfromfl; /* set if allocation is from freelist */ xfs_fsblock_t firstblock; /* io first block allocated */ struct xfs_owner_info oinfo; /* owner of blocks being allocated */ enum xfs_ag_resv_type resv; /* block reservation to use */ } xfs_alloc_arg_t; /* * Defines for datatype */ #define XFS_ALLOC_USERDATA (1 << 0)/* allocation is for user data*/ #define XFS_ALLOC_INITIAL_USER_DATA (1 << 1)/* special case start of file */ #define XFS_ALLOC_USERDATA_ZERO (1 << 2)/* zero extent on allocation */ #define XFS_ALLOC_NOBUSY (1 << 3)/* Busy extents not allowed */ static inline bool xfs_alloc_is_userdata(int datatype) { return (datatype & ~XFS_ALLOC_NOBUSY) != 0; } static inline bool xfs_alloc_allow_busy_reuse(int datatype) { return (datatype & XFS_ALLOC_NOBUSY) == 0; } /* freespace limit calculations */ #define XFS_ALLOC_AGFL_RESERVE 4 unsigned int xfs_alloc_set_aside(struct xfs_mount *mp); unsigned int xfs_alloc_ag_max_usable(struct xfs_mount *mp); xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp, struct xfs_perag *pag, xfs_extlen_t need, xfs_extlen_t reserved); unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp, struct xfs_perag *pag); /* * Compute and fill in value of m_ag_maxlevels. */ void xfs_alloc_compute_maxlevels( struct xfs_mount *mp); /* file system mount structure */ /* * Get a block from the freelist. * Returns with the buffer for the block gotten. */ int /* error */ xfs_alloc_get_freelist( struct xfs_trans *tp, /* transaction pointer */ struct xfs_buf *agbp, /* buffer containing the agf structure */ xfs_agblock_t *bnop, /* block address retrieved from freelist */ int btreeblk); /* destination is a AGF btree */ /* * Log the given fields from the agf structure. */ void xfs_alloc_log_agf( struct xfs_trans *tp, /* transaction pointer */ struct xfs_buf *bp, /* buffer for a.g. freelist header */ int fields);/* mask of fields to be logged (XFS_AGF_...) */ /* * Interface for inode allocation to force the pag data to be initialized. */ int /* error */ xfs_alloc_pagf_init( struct xfs_mount *mp, /* file system mount structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ int flags); /* XFS_ALLOC_FLAGS_... */ /* * Put the block on the freelist for the allocation group. */ int /* error */ xfs_alloc_put_freelist( struct xfs_trans *tp, /* transaction pointer */ struct xfs_buf *agbp, /* buffer for a.g. freelist header */ struct xfs_buf *agflbp,/* buffer for a.g. free block array */ xfs_agblock_t bno, /* block being freed */ int btreeblk); /* owner was a AGF btree */ /* * Read in the allocation group header (free/alloc section). */ int /* error */ xfs_alloc_read_agf( struct xfs_mount *mp, /* mount point structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ int flags, /* XFS_ALLOC_FLAG_... */ struct xfs_buf **bpp); /* buffer for the ag freelist header */ /* * Allocate an extent (variable-size). */ int /* error */ xfs_alloc_vextent( xfs_alloc_arg_t *args); /* allocation argument structure */ /* * Free an extent. */ int /* error */ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ struct xfs_owner_info *oinfo, /* extent owner */ enum xfs_ag_resv_type type); /* block reservation type */ int /* error */ xfs_alloc_lookup_ge( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len, /* length of extent */ int *stat); /* success/failure */ int /* error */ xfs_alloc_get_rec( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t *bno, /* output: starting block of extent */ xfs_extlen_t *len, /* output: length of extent */ int *stat); /* output: success/failure */ int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **agbp); xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); #endif /* __XFS_ALLOC_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_alloc_btree.c0000644000000000000000000002701313063067171017263 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_btree.h" #include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" STATIC struct xfs_btree_cur * xfs_allocbt_dup_cursor( struct xfs_btree_cur *cur) { return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agbp, cur->bc_private.a.agno, cur->bc_btnum); } STATIC void xfs_allocbt_set_root( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr, int inc) { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int btnum = cur->bc_btnum; struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); ASSERT(ptr->s != 0); agf->agf_roots[btnum] = ptr->s; be32_add_cpu(&agf->agf_levels[btnum], inc); pag->pagf_levels[btnum] += inc; xfs_perag_put(pag); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); } STATIC int xfs_allocbt_alloc_block( struct xfs_btree_cur *cur, union xfs_btree_ptr *start, union xfs_btree_ptr *new, int *stat) { int error; xfs_agblock_t bno; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); /* Allocate the new block from the freelist. If we can't, give up. */ error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp, &bno, 1); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } if (bno == NULLAGBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } xfs_extent_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1, false); xfs_trans_agbtree_delta(cur->bc_tp, 1); new->s = cpu_to_be32(bno); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; } STATIC int xfs_allocbt_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); xfs_agblock_t bno; int error; bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp)); error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); if (error) return error; xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, XFS_EXTENT_BUSY_SKIP_DISCARD); xfs_trans_agbtree_delta(cur->bc_tp, -1); return 0; } /* * Update the longest extent in the AGF */ STATIC void xfs_allocbt_update_lastrec( struct xfs_btree_cur *cur, struct xfs_btree_block *block, union xfs_btree_rec *rec, int ptr, int reason) { struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); struct xfs_perag *pag; __be32 len; int numrecs; ASSERT(cur->bc_btnum == XFS_BTNUM_CNT); switch (reason) { case LASTREC_UPDATE: /* * If this is the last leaf block and it's the last record, * then update the size of the longest extent in the AG. */ if (ptr != xfs_btree_get_numrecs(block)) return; len = rec->alloc.ar_blockcount; break; case LASTREC_INSREC: if (be32_to_cpu(rec->alloc.ar_blockcount) <= be32_to_cpu(agf->agf_longest)) return; len = rec->alloc.ar_blockcount; break; case LASTREC_DELREC: numrecs = xfs_btree_get_numrecs(block); if (ptr <= numrecs) return; ASSERT(ptr == numrecs + 1); if (numrecs) { xfs_alloc_rec_t *rrp; rrp = XFS_ALLOC_REC_ADDR(cur->bc_mp, block, numrecs); len = rrp->ar_blockcount; } else { len = 0; } break; default: ASSERT(0); return; } agf->agf_longest = len; pag = xfs_perag_get(cur->bc_mp, seqno); pag->pagf_longest = be32_to_cpu(len); xfs_perag_put(pag); xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST); } STATIC int xfs_allocbt_get_minrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_alloc_mnr[level != 0]; } STATIC int xfs_allocbt_get_maxrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_alloc_mxr[level != 0]; } STATIC void xfs_allocbt_init_key_from_rec( union xfs_btree_key *key, union xfs_btree_rec *rec) { ASSERT(rec->alloc.ar_startblock != 0); key->alloc.ar_startblock = rec->alloc.ar_startblock; key->alloc.ar_blockcount = rec->alloc.ar_blockcount; } STATIC void xfs_allocbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) { ASSERT(cur->bc_rec.a.ar_startblock != 0); rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock); rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount); } STATIC void xfs_allocbt_init_ptr_from_cur( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); ASSERT(agf->agf_roots[cur->bc_btnum] != 0); ptr->s = agf->agf_roots[cur->bc_btnum]; } STATIC __int64_t xfs_allocbt_key_diff( struct xfs_btree_cur *cur, union xfs_btree_key *key) { xfs_alloc_rec_incore_t *rec = &cur->bc_rec.a; xfs_alloc_key_t *kp = &key->alloc; __int64_t diff; if (cur->bc_btnum == XFS_BTNUM_BNO) { return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock; } diff = (__int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount; if (diff) return diff; return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock; } static bool xfs_allocbt_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_perag *pag = bp->b_pag; unsigned int level; /* * magic number and level verification * * During growfs operations, we can't verify the exact level or owner as * the perag is not fully initialised and hence not attached to the * buffer. In this case, check against the maximum tree depth. * * Similarly, during log recovery we will have a perag structure * attached, but the agf information will not yet have been initialised * from the on disk AGF. Again, we can only check against maximum limits * in this case. */ level = be16_to_cpu(block->bb_level); switch (block->bb_magic) { case cpu_to_be32(XFS_ABTB_CRC_MAGIC): if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; /* fall through */ case cpu_to_be32(XFS_ABTB_MAGIC): if (pag && pag->pagf_init) { if (level >= pag->pagf_levels[XFS_BTNUM_BNOi]) return false; } else if (level >= mp->m_ag_maxlevels) return false; break; case cpu_to_be32(XFS_ABTC_CRC_MAGIC): if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; /* fall through */ case cpu_to_be32(XFS_ABTC_MAGIC): if (pag && pag->pagf_init) { if (level >= pag->pagf_levels[XFS_BTNUM_CNTi]) return false; } else if (level >= mp->m_ag_maxlevels) return false; break; default: return false; } return xfs_btree_sblock_verify(bp, mp->m_alloc_mxr[level != 0]); } static void xfs_allocbt_read_verify( struct xfs_buf *bp) { if (!xfs_btree_sblock_verify_crc(bp)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_allocbt_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_verifier_error(bp); } } static void xfs_allocbt_write_verify( struct xfs_buf *bp) { if (!xfs_allocbt_verify(bp)) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } xfs_btree_sblock_calc_crc(bp); } const struct xfs_buf_ops xfs_allocbt_buf_ops = { .name = "xfs_allocbt", .verify_read = xfs_allocbt_read_verify, .verify_write = xfs_allocbt_write_verify, }; #if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_allocbt_keys_inorder( struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2) { if (cur->bc_btnum == XFS_BTNUM_BNO) { return be32_to_cpu(k1->alloc.ar_startblock) < be32_to_cpu(k2->alloc.ar_startblock); } else { return be32_to_cpu(k1->alloc.ar_blockcount) < be32_to_cpu(k2->alloc.ar_blockcount) || (k1->alloc.ar_blockcount == k2->alloc.ar_blockcount && be32_to_cpu(k1->alloc.ar_startblock) < be32_to_cpu(k2->alloc.ar_startblock)); } } STATIC int xfs_allocbt_recs_inorder( struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2) { if (cur->bc_btnum == XFS_BTNUM_BNO) { return be32_to_cpu(r1->alloc.ar_startblock) + be32_to_cpu(r1->alloc.ar_blockcount) <= be32_to_cpu(r2->alloc.ar_startblock); } else { return be32_to_cpu(r1->alloc.ar_blockcount) < be32_to_cpu(r2->alloc.ar_blockcount) || (r1->alloc.ar_blockcount == r2->alloc.ar_blockcount && be32_to_cpu(r1->alloc.ar_startblock) < be32_to_cpu(r2->alloc.ar_startblock)); } } #endif /* DEBUG */ static const struct xfs_btree_ops xfs_allocbt_ops = { .rec_len = sizeof(xfs_alloc_rec_t), .key_len = sizeof(xfs_alloc_key_t), .dup_cursor = xfs_allocbt_dup_cursor, .set_root = xfs_allocbt_set_root, .alloc_block = xfs_allocbt_alloc_block, .free_block = xfs_allocbt_free_block, .update_lastrec = xfs_allocbt_update_lastrec, .get_minrecs = xfs_allocbt_get_minrecs, .get_maxrecs = xfs_allocbt_get_maxrecs, .init_key_from_rec = xfs_allocbt_init_key_from_rec, .init_rec_from_cur = xfs_allocbt_init_rec_from_cur, .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, .key_diff = xfs_allocbt_key_diff, .buf_ops = &xfs_allocbt_buf_ops, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_allocbt_keys_inorder, .recs_inorder = xfs_allocbt_recs_inorder, #endif }; /* * Allocate a new allocation btree cursor. */ struct xfs_btree_cur * /* new alloc btree cursor */ xfs_allocbt_init_cursor( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ struct xfs_buf *agbp, /* buffer for agf structure */ xfs_agnumber_t agno, /* allocation group number */ xfs_btnum_t btnum) /* btree identifier */ { struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); struct xfs_btree_cur *cur; ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); cur->bc_tp = tp; cur->bc_mp = mp; cur->bc_btnum = btnum; cur->bc_blocklog = mp->m_sb.sb_blocklog; cur->bc_ops = &xfs_allocbt_ops; if (btnum == XFS_BTNUM_CNT) { cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; } else { cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); } cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; if (xfs_sb_version_hascrc(&mp->m_sb)) cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; return cur; } /* * Calculate number of records in an alloc btree block. */ int xfs_allocbt_maxrecs( struct xfs_mount *mp, int blocklen, int leaf) { blocklen -= XFS_ALLOC_BLOCK_LEN(mp); if (leaf) return blocklen / sizeof(xfs_alloc_rec_t); return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t)); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_alloc_btree.h0000644000000000000000000000376113063067171017274 0ustar /* * Copyright (c) 2000,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_ALLOC_BTREE_H__ #define __XFS_ALLOC_BTREE_H__ /* * Freespace on-disk structures */ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; /* * Btree block header size depends on a superblock flag. */ #define XFS_ALLOC_BLOCK_LEN(mp) \ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN) /* * Record, key, and pointer address macros for btree blocks. * * (note that some of these may appear unused, but they are used in userspace) */ #define XFS_ALLOC_REC_ADDR(mp, block, index) \ ((xfs_alloc_rec_t *) \ ((char *)(block) + \ XFS_ALLOC_BLOCK_LEN(mp) + \ (((index) - 1) * sizeof(xfs_alloc_rec_t)))) #define XFS_ALLOC_KEY_ADDR(mp, block, index) \ ((xfs_alloc_key_t *) \ ((char *)(block) + \ XFS_ALLOC_BLOCK_LEN(mp) + \ ((index) - 1) * sizeof(xfs_alloc_key_t))) #define XFS_ALLOC_PTR_ADDR(mp, block, index, maxrecs) \ ((xfs_alloc_ptr_t *) \ ((char *)(block) + \ XFS_ALLOC_BLOCK_LEN(mp) + \ (maxrecs) * sizeof(xfs_alloc_key_t) + \ ((index) - 1) * sizeof(xfs_alloc_ptr_t))) extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *, struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t, xfs_btnum_t); extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); #endif /* __XFS_ALLOC_BTREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_attr.c0000644000000000000000000010171313063067170015761 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_attr_sf.h" #include "xfs_inode.h" #include "xfs_alloc.h" #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_bmap_btree.h" #include "xfs_attr_leaf.h" #include "xfs_attr_remote.h" #include "xfs_trans_space.h" #include "xfs_trace.h" /* * xfs_attr.c * * Provide the external interfaces to manage attribute lists. */ /*======================================================================== * Function prototypes for the kernel. *========================================================================*/ /* * Internal routines when attribute list fits inside the inode. */ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args); /* * Internal routines when attribute list is one block. */ STATIC int xfs_attr_leaf_get(xfs_da_args_t *args); STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args); STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args); /* * Internal routines when attribute list is more than one block. */ STATIC int xfs_attr_node_get(xfs_da_args_t *args); STATIC int xfs_attr_node_addname(xfs_da_args_t *args); STATIC int xfs_attr_node_removename(xfs_da_args_t *args); STATIC int xfs_attr_fillstate(xfs_da_state_t *state); STATIC int xfs_attr_refillstate(xfs_da_state_t *state); STATIC int xfs_attr_args_init( struct xfs_da_args *args, struct xfs_inode *dp, const unsigned char *name, int flags) { if (!name) return -EINVAL; memset(args, 0, sizeof(*args)); args->geo = dp->i_mount->m_attr_geo; args->whichfork = XFS_ATTR_FORK; args->dp = dp; args->flags = flags; args->name = name; args->namelen = strlen((const char *)name); if (args->namelen >= MAXNAMELEN) return -EFAULT; /* match IRIX behaviour */ args->hashval = xfs_da_hashname(args->name, args->namelen); return 0; } int xfs_inode_hasattr( struct xfs_inode *ip) { if (!XFS_IFORK_Q(ip) || (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && ip->i_d.di_anextents == 0)) return 0; return 1; } /*======================================================================== * Overall external interface routines. *========================================================================*/ int xfs_attr_get( struct xfs_inode *ip, const unsigned char *name, unsigned char *value, int *valuelenp, int flags) { struct xfs_da_args args; uint lock_mode; int error; XFS_STATS_INC(ip->i_mount, xs_attr_get); if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return -EIO; if (!xfs_inode_hasattr(ip)) return -ENOATTR; error = xfs_attr_args_init(&args, ip, name, flags); if (error) return error; args.value = value; args.valuelen = *valuelenp; lock_mode = xfs_ilock_attr_map_shared(ip); if (!xfs_inode_hasattr(ip)) error = -ENOATTR; else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) error = xfs_attr_shortform_getvalue(&args); else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) error = xfs_attr_leaf_get(&args); else error = xfs_attr_node_get(&args); xfs_iunlock(ip, lock_mode); *valuelenp = args.valuelen; return error == -EEXIST ? 0 : error; } /* * Calculate how many blocks we need for the new attribute, */ STATIC int xfs_attr_calc_size( struct xfs_da_args *args, int *local) { struct xfs_mount *mp = args->dp->i_mount; int size; int nblks; /* * Determine space new attribute will use, and if it would be * "local" or "remote" (note: local != inline). */ size = xfs_attr_leaf_newentsize(args, local); nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); if (*local) { if (size > (args->geo->blksize / 2)) { /* Double split possible */ nblks *= 2; } } else { /* * Out of line attribute, cannot double split, but * make room for the attribute value itself. */ uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen); nblks += dblocks; nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); } return nblks; } int xfs_attr_set( struct xfs_inode *dp, const unsigned char *name, unsigned char *value, int valuelen, int flags) { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; struct xfs_defer_ops dfops; struct xfs_trans_res tres; xfs_fsblock_t firstblock; int rsvd = (flags & ATTR_ROOT) != 0; int error, err2, local; XFS_STATS_INC(mp, xs_attr_set); if (XFS_FORCED_SHUTDOWN(dp->i_mount)) return -EIO; error = xfs_attr_args_init(&args, dp, name, flags); if (error) return error; args.value = value; args.valuelen = valuelen; args.firstblock = &firstblock; args.dfops = &dfops; args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; args.total = xfs_attr_calc_size(&args, &local); error = xfs_qm_dqattach(dp, 0); if (error) return error; /* * If the inode doesn't have an attribute fork, add one. * (inode must not be locked when we call this routine) */ if (XFS_IFORK_Q(dp) == 0) { int sf_size = sizeof(xfs_attr_sf_hdr_t) + XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen); error = xfs_bmap_add_attrfork(dp, sf_size, rsvd); if (error) return error; } tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres + M_RES(mp)->tr_attrsetrt.tr_logres * args.total; tres.tr_logcount = XFS_ATTRSET_LOG_COUNT; tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; /* * Root fork attributes can use reserved data blocks for this * operation if necessary */ error = xfs_trans_alloc(mp, &tres, args.total, 0, rsvd ? XFS_TRANS_RESERVE : 0, &args.trans); if (error) return error; xfs_ilock(dp, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0, rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : XFS_QMOPT_RES_REGBLKS); if (error) { xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_trans_cancel(args.trans); return error; } xfs_trans_ijoin(args.trans, dp, 0); /* * If the attribute list is non-existent or a shortform list, * upgrade it to a single-leaf-block attribute list. */ if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL || (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && dp->i_d.di_anextents == 0)) { /* * Build initial attribute list (if required). */ if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) xfs_attr_shortform_create(&args); /* * Try to add the attr to the attribute list in * the inode. */ error = xfs_attr_shortform_addname(&args); if (error != -ENOSPC) { /* * Commit the shortform mods, and we're done. * NOTE: this is also the error path (EEXIST, etc). */ ASSERT(args.trans != NULL); /* * If this is a synchronous mount, make sure that * the transaction goes to disk before returning * to the user. */ if (mp->m_flags & XFS_MOUNT_WSYNC) xfs_trans_set_sync(args.trans); if (!error && (flags & ATTR_KERNOTIME) == 0) { xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); } err2 = xfs_trans_commit(args.trans); xfs_iunlock(dp, XFS_ILOCK_EXCL); return error ? error : err2; } /* * It won't fit in the shortform, transform to a leaf block. * GROT: another possible req'mt for a double-split btree op. */ xfs_defer_init(args.dfops, args.firstblock); error = xfs_attr_shortform_to_leaf(&args); if (!error) error = xfs_defer_finish(&args.trans, args.dfops, dp); if (error) { args.trans = NULL; xfs_defer_cancel(&dfops); goto out; } /* * Commit the leaf transformation. We'll need another (linked) * transaction to add the new attribute to the leaf. */ error = xfs_trans_roll(&args.trans, dp); if (error) goto out; } if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) error = xfs_attr_leaf_addname(&args); else error = xfs_attr_node_addname(&args); if (error) goto out; /* * If this is a synchronous mount, make sure that the * transaction goes to disk before returning to the user. */ if (mp->m_flags & XFS_MOUNT_WSYNC) xfs_trans_set_sync(args.trans); if ((flags & ATTR_KERNOTIME) == 0) xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); /* * Commit the last in the sequence of transactions. */ xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE); error = xfs_trans_commit(args.trans); xfs_iunlock(dp, XFS_ILOCK_EXCL); return error; out: if (args.trans) xfs_trans_cancel(args.trans); xfs_iunlock(dp, XFS_ILOCK_EXCL); return error; } /* * Generic handler routine to remove a name from an attribute list. * Transitions attribute list from Btree to shortform as necessary. */ int xfs_attr_remove( struct xfs_inode *dp, const unsigned char *name, int flags) { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; struct xfs_defer_ops dfops; xfs_fsblock_t firstblock; int error; XFS_STATS_INC(mp, xs_attr_remove); if (XFS_FORCED_SHUTDOWN(dp->i_mount)) return -EIO; if (!xfs_inode_hasattr(dp)) return -ENOATTR; error = xfs_attr_args_init(&args, dp, name, flags); if (error) return error; args.firstblock = &firstblock; args.dfops = &dfops; /* * we have no control over the attribute names that userspace passes us * to remove, so we have to allow the name lookup prior to attribute * removal to fail. */ args.op_flags = XFS_DA_OP_OKNOENT; error = xfs_qm_dqattach(dp, 0); if (error) return error; /* * Root fork attributes can use reserved data blocks for this * operation if necessary */ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_attrrm, XFS_ATTRRM_SPACE_RES(mp), 0, (flags & ATTR_ROOT) ? XFS_TRANS_RESERVE : 0, &args.trans); if (error) return error; xfs_ilock(dp, XFS_ILOCK_EXCL); /* * No need to make quota reservations here. We expect to release some * blocks not allocate in the common case. */ xfs_trans_ijoin(args.trans, dp, 0); if (!xfs_inode_hasattr(dp)) { error = -ENOATTR; } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); error = xfs_attr_shortform_remove(&args); } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { error = xfs_attr_leaf_removename(&args); } else { error = xfs_attr_node_removename(&args); } if (error) goto out; /* * If this is a synchronous mount, make sure that the * transaction goes to disk before returning to the user. */ if (mp->m_flags & XFS_MOUNT_WSYNC) xfs_trans_set_sync(args.trans); if ((flags & ATTR_KERNOTIME) == 0) xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); /* * Commit the last in the sequence of transactions. */ xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE); error = xfs_trans_commit(args.trans); xfs_iunlock(dp, XFS_ILOCK_EXCL); return error; out: if (args.trans) xfs_trans_cancel(args.trans); xfs_iunlock(dp, XFS_ILOCK_EXCL); return error; } /*======================================================================== * External routines when attribute list is inside the inode *========================================================================*/ /* * Add a name to the shortform attribute list structure * This is the external routine. */ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args) { int newsize, forkoff, retval; trace_xfs_attr_sf_addname(args); retval = xfs_attr_shortform_lookup(args); if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) { return retval; } else if (retval == -EEXIST) { if (args->flags & ATTR_CREATE) return retval; retval = xfs_attr_shortform_remove(args); ASSERT(retval == 0); } if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX || args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX) return -ENOSPC; newsize = XFS_ATTR_SF_TOTSIZE(args->dp); newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize); if (!forkoff) return -ENOSPC; xfs_attr_shortform_add(args, forkoff); return 0; } /*======================================================================== * External routines when attribute list is one block *========================================================================*/ /* * Add a name to the leaf attribute list structure * * This leaf block cannot have a "remote" value, we only call this routine * if bmap_one_block() says there is only one block (ie: no remote blks). */ STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args) { xfs_inode_t *dp; struct xfs_buf *bp; int retval, error, forkoff; trace_xfs_attr_leaf_addname(args); /* * Read the (only) block in the attribute list in. */ dp = args->dp; args->blkno = 0; error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); if (error) return error; /* * Look up the given attribute in the leaf block. Figure out if * the given flags produce an error or call for an atomic rename. */ retval = xfs_attr3_leaf_lookup_int(bp, args); if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) { xfs_trans_brelse(args->trans, bp); return retval; } else if (retval == -EEXIST) { if (args->flags & ATTR_CREATE) { /* pure create op */ xfs_trans_brelse(args->trans, bp); return retval; } trace_xfs_attr_leaf_replace(args); /* save the attribute state for later removal*/ args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */ args->blkno2 = args->blkno; /* set 2nd entry info*/ args->index2 = args->index; args->rmtblkno2 = args->rmtblkno; args->rmtblkcnt2 = args->rmtblkcnt; args->rmtvaluelen2 = args->rmtvaluelen; /* * clear the remote attr state now that it is saved so that the * values reflect the state of the attribute we are about to * add, not the attribute we just found and will remove later. */ args->rmtblkno = 0; args->rmtblkcnt = 0; args->rmtvaluelen = 0; } /* * Add the attribute to the leaf block, transitioning to a Btree * if required. */ retval = xfs_attr3_leaf_add(bp, args); if (retval == -ENOSPC) { /* * Promote the attribute list to the Btree format, then * Commit that transaction so that the node_addname() call * can manage its own transactions. */ xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); return error; } /* * Commit the current trans (including the inode) and start * a new one. */ error = xfs_trans_roll(&args->trans, dp); if (error) return error; /* * Fob the whole rest of the problem off on the Btree code. */ error = xfs_attr_node_addname(args); return error; } /* * Commit the transaction that added the attr name so that * later routines can manage their own transactions. */ error = xfs_trans_roll(&args->trans, dp); if (error) return error; /* * If there was an out-of-line value, allocate the blocks we * identified for its storage and copy the value. This is done * after we create the attribute so that we don't overflow the * maximum size of a transaction and/or hit a deadlock. */ if (args->rmtblkno > 0) { error = xfs_attr_rmtval_set(args); if (error) return error; } /* * If this is an atomic rename operation, we must "flip" the * incomplete flags on the "new" and "old" attribute/value pairs * so that one disappears and one appears atomically. Then we * must remove the "old" attribute/value pair. */ if (args->op_flags & XFS_DA_OP_RENAME) { /* * In a separate transaction, set the incomplete flag on the * "old" attr and clear the incomplete flag on the "new" attr. */ error = xfs_attr3_leaf_flipflags(args); if (error) return error; /* * Dismantle the "old" attribute/value pair by removing * a "remote" value (if it exists). */ args->index = args->index2; args->blkno = args->blkno2; args->rmtblkno = args->rmtblkno2; args->rmtblkcnt = args->rmtblkcnt2; args->rmtvaluelen = args->rmtvaluelen2; if (args->rmtblkno) { error = xfs_attr_rmtval_remove(args); if (error) return error; } /* * Read in the block containing the "old" attr, then * remove the "old" attr from that block (neat, huh!) */ error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); if (error) return error; xfs_attr3_leaf_remove(bp, args); /* * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); return error; } } /* * Commit the remove and start the next trans in series. */ error = xfs_trans_roll(&args->trans, dp); } else if (args->rmtblkno > 0) { /* * Added a "remote" value, just clear the incomplete flag. */ error = xfs_attr3_leaf_clearflag(args); } return error; } /* * Remove a name from the leaf attribute list structure * * This leaf block cannot have a "remote" value, we only call this routine * if bmap_one_block() says there is only one block (ie: no remote blks). */ STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args) { xfs_inode_t *dp; struct xfs_buf *bp; int error, forkoff; trace_xfs_attr_leaf_removename(args); /* * Remove the attribute. */ dp = args->dp; args->blkno = 0; error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); if (error) return error; error = xfs_attr3_leaf_lookup_int(bp, args); if (error == -ENOATTR) { xfs_trans_brelse(args->trans, bp); return error; } xfs_attr3_leaf_remove(bp, args); /* * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); return error; } } return 0; } /* * Look up a name in a leaf attribute list structure. * * This leaf block cannot have a "remote" value, we only call this routine * if bmap_one_block() says there is only one block (ie: no remote blks). */ STATIC int xfs_attr_leaf_get(xfs_da_args_t *args) { struct xfs_buf *bp; int error; trace_xfs_attr_leaf_get(args); args->blkno = 0; error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); if (error) return error; error = xfs_attr3_leaf_lookup_int(bp, args); if (error != -EEXIST) { xfs_trans_brelse(args->trans, bp); return error; } error = xfs_attr3_leaf_getvalue(bp, args); xfs_trans_brelse(args->trans, bp); if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) { error = xfs_attr_rmtval_get(args); } return error; } /*======================================================================== * External routines when attribute list size > geo->blksize *========================================================================*/ /* * Add a name to a Btree-format attribute list. * * This will involve walking down the Btree, and may involve splitting * leaf nodes and even splitting intermediate nodes up to and including * the root node (a special case of an intermediate node). * * "Remote" attribute values confuse the issue and atomic rename operations * add a whole extra layer of confusion on top of that. */ STATIC int xfs_attr_node_addname(xfs_da_args_t *args) { xfs_da_state_t *state; xfs_da_state_blk_t *blk; xfs_inode_t *dp; xfs_mount_t *mp; int retval, error; trace_xfs_attr_node_addname(args); /* * Fill in bucket of arguments/results/context to carry around. */ dp = args->dp; mp = dp->i_mount; restart: state = xfs_da_state_alloc(); state->args = args; state->mp = mp; /* * Search to see if name already exists, and get back a pointer * to where it should go. */ error = xfs_da3_node_lookup_int(state, &retval); if (error) goto out; blk = &state->path.blk[ state->path.active-1 ]; ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) { goto out; } else if (retval == -EEXIST) { if (args->flags & ATTR_CREATE) goto out; trace_xfs_attr_node_replace(args); /* save the attribute state for later removal*/ args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */ args->blkno2 = args->blkno; /* set 2nd entry info*/ args->index2 = args->index; args->rmtblkno2 = args->rmtblkno; args->rmtblkcnt2 = args->rmtblkcnt; args->rmtvaluelen2 = args->rmtvaluelen; /* * clear the remote attr state now that it is saved so that the * values reflect the state of the attribute we are about to * add, not the attribute we just found and will remove later. */ args->rmtblkno = 0; args->rmtblkcnt = 0; args->rmtvaluelen = 0; } retval = xfs_attr3_leaf_add(blk->bp, state->args); if (retval == -ENOSPC) { if (state->path.active == 1) { /* * Its really a single leaf node, but it had * out-of-line values so it looked like it *might* * have been a b-tree. */ xfs_da_state_free(state); state = NULL; xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); goto out; } /* * Commit the node conversion and start the next * trans in the chain. */ error = xfs_trans_roll(&args->trans, dp); if (error) goto out; goto restart; } /* * Split as many Btree elements as required. * This code tracks the new and old attr's location * in the index/blkno/rmtblkno/rmtblkcnt fields and * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_split(state); if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); goto out; } } else { /* * Addition succeeded, update Btree hashvals. */ xfs_da3_fixhashpath(state, &state->path); } /* * Kill the state structure, we're done with it and need to * allow the buffers to come back later. */ xfs_da_state_free(state); state = NULL; /* * Commit the leaf addition or btree split and start the next * trans in the chain. */ error = xfs_trans_roll(&args->trans, dp); if (error) goto out; /* * If there was an out-of-line value, allocate the blocks we * identified for its storage and copy the value. This is done * after we create the attribute so that we don't overflow the * maximum size of a transaction and/or hit a deadlock. */ if (args->rmtblkno > 0) { error = xfs_attr_rmtval_set(args); if (error) return error; } /* * If this is an atomic rename operation, we must "flip" the * incomplete flags on the "new" and "old" attribute/value pairs * so that one disappears and one appears atomically. Then we * must remove the "old" attribute/value pair. */ if (args->op_flags & XFS_DA_OP_RENAME) { /* * In a separate transaction, set the incomplete flag on the * "old" attr and clear the incomplete flag on the "new" attr. */ error = xfs_attr3_leaf_flipflags(args); if (error) goto out; /* * Dismantle the "old" attribute/value pair by removing * a "remote" value (if it exists). */ args->index = args->index2; args->blkno = args->blkno2; args->rmtblkno = args->rmtblkno2; args->rmtblkcnt = args->rmtblkcnt2; args->rmtvaluelen = args->rmtvaluelen2; if (args->rmtblkno) { error = xfs_attr_rmtval_remove(args); if (error) return error; } /* * Re-find the "old" attribute entry after any split ops. * The INCOMPLETE flag means that we will find the "old" * attr, not the "new" one. */ args->flags |= XFS_ATTR_INCOMPLETE; state = xfs_da_state_alloc(); state->args = args; state->mp = mp; state->inleaf = 0; error = xfs_da3_node_lookup_int(state, &retval); if (error) goto out; /* * Remove the name and update the hashvals in the tree. */ blk = &state->path.blk[ state->path.active-1 ]; ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); error = xfs_attr3_leaf_remove(blk->bp, args); xfs_da3_fixhashpath(state, &state->path); /* * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_join(state); if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); goto out; } } /* * Commit and start the next trans in the chain. */ error = xfs_trans_roll(&args->trans, dp); if (error) goto out; } else if (args->rmtblkno > 0) { /* * Added a "remote" value, just clear the incomplete flag. */ error = xfs_attr3_leaf_clearflag(args); if (error) goto out; } retval = error = 0; out: if (state) xfs_da_state_free(state); if (error) return error; return retval; } /* * Remove a name from a B-tree attribute list. * * This will involve walking down the Btree, and may involve joining * leaf nodes and even joining intermediate nodes up to and including * the root node (a special case of an intermediate node). */ STATIC int xfs_attr_node_removename(xfs_da_args_t *args) { xfs_da_state_t *state; xfs_da_state_blk_t *blk; xfs_inode_t *dp; struct xfs_buf *bp; int retval, error, forkoff; trace_xfs_attr_node_removename(args); /* * Tie a string around our finger to remind us where we are. */ dp = args->dp; state = xfs_da_state_alloc(); state->args = args; state->mp = dp->i_mount; /* * Search to see if name exists, and get back a pointer to it. */ error = xfs_da3_node_lookup_int(state, &retval); if (error || (retval != -EEXIST)) { if (error == 0) error = retval; goto out; } /* * If there is an out-of-line value, de-allocate the blocks. * This is done before we remove the attribute so that we don't * overflow the maximum size of a transaction and/or hit a deadlock. */ blk = &state->path.blk[ state->path.active-1 ]; ASSERT(blk->bp != NULL); ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); if (args->rmtblkno > 0) { /* * Fill in disk block numbers in the state structure * so that we can get the buffers back after we commit * several transactions in the following calls. */ error = xfs_attr_fillstate(state); if (error) goto out; /* * Mark the attribute as INCOMPLETE, then bunmapi() the * remote value. */ error = xfs_attr3_leaf_setflag(args); if (error) goto out; error = xfs_attr_rmtval_remove(args); if (error) goto out; /* * Refill the state structure with buffers, the prior calls * released our buffers. */ error = xfs_attr_refillstate(state); if (error) goto out; } /* * Remove the name and update the hashvals in the tree. */ blk = &state->path.blk[ state->path.active-1 ]; ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); retval = xfs_attr3_leaf_remove(blk->bp, args); xfs_da3_fixhashpath(state, &state->path); /* * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_join(state); if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); goto out; } /* * Commit the Btree join operation and start a new trans. */ error = xfs_trans_roll(&args->trans, dp); if (error) goto out; } /* * If the result is small enough, push it all into the inode. */ if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { /* * Have to get rid of the copy of this dabuf in the state. */ ASSERT(state->path.active == 1); ASSERT(state->path.blk[0].bp); state->path.blk[0].bp = NULL; error = xfs_attr3_leaf_read(args->trans, args->dp, 0, -1, &bp); if (error) goto out; if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); goto out; } } else xfs_trans_brelse(args->trans, bp); } error = 0; out: xfs_da_state_free(state); return error; } /* * Fill in the disk block numbers in the state structure for the buffers * that are attached to the state structure. * This is done so that we can quickly reattach ourselves to those buffers * after some set of transaction commits have released these buffers. */ STATIC int xfs_attr_fillstate(xfs_da_state_t *state) { xfs_da_state_path_t *path; xfs_da_state_blk_t *blk; int level; trace_xfs_attr_fillstate(state->args); /* * Roll down the "path" in the state structure, storing the on-disk * block number for those buffers in the "path". */ path = &state->path; ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); for (blk = path->blk, level = 0; level < path->active; blk++, level++) { if (blk->bp) { blk->disk_blkno = XFS_BUF_ADDR(blk->bp); blk->bp = NULL; } else { blk->disk_blkno = 0; } } /* * Roll down the "altpath" in the state structure, storing the on-disk * block number for those buffers in the "altpath". */ path = &state->altpath; ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); for (blk = path->blk, level = 0; level < path->active; blk++, level++) { if (blk->bp) { blk->disk_blkno = XFS_BUF_ADDR(blk->bp); blk->bp = NULL; } else { blk->disk_blkno = 0; } } return 0; } /* * Reattach the buffers to the state structure based on the disk block * numbers stored in the state structure. * This is done after some set of transaction commits have released those * buffers from our grip. */ STATIC int xfs_attr_refillstate(xfs_da_state_t *state) { xfs_da_state_path_t *path; xfs_da_state_blk_t *blk; int level, error; trace_xfs_attr_refillstate(state->args); /* * Roll down the "path" in the state structure, storing the on-disk * block number for those buffers in the "path". */ path = &state->path; ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); for (blk = path->blk, level = 0; level < path->active; blk++, level++) { if (blk->disk_blkno) { error = xfs_da3_node_read(state->args->trans, state->args->dp, blk->blkno, blk->disk_blkno, &blk->bp, XFS_ATTR_FORK); if (error) return error; } else { blk->bp = NULL; } } /* * Roll down the "altpath" in the state structure, storing the on-disk * block number for those buffers in the "altpath". */ path = &state->altpath; ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); for (blk = path->blk, level = 0; level < path->active; blk++, level++) { if (blk->disk_blkno) { error = xfs_da3_node_read(state->args->trans, state->args->dp, blk->blkno, blk->disk_blkno, &blk->bp, XFS_ATTR_FORK); if (error) return error; } else { blk->bp = NULL; } } return 0; } /* * Look up a filename in a node attribute list. * * This routine gets called for any attribute fork that has more than one * block, ie: both true Btree attr lists and for single-leaf-blocks with * "remote" values taking up more blocks. */ STATIC int xfs_attr_node_get(xfs_da_args_t *args) { xfs_da_state_t *state; xfs_da_state_blk_t *blk; int error, retval; int i; trace_xfs_attr_node_get(args); state = xfs_da_state_alloc(); state->args = args; state->mp = args->dp->i_mount; /* * Search to see if name exists, and get back a pointer to it. */ error = xfs_da3_node_lookup_int(state, &retval); if (error) { retval = error; } else if (retval == -EEXIST) { blk = &state->path.blk[ state->path.active-1 ]; ASSERT(blk->bp != NULL); ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); /* * Get the value, local or "remote" */ retval = xfs_attr3_leaf_getvalue(blk->bp, args); if (!retval && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) { retval = xfs_attr_rmtval_get(args); } } /* * If not in a transaction, we have to release all the buffers. */ for (i = 0; i < state->path.active; i++) { xfs_trans_brelse(args->trans, state->path.blk[i].bp); state->path.blk[i].bp = NULL; } xfs_da_state_free(state); return retval; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_attr_leaf.c0000644000000000000000000023533313063067171016757 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_bmap_btree.h" #include "xfs_bmap.h" #include "xfs_attr_sf.h" #include "xfs_attr_remote.h" #include "xfs_attr_leaf.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_dir2.h" /* * xfs_attr_leaf.c * * Routines to implement leaf blocks of attributes as Btrees of hashed names. */ /*======================================================================== * Function prototypes for the kernel. *========================================================================*/ /* * Routines used for growing the Btree. */ STATIC int xfs_attr3_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block, struct xfs_buf **bpp); STATIC int xfs_attr3_leaf_add_work(struct xfs_buf *leaf_buffer, struct xfs_attr3_icleaf_hdr *ichdr, struct xfs_da_args *args, int freemap_index); STATIC void xfs_attr3_leaf_compact(struct xfs_da_args *args, struct xfs_attr3_icleaf_hdr *ichdr, struct xfs_buf *leaf_buffer); STATIC void xfs_attr3_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_da_state_blk_t *blk2); STATIC int xfs_attr3_leaf_figure_balance(xfs_da_state_t *state, xfs_da_state_blk_t *leaf_blk_1, struct xfs_attr3_icleaf_hdr *ichdr1, xfs_da_state_blk_t *leaf_blk_2, struct xfs_attr3_icleaf_hdr *ichdr2, int *number_entries_in_blk1, int *number_usedbytes_in_blk1); /* * Utility routines. */ STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args, struct xfs_attr_leafblock *src_leaf, struct xfs_attr3_icleaf_hdr *src_ichdr, int src_start, struct xfs_attr_leafblock *dst_leaf, struct xfs_attr3_icleaf_hdr *dst_ichdr, int dst_start, int move_count); STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); /* * attr3 block 'firstused' conversion helpers. * * firstused refers to the offset of the first used byte of the nameval region * of an attr leaf block. The region starts at the tail of the block and expands * backwards towards the middle. As such, firstused is initialized to the block * size for an empty leaf block and is reduced from there. * * The attr3 block size is pegged to the fsb size and the maximum fsb is 64k. * The in-core firstused field is 32-bit and thus supports the maximum fsb size. * The on-disk field is only 16-bit, however, and overflows at 64k. Since this * only occurs at exactly 64k, we use zero as a magic on-disk value to represent * the attr block size. The following helpers manage the conversion between the * in-core and on-disk formats. */ static void xfs_attr3_leaf_firstused_from_disk( struct xfs_da_geometry *geo, struct xfs_attr3_icleaf_hdr *to, struct xfs_attr_leafblock *from) { struct xfs_attr3_leaf_hdr *hdr3; if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) { hdr3 = (struct xfs_attr3_leaf_hdr *) from; to->firstused = be16_to_cpu(hdr3->firstused); } else { to->firstused = be16_to_cpu(from->hdr.firstused); } /* * Convert from the magic fsb size value to actual blocksize. This * should only occur for empty blocks when the block size overflows * 16-bits. */ if (to->firstused == XFS_ATTR3_LEAF_NULLOFF) { ASSERT(!to->count && !to->usedbytes); ASSERT(geo->blksize > USHRT_MAX); to->firstused = geo->blksize; } } static void xfs_attr3_leaf_firstused_to_disk( struct xfs_da_geometry *geo, struct xfs_attr_leafblock *to, struct xfs_attr3_icleaf_hdr *from) { struct xfs_attr3_leaf_hdr *hdr3; uint32_t firstused; /* magic value should only be seen on disk */ ASSERT(from->firstused != XFS_ATTR3_LEAF_NULLOFF); /* * Scale down the 32-bit in-core firstused value to the 16-bit on-disk * value. This only overflows at the max supported value of 64k. Use the * magic on-disk value to represent block size in this case. */ firstused = from->firstused; if (firstused > USHRT_MAX) { ASSERT(from->firstused == geo->blksize); firstused = XFS_ATTR3_LEAF_NULLOFF; } if (from->magic == XFS_ATTR3_LEAF_MAGIC) { hdr3 = (struct xfs_attr3_leaf_hdr *) to; hdr3->firstused = cpu_to_be16(firstused); } else { to->hdr.firstused = cpu_to_be16(firstused); } } void xfs_attr3_leaf_hdr_from_disk( struct xfs_da_geometry *geo, struct xfs_attr3_icleaf_hdr *to, struct xfs_attr_leafblock *from) { int i; ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC) || from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)); if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) { struct xfs_attr3_leaf_hdr *hdr3 = (struct xfs_attr3_leaf_hdr *)from; to->forw = be32_to_cpu(hdr3->info.hdr.forw); to->back = be32_to_cpu(hdr3->info.hdr.back); to->magic = be16_to_cpu(hdr3->info.hdr.magic); to->count = be16_to_cpu(hdr3->count); to->usedbytes = be16_to_cpu(hdr3->usedbytes); xfs_attr3_leaf_firstused_from_disk(geo, to, from); to->holes = hdr3->holes; for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { to->freemap[i].base = be16_to_cpu(hdr3->freemap[i].base); to->freemap[i].size = be16_to_cpu(hdr3->freemap[i].size); } return; } to->forw = be32_to_cpu(from->hdr.info.forw); to->back = be32_to_cpu(from->hdr.info.back); to->magic = be16_to_cpu(from->hdr.info.magic); to->count = be16_to_cpu(from->hdr.count); to->usedbytes = be16_to_cpu(from->hdr.usedbytes); xfs_attr3_leaf_firstused_from_disk(geo, to, from); to->holes = from->hdr.holes; for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { to->freemap[i].base = be16_to_cpu(from->hdr.freemap[i].base); to->freemap[i].size = be16_to_cpu(from->hdr.freemap[i].size); } } void xfs_attr3_leaf_hdr_to_disk( struct xfs_da_geometry *geo, struct xfs_attr_leafblock *to, struct xfs_attr3_icleaf_hdr *from) { int i; ASSERT(from->magic == XFS_ATTR_LEAF_MAGIC || from->magic == XFS_ATTR3_LEAF_MAGIC); if (from->magic == XFS_ATTR3_LEAF_MAGIC) { struct xfs_attr3_leaf_hdr *hdr3 = (struct xfs_attr3_leaf_hdr *)to; hdr3->info.hdr.forw = cpu_to_be32(from->forw); hdr3->info.hdr.back = cpu_to_be32(from->back); hdr3->info.hdr.magic = cpu_to_be16(from->magic); hdr3->count = cpu_to_be16(from->count); hdr3->usedbytes = cpu_to_be16(from->usedbytes); xfs_attr3_leaf_firstused_to_disk(geo, to, from); hdr3->holes = from->holes; hdr3->pad1 = 0; for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { hdr3->freemap[i].base = cpu_to_be16(from->freemap[i].base); hdr3->freemap[i].size = cpu_to_be16(from->freemap[i].size); } return; } to->hdr.info.forw = cpu_to_be32(from->forw); to->hdr.info.back = cpu_to_be32(from->back); to->hdr.info.magic = cpu_to_be16(from->magic); to->hdr.count = cpu_to_be16(from->count); to->hdr.usedbytes = cpu_to_be16(from->usedbytes); xfs_attr3_leaf_firstused_to_disk(geo, to, from); to->hdr.holes = from->holes; to->hdr.pad1 = 0; for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { to->hdr.freemap[i].base = cpu_to_be16(from->freemap[i].base); to->hdr.freemap[i].size = cpu_to_be16(from->freemap[i].size); } } static bool xfs_attr3_leaf_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_attr_leafblock *leaf = bp->b_addr; struct xfs_attr3_icleaf_hdr ichdr; xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf); if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_da3_node_hdr *hdr3 = bp->b_addr; if (ichdr.magic != XFS_ATTR3_LEAF_MAGIC) return false; if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn))) return false; } else { if (ichdr.magic != XFS_ATTR_LEAF_MAGIC) return false; } if (ichdr.count == 0) return false; /* XXX: need to range check rest of attr header values */ /* XXX: hash order check? */ return true; } static void xfs_attr3_leaf_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr; if (!xfs_attr3_leaf_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF); } /* * leaf/node format detection on trees is sketchy, so a node read can be done on * leaf level blocks when detection identifies the tree as a node format tree * incorrectly. In this case, we need to swap the verifier to match the correct * format of the block being read. */ static void xfs_attr3_leaf_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&mp->m_sb) && !xfs_buf_verify_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_attr3_leaf_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = { .name = "xfs_attr3_leaf", .verify_read = xfs_attr3_leaf_read_verify, .verify_write = xfs_attr3_leaf_write_verify, }; int xfs_attr3_leaf_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp) { int err; err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops); if (!err && tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_ATTR_LEAF_BUF); return err; } /*======================================================================== * Namespace helper routines *========================================================================*/ /* * If namespace bits don't match return 0. * If all match then return 1. */ STATIC int xfs_attr_namesp_match(int arg_flags, int ondisk_flags) { return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); } /*======================================================================== * External routines when attribute fork size < XFS_LITINO(mp). *========================================================================*/ /* * Query whether the requested number of additional bytes of extended * attribute space will be able to fit inline. * * Returns zero if not, else the di_forkoff fork offset to be used in the * literal area for attribute data once the new bytes have been added. * * di_forkoff must be 8 byte aligned, hence is stored as a >>3 value; * special case for dev/uuid inodes, they have fixed size data forks. */ int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) { int offset; int minforkoff; /* lower limit on valid forkoff locations */ int maxforkoff; /* upper limit on valid forkoff locations */ int dsize; xfs_mount_t *mp = dp->i_mount; /* rounded down */ offset = (XFS_LITINO(mp, dp->i_d.di_version) - bytes) >> 3; switch (dp->i_d.di_format) { case XFS_DINODE_FMT_DEV: minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; return (offset >= minforkoff) ? minforkoff : 0; case XFS_DINODE_FMT_UUID: minforkoff = roundup(sizeof(uuid_t), 8) >> 3; return (offset >= minforkoff) ? minforkoff : 0; } /* * If the requested numbers of bytes is smaller or equal to the * current attribute fork size we can always proceed. * * Note that if_bytes in the data fork might actually be larger than * the current data fork size is due to delalloc extents. In that * case either the extent count will go down when they are converted * to real extents, or the delalloc conversion will take care of the * literal area rebalancing. */ if (bytes <= XFS_IFORK_ASIZE(dp)) return dp->i_d.di_forkoff; /* * For attr2 we can try to move the forkoff if there is space in the * literal area, but for the old format we are done if there is no * space in the fixed attribute fork. */ if (!(mp->m_flags & XFS_MOUNT_ATTR2)) return 0; dsize = dp->i_df.if_bytes; switch (dp->i_d.di_format) { case XFS_DINODE_FMT_EXTENTS: /* * If there is no attr fork and the data fork is extents, * determine if creating the default attr fork will result * in the extents form migrating to btree. If so, the * minimum offset only needs to be the space required for * the btree root. */ if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > xfs_default_attroffset(dp)) dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); break; case XFS_DINODE_FMT_BTREE: /* * If we have a data btree then keep forkoff if we have one, * otherwise we are adding a new attr, so then we set * minforkoff to where the btree root can finish so we have * plenty of room for attrs */ if (dp->i_d.di_forkoff) { if (offset < dp->i_d.di_forkoff) return 0; return dp->i_d.di_forkoff; } dsize = XFS_BMAP_BROOT_SPACE(mp, dp->i_df.if_broot); break; } /* * A data fork btree root must have space for at least * MINDBTPTRS key/ptr pairs if the data fork is small or empty. */ minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); minforkoff = roundup(minforkoff, 8) >> 3; /* attr fork btree root can have at least this many key/ptr pairs */ maxforkoff = XFS_LITINO(mp, dp->i_d.di_version) - XFS_BMDR_SPACE_CALC(MINABTPTRS); maxforkoff = maxforkoff >> 3; /* rounded down */ if (offset >= maxforkoff) return maxforkoff; if (offset >= minforkoff) return offset; return 0; } /* * Switch on the ATTR2 superblock bit (implies also FEATURES2) */ STATIC void xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp) { if ((mp->m_flags & XFS_MOUNT_ATTR2) && !(xfs_sb_version_hasattr2(&mp->m_sb))) { spin_lock(&mp->m_sb_lock); if (!xfs_sb_version_hasattr2(&mp->m_sb)) { xfs_sb_version_addattr2(&mp->m_sb); spin_unlock(&mp->m_sb_lock); xfs_log_sb(tp); } else spin_unlock(&mp->m_sb_lock); } } /* * Create the initial contents of a shortform attribute list. */ void xfs_attr_shortform_create(xfs_da_args_t *args) { xfs_attr_sf_hdr_t *hdr; xfs_inode_t *dp; xfs_ifork_t *ifp; trace_xfs_attr_sf_create(args); dp = args->dp; ASSERT(dp != NULL); ifp = dp->i_afp; ASSERT(ifp != NULL); ASSERT(ifp->if_bytes == 0); if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) { ifp->if_flags &= ~XFS_IFEXTENTS; /* just in case */ dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL; ifp->if_flags |= XFS_IFINLINE; } else { ASSERT(ifp->if_flags & XFS_IFINLINE); } xfs_idata_realloc(dp, sizeof(*hdr), XFS_ATTR_FORK); hdr = (xfs_attr_sf_hdr_t *)ifp->if_u1.if_data; hdr->count = 0; hdr->totsize = cpu_to_be16(sizeof(*hdr)); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); } /* * Add a name/value pair to the shortform attribute list. * Overflow from the inode has already been checked for. */ void xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) { xfs_attr_shortform_t *sf; xfs_attr_sf_entry_t *sfe; int i, offset, size; xfs_mount_t *mp; xfs_inode_t *dp; xfs_ifork_t *ifp; trace_xfs_attr_sf_add(args); dp = args->dp; mp = dp->i_mount; dp->i_d.di_forkoff = forkoff; ifp = dp->i_afp; ASSERT(ifp->if_flags & XFS_IFINLINE); sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; sfe = &sf->list[0]; for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { #ifdef DEBUG if (sfe->namelen != args->namelen) continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; if (!xfs_attr_namesp_match(args->flags, sfe->flags)) continue; ASSERT(0); #endif } offset = (char *)sfe - (char *)sf; size = XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); xfs_idata_realloc(dp, size, XFS_ATTR_FORK); sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; sfe = (xfs_attr_sf_entry_t *)((char *)sf + offset); sfe->namelen = args->namelen; sfe->valuelen = args->valuelen; sfe->flags = XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); memcpy(sfe->nameval, args->name, args->namelen); memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); sf->hdr.count++; be16_add_cpu(&sf->hdr.totsize, size); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); xfs_sbversion_add_attr2(mp, args->trans); } /* * After the last attribute is removed revert to original inode format, * making all literal area available to the data fork once more. */ void xfs_attr_fork_remove( struct xfs_inode *ip, struct xfs_trans *tp) { xfs_idestroy_fork(ip, XFS_ATTR_FORK); ip->i_d.di_forkoff = 0; ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; ASSERT(ip->i_d.di_anextents == 0); ASSERT(ip->i_afp == NULL); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } /* * Remove an attribute from the shortform attribute list structure. */ int xfs_attr_shortform_remove(xfs_da_args_t *args) { xfs_attr_shortform_t *sf; xfs_attr_sf_entry_t *sfe; int base, size=0, end, totsize, i; xfs_mount_t *mp; xfs_inode_t *dp; trace_xfs_attr_sf_remove(args); dp = args->dp; mp = dp->i_mount; base = sizeof(xfs_attr_sf_hdr_t); sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; sfe = &sf->list[0]; end = sf->hdr.count; for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), base += size, i++) { size = XFS_ATTR_SF_ENTSIZE(sfe); if (sfe->namelen != args->namelen) continue; if (memcmp(sfe->nameval, args->name, args->namelen) != 0) continue; if (!xfs_attr_namesp_match(args->flags, sfe->flags)) continue; break; } if (i == end) return -ENOATTR; /* * Fix up the attribute fork data, covering the hole */ end = base + size; totsize = be16_to_cpu(sf->hdr.totsize); if (end != totsize) memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end); sf->hdr.count--; be16_add_cpu(&sf->hdr.totsize, -size); /* * Fix up the start offset of the attribute fork */ totsize -= size; if (totsize == sizeof(xfs_attr_sf_hdr_t) && (mp->m_flags & XFS_MOUNT_ATTR2) && (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && !(args->op_flags & XFS_DA_OP_ADDNAME)) { xfs_attr_fork_remove(dp, args->trans); } else { xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); ASSERT(dp->i_d.di_forkoff); ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || (args->op_flags & XFS_DA_OP_ADDNAME) || !(mp->m_flags & XFS_MOUNT_ATTR2) || dp->i_d.di_format == XFS_DINODE_FMT_BTREE); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); } xfs_sbversion_add_attr2(mp, args->trans); return 0; } /* * Look up a name in a shortform attribute list structure. */ /*ARGSUSED*/ int xfs_attr_shortform_lookup(xfs_da_args_t *args) { xfs_attr_shortform_t *sf; xfs_attr_sf_entry_t *sfe; int i; xfs_ifork_t *ifp; trace_xfs_attr_sf_lookup(args); ifp = args->dp->i_afp; ASSERT(ifp->if_flags & XFS_IFINLINE); sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; sfe = &sf->list[0]; for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { if (sfe->namelen != args->namelen) continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; if (!xfs_attr_namesp_match(args->flags, sfe->flags)) continue; return -EEXIST; } return -ENOATTR; } /* * Look up a name in a shortform attribute list structure. */ /*ARGSUSED*/ int xfs_attr_shortform_getvalue(xfs_da_args_t *args) { xfs_attr_shortform_t *sf; xfs_attr_sf_entry_t *sfe; int i; ASSERT(args->dp->i_afp->if_flags == XFS_IFINLINE); sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data; sfe = &sf->list[0]; for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { if (sfe->namelen != args->namelen) continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; if (!xfs_attr_namesp_match(args->flags, sfe->flags)) continue; if (args->flags & ATTR_KERNOVAL) { args->valuelen = sfe->valuelen; return -EEXIST; } if (args->valuelen < sfe->valuelen) { args->valuelen = sfe->valuelen; return -ERANGE; } args->valuelen = sfe->valuelen; memcpy(args->value, &sfe->nameval[args->namelen], args->valuelen); return -EEXIST; } return -ENOATTR; } /* * Convert from using the shortform to the leaf. */ int xfs_attr_shortform_to_leaf(xfs_da_args_t *args) { xfs_inode_t *dp; xfs_attr_shortform_t *sf; xfs_attr_sf_entry_t *sfe; xfs_da_args_t nargs; char *tmpbuffer; int error, i, size; xfs_dablk_t blkno; struct xfs_buf *bp; xfs_ifork_t *ifp; trace_xfs_attr_sf_to_leaf(args); dp = args->dp; ifp = dp->i_afp; sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; size = be16_to_cpu(sf->hdr.totsize); tmpbuffer = kmem_alloc(size, KM_SLEEP); ASSERT(tmpbuffer != NULL); memcpy(tmpbuffer, ifp->if_u1.if_data, size); sf = (xfs_attr_shortform_t *)tmpbuffer; xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); xfs_bmap_local_to_extents_empty(dp, XFS_ATTR_FORK); bp = NULL; error = xfs_da_grow_inode(args, &blkno); if (error) { /* * If we hit an IO error middle of the transaction inside * grow_inode(), we may have inconsistent data. Bail out. */ if (error == -EIO) goto out; xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ goto out; } ASSERT(blkno == 0); error = xfs_attr3_leaf_create(args, blkno, &bp); if (error) { error = xfs_da_shrink_inode(args, 0, bp); bp = NULL; if (error) goto out; xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ goto out; } memset((char *)&nargs, 0, sizeof(nargs)); nargs.dp = dp; nargs.geo = args->geo; nargs.firstblock = args->firstblock; nargs.dfops = args->dfops; nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; nargs.op_flags = XFS_DA_OP_OKNOENT; sfe = &sf->list[0]; for (i = 0; i < sf->hdr.count; i++) { nargs.name = sfe->nameval; nargs.namelen = sfe->namelen; nargs.value = &sfe->nameval[nargs.namelen]; nargs.valuelen = sfe->valuelen; nargs.hashval = xfs_da_hashname(sfe->nameval, sfe->namelen); nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags); error = xfs_attr3_leaf_lookup_int(bp, &nargs); /* set a->index */ ASSERT(error == -ENOATTR); error = xfs_attr3_leaf_add(bp, &nargs); ASSERT(error != -ENOSPC); if (error) goto out; sfe = XFS_ATTR_SF_NEXTENTRY(sfe); } error = 0; out: kmem_free(tmpbuffer); return error; } /* * Check a leaf attribute block to see if all the entries would fit into * a shortform attribute list. */ int xfs_attr_shortform_allfit( struct xfs_buf *bp, struct xfs_inode *dp) { struct xfs_attr_leafblock *leaf; struct xfs_attr_leaf_entry *entry; xfs_attr_leaf_name_local_t *name_loc; struct xfs_attr3_icleaf_hdr leafhdr; int bytes; int i; struct xfs_mount *mp = bp->b_target->bt_mount; leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); entry = xfs_attr3_leaf_entryp(leaf); bytes = sizeof(struct xfs_attr_sf_hdr); for (i = 0; i < leafhdr.count; entry++, i++) { if (entry->flags & XFS_ATTR_INCOMPLETE) continue; /* don't copy partial entries */ if (!(entry->flags & XFS_ATTR_LOCAL)) return 0; name_loc = xfs_attr3_leaf_name_local(leaf, i); if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX) return 0; if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) return 0; bytes += sizeof(struct xfs_attr_sf_entry) - 1 + name_loc->namelen + be16_to_cpu(name_loc->valuelen); } if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && (bytes == sizeof(struct xfs_attr_sf_hdr))) return -1; return xfs_attr_shortform_bytesfit(dp, bytes); } /* * Convert a leaf attribute list to shortform attribute list */ int xfs_attr3_leaf_to_shortform( struct xfs_buf *bp, struct xfs_da_args *args, int forkoff) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr ichdr; struct xfs_attr_leaf_entry *entry; struct xfs_attr_leaf_name_local *name_loc; struct xfs_da_args nargs; struct xfs_inode *dp = args->dp; char *tmpbuffer; int error; int i; trace_xfs_attr_leaf_to_sf(args); tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP); if (!tmpbuffer) return -ENOMEM; memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); leaf = (xfs_attr_leafblock_t *)tmpbuffer; xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); entry = xfs_attr3_leaf_entryp(leaf); /* XXX (dgc): buffer is about to be marked stale - why zero it? */ memset(bp->b_addr, 0, args->geo->blksize); /* * Clean out the prior contents of the attribute list. */ error = xfs_da_shrink_inode(args, 0, bp); if (error) goto out; if (forkoff == -1) { ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); xfs_attr_fork_remove(dp, args->trans); goto out; } xfs_attr_shortform_create(args); /* * Copy the attributes */ memset((char *)&nargs, 0, sizeof(nargs)); nargs.geo = args->geo; nargs.dp = dp; nargs.firstblock = args->firstblock; nargs.dfops = args->dfops; nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; nargs.op_flags = XFS_DA_OP_OKNOENT; for (i = 0; i < ichdr.count; entry++, i++) { if (entry->flags & XFS_ATTR_INCOMPLETE) continue; /* don't copy partial entries */ if (!entry->nameidx) continue; ASSERT(entry->flags & XFS_ATTR_LOCAL); name_loc = xfs_attr3_leaf_name_local(leaf, i); nargs.name = name_loc->nameval; nargs.namelen = name_loc->namelen; nargs.value = &name_loc->nameval[nargs.namelen]; nargs.valuelen = be16_to_cpu(name_loc->valuelen); nargs.hashval = be32_to_cpu(entry->hashval); nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags); xfs_attr_shortform_add(&nargs, forkoff); } error = 0; out: kmem_free(tmpbuffer); return error; } /* * Convert from using a single leaf to a root node and a leaf. */ int xfs_attr3_leaf_to_node( struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr icleafhdr; struct xfs_attr_leaf_entry *entries; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr icnodehdr; struct xfs_da_intnode *node; struct xfs_inode *dp = args->dp; struct xfs_mount *mp = dp->i_mount; struct xfs_buf *bp1 = NULL; struct xfs_buf *bp2 = NULL; xfs_dablk_t blkno; int error; trace_xfs_attr_leaf_to_node(args); error = xfs_da_grow_inode(args, &blkno); if (error) goto out; error = xfs_attr3_leaf_read(args->trans, dp, 0, -1, &bp1); if (error) goto out; error = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp2, XFS_ATTR_FORK); if (error) goto out; /* copy leaf to new buffer, update identifiers */ xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF); bp2->b_ops = bp1->b_ops; memcpy(bp2->b_addr, bp1->b_addr, args->geo->blksize); if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_da3_blkinfo *hdr3 = bp2->b_addr; hdr3->blkno = cpu_to_be64(bp2->b_bn); } xfs_trans_log_buf(args->trans, bp2, 0, args->geo->blksize - 1); /* * Set up the new root node. */ error = xfs_da3_node_create(args, 0, 1, &bp1, XFS_ATTR_FORK); if (error) goto out; node = bp1->b_addr; dp->d_ops->node_hdr_from_disk(&icnodehdr, node); btree = dp->d_ops->node_tree_p(node); leaf = bp2->b_addr; xfs_attr3_leaf_hdr_from_disk(args->geo, &icleafhdr, leaf); entries = xfs_attr3_leaf_entryp(leaf); /* both on-disk, don't endian-flip twice */ btree[0].hashval = entries[icleafhdr.count - 1].hashval; btree[0].before = cpu_to_be32(blkno); icnodehdr.count = 1; dp->d_ops->node_hdr_to_disk(node, &icnodehdr); xfs_trans_log_buf(args->trans, bp1, 0, args->geo->blksize - 1); error = 0; out: return error; } /*======================================================================== * Routines used for growing the Btree. *========================================================================*/ /* * Create the initial contents of a leaf attribute list * or a leaf in a node attribute list. */ STATIC int xfs_attr3_leaf_create( struct xfs_da_args *args, xfs_dablk_t blkno, struct xfs_buf **bpp) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr ichdr; struct xfs_inode *dp = args->dp; struct xfs_mount *mp = dp->i_mount; struct xfs_buf *bp; int error; trace_xfs_attr_leaf_create(args); error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp, XFS_ATTR_FORK); if (error) return error; bp->b_ops = &xfs_attr3_leaf_buf_ops; xfs_trans_buf_set_type(args->trans, bp, XFS_BLFT_ATTR_LEAF_BUF); leaf = bp->b_addr; memset(leaf, 0, args->geo->blksize); memset(&ichdr, 0, sizeof(ichdr)); ichdr.firstused = args->geo->blksize; if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_da3_blkinfo *hdr3 = bp->b_addr; ichdr.magic = XFS_ATTR3_LEAF_MAGIC; hdr3->blkno = cpu_to_be64(bp->b_bn); hdr3->owner = cpu_to_be64(dp->i_ino); uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr); } else { ichdr.magic = XFS_ATTR_LEAF_MAGIC; ichdr.freemap[0].base = sizeof(struct xfs_attr_leaf_hdr); } ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base; xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr); xfs_trans_log_buf(args->trans, bp, 0, args->geo->blksize - 1); *bpp = bp; return 0; } /* * Split the leaf node, rebalance, then add the new entry. */ int xfs_attr3_leaf_split( struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk) { xfs_dablk_t blkno; int error; trace_xfs_attr_leaf_split(state->args); /* * Allocate space for a new leaf node. */ ASSERT(oldblk->magic == XFS_ATTR_LEAF_MAGIC); error = xfs_da_grow_inode(state->args, &blkno); if (error) return error; error = xfs_attr3_leaf_create(state->args, blkno, &newblk->bp); if (error) return error; newblk->blkno = blkno; newblk->magic = XFS_ATTR_LEAF_MAGIC; /* * Rebalance the entries across the two leaves. * NOTE: rebalance() currently depends on the 2nd block being empty. */ xfs_attr3_leaf_rebalance(state, oldblk, newblk); error = xfs_da3_blk_link(state, oldblk, newblk); if (error) return error; /* * Save info on "old" attribute for "atomic rename" ops, leaf_add() * modifies the index/blkno/rmtblk/rmtblkcnt fields to show the * "new" attrs info. Will need the "old" info to remove it later. * * Insert the "new" entry in the correct block. */ if (state->inleaf) { trace_xfs_attr_leaf_add_old(state->args); error = xfs_attr3_leaf_add(oldblk->bp, state->args); } else { trace_xfs_attr_leaf_add_new(state->args); error = xfs_attr3_leaf_add(newblk->bp, state->args); } /* * Update last hashval in each block since we added the name. */ oldblk->hashval = xfs_attr_leaf_lasthash(oldblk->bp, NULL); newblk->hashval = xfs_attr_leaf_lasthash(newblk->bp, NULL); return error; } /* * Add a name to the leaf attribute list structure. */ int xfs_attr3_leaf_add( struct xfs_buf *bp, struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr ichdr; int tablesize; int entsize; int sum; int tmp; int i; trace_xfs_attr_leaf_add(args); leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); ASSERT(args->index >= 0 && args->index <= ichdr.count); entsize = xfs_attr_leaf_newentsize(args, NULL); /* * Search through freemap for first-fit on new name length. * (may need to figure in size of entry struct too) */ tablesize = (ichdr.count + 1) * sizeof(xfs_attr_leaf_entry_t) + xfs_attr3_leaf_hdr_size(leaf); for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE - 1; i >= 0; i--) { if (tablesize > ichdr.firstused) { sum += ichdr.freemap[i].size; continue; } if (!ichdr.freemap[i].size) continue; /* no space in this map */ tmp = entsize; if (ichdr.freemap[i].base < ichdr.firstused) tmp += sizeof(xfs_attr_leaf_entry_t); if (ichdr.freemap[i].size >= tmp) { tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, i); goto out_log_hdr; } sum += ichdr.freemap[i].size; } /* * If there are no holes in the address space of the block, * and we don't have enough freespace, then compaction will do us * no good and we should just give up. */ if (!ichdr.holes && sum < entsize) return -ENOSPC; /* * Compact the entries to coalesce free space. * This may change the hdr->count via dropping INCOMPLETE entries. */ xfs_attr3_leaf_compact(args, &ichdr, bp); /* * After compaction, the block is guaranteed to have only one * free region, in freemap[0]. If it is not big enough, give up. */ if (ichdr.freemap[0].size < (entsize + sizeof(xfs_attr_leaf_entry_t))) { tmp = -ENOSPC; goto out_log_hdr; } tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, 0); out_log_hdr: xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr); xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, &leaf->hdr, xfs_attr3_leaf_hdr_size(leaf))); return tmp; } /* * Add a name to a leaf attribute list structure. */ STATIC int xfs_attr3_leaf_add_work( struct xfs_buf *bp, struct xfs_attr3_icleaf_hdr *ichdr, struct xfs_da_args *args, int mapindex) { struct xfs_attr_leafblock *leaf; struct xfs_attr_leaf_entry *entry; struct xfs_attr_leaf_name_local *name_loc; struct xfs_attr_leaf_name_remote *name_rmt; struct xfs_mount *mp; int tmp; int i; trace_xfs_attr_leaf_add_work(args); leaf = bp->b_addr; ASSERT(mapindex >= 0 && mapindex < XFS_ATTR_LEAF_MAPSIZE); ASSERT(args->index >= 0 && args->index <= ichdr->count); /* * Force open some space in the entry array and fill it in. */ entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; if (args->index < ichdr->count) { tmp = ichdr->count - args->index; tmp *= sizeof(xfs_attr_leaf_entry_t); memmove(entry + 1, entry, tmp); xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); } ichdr->count++; /* * Allocate space for the new string (at the end of the run). */ mp = args->trans->t_mountp; ASSERT(ichdr->freemap[mapindex].base < args->geo->blksize); ASSERT((ichdr->freemap[mapindex].base & 0x3) == 0); ASSERT(ichdr->freemap[mapindex].size >= xfs_attr_leaf_newentsize(args, NULL)); ASSERT(ichdr->freemap[mapindex].size < args->geo->blksize); ASSERT((ichdr->freemap[mapindex].size & 0x3) == 0); ichdr->freemap[mapindex].size -= xfs_attr_leaf_newentsize(args, &tmp); entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base + ichdr->freemap[mapindex].size); entry->hashval = cpu_to_be32(args->hashval); entry->flags = tmp ? XFS_ATTR_LOCAL : 0; entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); if (args->op_flags & XFS_DA_OP_RENAME) { entry->flags |= XFS_ATTR_INCOMPLETE; if ((args->blkno2 == args->blkno) && (args->index2 <= args->index)) { args->index2++; } } xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); ASSERT((args->index == 0) || (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval))); ASSERT((args->index == ichdr->count - 1) || (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval))); /* * For "remote" attribute values, simply note that we need to * allocate space for the "remote" value. We can't actually * allocate the extents in this transaction, and we can't decide * which blocks they should be as we might allocate more blocks * as part of this transaction (a split operation for example). */ if (entry->flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf, args->index); name_loc->namelen = args->namelen; name_loc->valuelen = cpu_to_be16(args->valuelen); memcpy((char *)name_loc->nameval, args->name, args->namelen); memcpy((char *)&name_loc->nameval[args->namelen], args->value, be16_to_cpu(name_loc->valuelen)); } else { name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); name_rmt->namelen = args->namelen; memcpy((char *)name_rmt->name, args->name, args->namelen); entry->flags |= XFS_ATTR_INCOMPLETE; /* just in case */ name_rmt->valuelen = 0; name_rmt->valueblk = 0; args->rmtblkno = 1; args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen); args->rmtvaluelen = args->valuelen; } xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index), xfs_attr_leaf_entsize(leaf, args->index))); /* * Update the control info for this leaf node */ if (be16_to_cpu(entry->nameidx) < ichdr->firstused) ichdr->firstused = be16_to_cpu(entry->nameidx); ASSERT(ichdr->firstused >= ichdr->count * sizeof(xfs_attr_leaf_entry_t) + xfs_attr3_leaf_hdr_size(leaf)); tmp = (ichdr->count - 1) * sizeof(xfs_attr_leaf_entry_t) + xfs_attr3_leaf_hdr_size(leaf); for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { if (ichdr->freemap[i].base == tmp) { ichdr->freemap[i].base += sizeof(xfs_attr_leaf_entry_t); ichdr->freemap[i].size -= sizeof(xfs_attr_leaf_entry_t); } } ichdr->usedbytes += xfs_attr_leaf_entsize(leaf, args->index); return 0; } /* * Garbage collect a leaf attribute list block by copying it to a new buffer. */ STATIC void xfs_attr3_leaf_compact( struct xfs_da_args *args, struct xfs_attr3_icleaf_hdr *ichdr_dst, struct xfs_buf *bp) { struct xfs_attr_leafblock *leaf_src; struct xfs_attr_leafblock *leaf_dst; struct xfs_attr3_icleaf_hdr ichdr_src; struct xfs_trans *trans = args->trans; char *tmpbuffer; trace_xfs_attr_leaf_compact(args); tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP); memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); memset(bp->b_addr, 0, args->geo->blksize); leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; leaf_dst = bp->b_addr; /* * Copy the on-disk header back into the destination buffer to ensure * all the information in the header that is not part of the incore * header structure is preserved. */ memcpy(bp->b_addr, tmpbuffer, xfs_attr3_leaf_hdr_size(leaf_src)); /* Initialise the incore headers */ ichdr_src = *ichdr_dst; /* struct copy */ ichdr_dst->firstused = args->geo->blksize; ichdr_dst->usedbytes = 0; ichdr_dst->count = 0; ichdr_dst->holes = 0; ichdr_dst->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_src); ichdr_dst->freemap[0].size = ichdr_dst->firstused - ichdr_dst->freemap[0].base; /* write the header back to initialise the underlying buffer */ xfs_attr3_leaf_hdr_to_disk(args->geo, leaf_dst, ichdr_dst); /* * Copy all entry's in the same (sorted) order, * but allocate name/value pairs packed and in sequence. */ xfs_attr3_leaf_moveents(args, leaf_src, &ichdr_src, 0, leaf_dst, ichdr_dst, 0, ichdr_src.count); /* * this logs the entire buffer, but the caller must write the header * back to the buffer when it is finished modifying it. */ xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1); kmem_free(tmpbuffer); } /* * Compare two leaf blocks "order". * Return 0 unless leaf2 should go before leaf1. */ static int xfs_attr3_leaf_order( struct xfs_buf *leaf1_bp, struct xfs_attr3_icleaf_hdr *leaf1hdr, struct xfs_buf *leaf2_bp, struct xfs_attr3_icleaf_hdr *leaf2hdr) { struct xfs_attr_leaf_entry *entries1; struct xfs_attr_leaf_entry *entries2; entries1 = xfs_attr3_leaf_entryp(leaf1_bp->b_addr); entries2 = xfs_attr3_leaf_entryp(leaf2_bp->b_addr); if (leaf1hdr->count > 0 && leaf2hdr->count > 0 && ((be32_to_cpu(entries2[0].hashval) < be32_to_cpu(entries1[0].hashval)) || (be32_to_cpu(entries2[leaf2hdr->count - 1].hashval) < be32_to_cpu(entries1[leaf1hdr->count - 1].hashval)))) { return 1; } return 0; } int xfs_attr_leaf_order( struct xfs_buf *leaf1_bp, struct xfs_buf *leaf2_bp) { struct xfs_attr3_icleaf_hdr ichdr1; struct xfs_attr3_icleaf_hdr ichdr2; struct xfs_mount *mp = leaf1_bp->b_target->bt_mount; xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr1, leaf1_bp->b_addr); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr2, leaf2_bp->b_addr); return xfs_attr3_leaf_order(leaf1_bp, &ichdr1, leaf2_bp, &ichdr2); } /* * Redistribute the attribute list entries between two leaf nodes, * taking into account the size of the new entry. * * NOTE: if new block is empty, then it will get the upper half of the * old block. At present, all (one) callers pass in an empty second block. * * This code adjusts the args->index/blkno and args->index2/blkno2 fields * to match what it is doing in splitting the attribute leaf block. Those * values are used in "atomic rename" operations on attributes. Note that * the "new" and "old" values can end up in different blocks. */ STATIC void xfs_attr3_leaf_rebalance( struct xfs_da_state *state, struct xfs_da_state_blk *blk1, struct xfs_da_state_blk *blk2) { struct xfs_da_args *args; struct xfs_attr_leafblock *leaf1; struct xfs_attr_leafblock *leaf2; struct xfs_attr3_icleaf_hdr ichdr1; struct xfs_attr3_icleaf_hdr ichdr2; struct xfs_attr_leaf_entry *entries1; struct xfs_attr_leaf_entry *entries2; int count; int totallen; int max; int space; int swap; /* * Set up environment. */ ASSERT(blk1->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC); leaf1 = blk1->bp->b_addr; leaf2 = blk2->bp->b_addr; xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr1, leaf1); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, leaf2); ASSERT(ichdr2.count == 0); args = state->args; trace_xfs_attr_leaf_rebalance(args); /* * Check ordering of blocks, reverse if it makes things simpler. * * NOTE: Given that all (current) callers pass in an empty * second block, this code should never set "swap". */ swap = 0; if (xfs_attr3_leaf_order(blk1->bp, &ichdr1, blk2->bp, &ichdr2)) { struct xfs_da_state_blk *tmp_blk; struct xfs_attr3_icleaf_hdr tmp_ichdr; tmp_blk = blk1; blk1 = blk2; blk2 = tmp_blk; /* struct copies to swap them rather than reconverting */ tmp_ichdr = ichdr1; ichdr1 = ichdr2; ichdr2 = tmp_ichdr; leaf1 = blk1->bp->b_addr; leaf2 = blk2->bp->b_addr; swap = 1; } /* * Examine entries until we reduce the absolute difference in * byte usage between the two blocks to a minimum. Then get * the direction to copy and the number of elements to move. * * "inleaf" is true if the new entry should be inserted into blk1. * If "swap" is also true, then reverse the sense of "inleaf". */ state->inleaf = xfs_attr3_leaf_figure_balance(state, blk1, &ichdr1, blk2, &ichdr2, &count, &totallen); if (swap) state->inleaf = !state->inleaf; /* * Move any entries required from leaf to leaf: */ if (count < ichdr1.count) { /* * Figure the total bytes to be added to the destination leaf. */ /* number entries being moved */ count = ichdr1.count - count; space = ichdr1.usedbytes - totallen; space += count * sizeof(xfs_attr_leaf_entry_t); /* * leaf2 is the destination, compact it if it looks tight. */ max = ichdr2.firstused - xfs_attr3_leaf_hdr_size(leaf1); max -= ichdr2.count * sizeof(xfs_attr_leaf_entry_t); if (space > max) xfs_attr3_leaf_compact(args, &ichdr2, blk2->bp); /* * Move high entries from leaf1 to low end of leaf2. */ xfs_attr3_leaf_moveents(args, leaf1, &ichdr1, ichdr1.count - count, leaf2, &ichdr2, 0, count); } else if (count > ichdr1.count) { /* * I assert that since all callers pass in an empty * second buffer, this code should never execute. */ ASSERT(0); /* * Figure the total bytes to be added to the destination leaf. */ /* number entries being moved */ count -= ichdr1.count; space = totallen - ichdr1.usedbytes; space += count * sizeof(xfs_attr_leaf_entry_t); /* * leaf1 is the destination, compact it if it looks tight. */ max = ichdr1.firstused - xfs_attr3_leaf_hdr_size(leaf1); max -= ichdr1.count * sizeof(xfs_attr_leaf_entry_t); if (space > max) xfs_attr3_leaf_compact(args, &ichdr1, blk1->bp); /* * Move low entries from leaf2 to high end of leaf1. */ xfs_attr3_leaf_moveents(args, leaf2, &ichdr2, 0, leaf1, &ichdr1, ichdr1.count, count); } xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf1, &ichdr1); xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf2, &ichdr2); xfs_trans_log_buf(args->trans, blk1->bp, 0, args->geo->blksize - 1); xfs_trans_log_buf(args->trans, blk2->bp, 0, args->geo->blksize - 1); /* * Copy out last hashval in each block for B-tree code. */ entries1 = xfs_attr3_leaf_entryp(leaf1); entries2 = xfs_attr3_leaf_entryp(leaf2); blk1->hashval = be32_to_cpu(entries1[ichdr1.count - 1].hashval); blk2->hashval = be32_to_cpu(entries2[ichdr2.count - 1].hashval); /* * Adjust the expected index for insertion. * NOTE: this code depends on the (current) situation that the * second block was originally empty. * * If the insertion point moved to the 2nd block, we must adjust * the index. We must also track the entry just following the * new entry for use in an "atomic rename" operation, that entry * is always the "old" entry and the "new" entry is what we are * inserting. The index/blkno fields refer to the "old" entry, * while the index2/blkno2 fields refer to the "new" entry. */ if (blk1->index > ichdr1.count) { ASSERT(state->inleaf == 0); blk2->index = blk1->index - ichdr1.count; args->index = args->index2 = blk2->index; args->blkno = args->blkno2 = blk2->blkno; } else if (blk1->index == ichdr1.count) { if (state->inleaf) { args->index = blk1->index; args->blkno = blk1->blkno; args->index2 = 0; args->blkno2 = blk2->blkno; } else { /* * On a double leaf split, the original attr location * is already stored in blkno2/index2, so don't * overwrite it overwise we corrupt the tree. */ blk2->index = blk1->index - ichdr1.count; args->index = blk2->index; args->blkno = blk2->blkno; if (!state->extravalid) { /* * set the new attr location to match the old * one and let the higher level split code * decide where in the leaf to place it. */ args->index2 = blk2->index; args->blkno2 = blk2->blkno; } } } else { ASSERT(state->inleaf == 1); args->index = args->index2 = blk1->index; args->blkno = args->blkno2 = blk1->blkno; } } /* * Examine entries until we reduce the absolute difference in * byte usage between the two blocks to a minimum. * GROT: Is this really necessary? With other than a 512 byte blocksize, * GROT: there will always be enough room in either block for a new entry. * GROT: Do a double-split for this case? */ STATIC int xfs_attr3_leaf_figure_balance( struct xfs_da_state *state, struct xfs_da_state_blk *blk1, struct xfs_attr3_icleaf_hdr *ichdr1, struct xfs_da_state_blk *blk2, struct xfs_attr3_icleaf_hdr *ichdr2, int *countarg, int *usedbytesarg) { struct xfs_attr_leafblock *leaf1 = blk1->bp->b_addr; struct xfs_attr_leafblock *leaf2 = blk2->bp->b_addr; struct xfs_attr_leaf_entry *entry; int count; int max; int index; int totallen = 0; int half; int lastdelta; int foundit = 0; int tmp; /* * Examine entries until we reduce the absolute difference in * byte usage between the two blocks to a minimum. */ max = ichdr1->count + ichdr2->count; half = (max + 1) * sizeof(*entry); half += ichdr1->usedbytes + ichdr2->usedbytes + xfs_attr_leaf_newentsize(state->args, NULL); half /= 2; lastdelta = state->args->geo->blksize; entry = xfs_attr3_leaf_entryp(leaf1); for (count = index = 0; count < max; entry++, index++, count++) { #define XFS_ATTR_ABS(A) (((A) < 0) ? -(A) : (A)) /* * The new entry is in the first block, account for it. */ if (count == blk1->index) { tmp = totallen + sizeof(*entry) + xfs_attr_leaf_newentsize(state->args, NULL); if (XFS_ATTR_ABS(half - tmp) > lastdelta) break; lastdelta = XFS_ATTR_ABS(half - tmp); totallen = tmp; foundit = 1; } /* * Wrap around into the second block if necessary. */ if (count == ichdr1->count) { leaf1 = leaf2; entry = xfs_attr3_leaf_entryp(leaf1); index = 0; } /* * Figure out if next leaf entry would be too much. */ tmp = totallen + sizeof(*entry) + xfs_attr_leaf_entsize(leaf1, index); if (XFS_ATTR_ABS(half - tmp) > lastdelta) break; lastdelta = XFS_ATTR_ABS(half - tmp); totallen = tmp; #undef XFS_ATTR_ABS } /* * Calculate the number of usedbytes that will end up in lower block. * If new entry not in lower block, fix up the count. */ totallen -= count * sizeof(*entry); if (foundit) { totallen -= sizeof(*entry) + xfs_attr_leaf_newentsize(state->args, NULL); } *countarg = count; *usedbytesarg = totallen; return foundit; } /*======================================================================== * Routines used for shrinking the Btree. *========================================================================*/ /* * Check a leaf block and its neighbors to see if the block should be * collapsed into one or the other neighbor. Always keep the block * with the smaller block number. * If the current block is over 50% full, don't try to join it, return 0. * If the block is empty, fill in the state structure and return 2. * If it can be collapsed, fill in the state structure and return 1. * If nothing can be done, return 0. * * GROT: allow for INCOMPLETE entries in calculation. */ int xfs_attr3_leaf_toosmall( struct xfs_da_state *state, int *action) { struct xfs_attr_leafblock *leaf; struct xfs_da_state_blk *blk; struct xfs_attr3_icleaf_hdr ichdr; struct xfs_buf *bp; xfs_dablk_t blkno; int bytes; int forward; int error; int retval; int i; trace_xfs_attr_leaf_toosmall(state->args); /* * Check for the degenerate case of the block being over 50% full. * If so, it's not worth even looking to see if we might be able * to coalesce with a sibling. */ blk = &state->path.blk[ state->path.active-1 ]; leaf = blk->bp->b_addr; xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr, leaf); bytes = xfs_attr3_leaf_hdr_size(leaf) + ichdr.count * sizeof(xfs_attr_leaf_entry_t) + ichdr.usedbytes; if (bytes > (state->args->geo->blksize >> 1)) { *action = 0; /* blk over 50%, don't try to join */ return 0; } /* * Check for the degenerate case of the block being empty. * If the block is empty, we'll simply delete it, no need to * coalesce it with a sibling block. We choose (arbitrarily) * to merge with the forward block unless it is NULL. */ if (ichdr.count == 0) { /* * Make altpath point to the block we want to keep and * path point to the block we want to drop (this one). */ forward = (ichdr.forw != 0); memcpy(&state->altpath, &state->path, sizeof(state->path)); error = xfs_da3_path_shift(state, &state->altpath, forward, 0, &retval); if (error) return error; if (retval) { *action = 0; } else { *action = 2; } return 0; } /* * Examine each sibling block to see if we can coalesce with * at least 25% free space to spare. We need to figure out * whether to merge with the forward or the backward block. * We prefer coalescing with the lower numbered sibling so as * to shrink an attribute list over time. */ /* start with smaller blk num */ forward = ichdr.forw < ichdr.back; for (i = 0; i < 2; forward = !forward, i++) { struct xfs_attr3_icleaf_hdr ichdr2; if (forward) blkno = ichdr.forw; else blkno = ichdr.back; if (blkno == 0) continue; error = xfs_attr3_leaf_read(state->args->trans, state->args->dp, blkno, -1, &bp); if (error) return error; xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, bp->b_addr); bytes = state->args->geo->blksize - (state->args->geo->blksize >> 2) - ichdr.usedbytes - ichdr2.usedbytes - ((ichdr.count + ichdr2.count) * sizeof(xfs_attr_leaf_entry_t)) - xfs_attr3_leaf_hdr_size(leaf); xfs_trans_brelse(state->args->trans, bp); if (bytes >= 0) break; /* fits with at least 25% to spare */ } if (i >= 2) { *action = 0; return 0; } /* * Make altpath point to the block we want to keep (the lower * numbered block) and path point to the block we want to drop. */ memcpy(&state->altpath, &state->path, sizeof(state->path)); if (blkno < blk->blkno) { error = xfs_da3_path_shift(state, &state->altpath, forward, 0, &retval); } else { error = xfs_da3_path_shift(state, &state->path, forward, 0, &retval); } if (error) return error; if (retval) { *action = 0; } else { *action = 1; } return 0; } /* * Remove a name from the leaf attribute list structure. * * Return 1 if leaf is less than 37% full, 0 if >= 37% full. * If two leaves are 37% full, when combined they will leave 25% free. */ int xfs_attr3_leaf_remove( struct xfs_buf *bp, struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr ichdr; struct xfs_attr_leaf_entry *entry; int before; int after; int smallest; int entsize; int tablesize; int tmp; int i; trace_xfs_attr_leaf_remove(args); leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); ASSERT(ichdr.count > 0 && ichdr.count < args->geo->blksize / 8); ASSERT(args->index >= 0 && args->index < ichdr.count); ASSERT(ichdr.firstused >= ichdr.count * sizeof(*entry) + xfs_attr3_leaf_hdr_size(leaf)); entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize); /* * Scan through free region table: * check for adjacency of free'd entry with an existing one, * find smallest free region in case we need to replace it, * adjust any map that borders the entry table, */ tablesize = ichdr.count * sizeof(xfs_attr_leaf_entry_t) + xfs_attr3_leaf_hdr_size(leaf); tmp = ichdr.freemap[0].size; before = after = -1; smallest = XFS_ATTR_LEAF_MAPSIZE - 1; entsize = xfs_attr_leaf_entsize(leaf, args->index); for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { ASSERT(ichdr.freemap[i].base < args->geo->blksize); ASSERT(ichdr.freemap[i].size < args->geo->blksize); if (ichdr.freemap[i].base == tablesize) { ichdr.freemap[i].base -= sizeof(xfs_attr_leaf_entry_t); ichdr.freemap[i].size += sizeof(xfs_attr_leaf_entry_t); } if (ichdr.freemap[i].base + ichdr.freemap[i].size == be16_to_cpu(entry->nameidx)) { before = i; } else if (ichdr.freemap[i].base == (be16_to_cpu(entry->nameidx) + entsize)) { after = i; } else if (ichdr.freemap[i].size < tmp) { tmp = ichdr.freemap[i].size; smallest = i; } } /* * Coalesce adjacent freemap regions, * or replace the smallest region. */ if ((before >= 0) || (after >= 0)) { if ((before >= 0) && (after >= 0)) { ichdr.freemap[before].size += entsize; ichdr.freemap[before].size += ichdr.freemap[after].size; ichdr.freemap[after].base = 0; ichdr.freemap[after].size = 0; } else if (before >= 0) { ichdr.freemap[before].size += entsize; } else { ichdr.freemap[after].base = be16_to_cpu(entry->nameidx); ichdr.freemap[after].size += entsize; } } else { /* * Replace smallest region (if it is smaller than free'd entry) */ if (ichdr.freemap[smallest].size < entsize) { ichdr.freemap[smallest].base = be16_to_cpu(entry->nameidx); ichdr.freemap[smallest].size = entsize; } } /* * Did we remove the first entry? */ if (be16_to_cpu(entry->nameidx) == ichdr.firstused) smallest = 1; else smallest = 0; /* * Compress the remaining entries and zero out the removed stuff. */ memset(xfs_attr3_leaf_name(leaf, args->index), 0, entsize); ichdr.usedbytes -= entsize; xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index), entsize)); tmp = (ichdr.count - args->index) * sizeof(xfs_attr_leaf_entry_t); memmove(entry, entry + 1, tmp); ichdr.count--; xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(xfs_attr_leaf_entry_t))); entry = &xfs_attr3_leaf_entryp(leaf)[ichdr.count]; memset(entry, 0, sizeof(xfs_attr_leaf_entry_t)); /* * If we removed the first entry, re-find the first used byte * in the name area. Note that if the entry was the "firstused", * then we don't have a "hole" in our block resulting from * removing the name. */ if (smallest) { tmp = args->geo->blksize; entry = xfs_attr3_leaf_entryp(leaf); for (i = ichdr.count - 1; i >= 0; entry++, i--) { ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize); if (be16_to_cpu(entry->nameidx) < tmp) tmp = be16_to_cpu(entry->nameidx); } ichdr.firstused = tmp; ASSERT(ichdr.firstused != 0); } else { ichdr.holes = 1; /* mark as needing compaction */ } xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr); xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, &leaf->hdr, xfs_attr3_leaf_hdr_size(leaf))); /* * Check if leaf is less than 50% full, caller may want to * "join" the leaf with a sibling if so. */ tmp = ichdr.usedbytes + xfs_attr3_leaf_hdr_size(leaf) + ichdr.count * sizeof(xfs_attr_leaf_entry_t); return tmp < args->geo->magicpct; /* leaf is < 37% full */ } /* * Move all the attribute list entries from drop_leaf into save_leaf. */ void xfs_attr3_leaf_unbalance( struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, struct xfs_da_state_blk *save_blk) { struct xfs_attr_leafblock *drop_leaf = drop_blk->bp->b_addr; struct xfs_attr_leafblock *save_leaf = save_blk->bp->b_addr; struct xfs_attr3_icleaf_hdr drophdr; struct xfs_attr3_icleaf_hdr savehdr; struct xfs_attr_leaf_entry *entry; trace_xfs_attr_leaf_unbalance(state->args); drop_leaf = drop_blk->bp->b_addr; save_leaf = save_blk->bp->b_addr; xfs_attr3_leaf_hdr_from_disk(state->args->geo, &drophdr, drop_leaf); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &savehdr, save_leaf); entry = xfs_attr3_leaf_entryp(drop_leaf); /* * Save last hashval from dying block for later Btree fixup. */ drop_blk->hashval = be32_to_cpu(entry[drophdr.count - 1].hashval); /* * Check if we need a temp buffer, or can we do it in place. * Note that we don't check "leaf" for holes because we will * always be dropping it, toosmall() decided that for us already. */ if (savehdr.holes == 0) { /* * dest leaf has no holes, so we add there. May need * to make some room in the entry array. */ if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, drop_blk->bp, &drophdr)) { xfs_attr3_leaf_moveents(state->args, drop_leaf, &drophdr, 0, save_leaf, &savehdr, 0, drophdr.count); } else { xfs_attr3_leaf_moveents(state->args, drop_leaf, &drophdr, 0, save_leaf, &savehdr, savehdr.count, drophdr.count); } } else { /* * Destination has holes, so we make a temporary copy * of the leaf and add them both to that. */ struct xfs_attr_leafblock *tmp_leaf; struct xfs_attr3_icleaf_hdr tmphdr; tmp_leaf = kmem_zalloc(state->args->geo->blksize, KM_SLEEP); /* * Copy the header into the temp leaf so that all the stuff * not in the incore header is present and gets copied back in * once we've moved all the entries. */ memcpy(tmp_leaf, save_leaf, xfs_attr3_leaf_hdr_size(save_leaf)); memset(&tmphdr, 0, sizeof(tmphdr)); tmphdr.magic = savehdr.magic; tmphdr.forw = savehdr.forw; tmphdr.back = savehdr.back; tmphdr.firstused = state->args->geo->blksize; /* write the header to the temp buffer to initialise it */ xfs_attr3_leaf_hdr_to_disk(state->args->geo, tmp_leaf, &tmphdr); if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, drop_blk->bp, &drophdr)) { xfs_attr3_leaf_moveents(state->args, drop_leaf, &drophdr, 0, tmp_leaf, &tmphdr, 0, drophdr.count); xfs_attr3_leaf_moveents(state->args, save_leaf, &savehdr, 0, tmp_leaf, &tmphdr, tmphdr.count, savehdr.count); } else { xfs_attr3_leaf_moveents(state->args, save_leaf, &savehdr, 0, tmp_leaf, &tmphdr, 0, savehdr.count); xfs_attr3_leaf_moveents(state->args, drop_leaf, &drophdr, 0, tmp_leaf, &tmphdr, tmphdr.count, drophdr.count); } memcpy(save_leaf, tmp_leaf, state->args->geo->blksize); savehdr = tmphdr; /* struct copy */ kmem_free(tmp_leaf); } xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr); xfs_trans_log_buf(state->args->trans, save_blk->bp, 0, state->args->geo->blksize - 1); /* * Copy out last hashval in each block for B-tree code. */ entry = xfs_attr3_leaf_entryp(save_leaf); save_blk->hashval = be32_to_cpu(entry[savehdr.count - 1].hashval); } /*======================================================================== * Routines used for finding things in the Btree. *========================================================================*/ /* * Look up a name in a leaf attribute list structure. * This is the internal routine, it uses the caller's buffer. * * Note that duplicate keys are allowed, but only check within the * current leaf node. The Btree code must check in adjacent leaf nodes. * * Return in args->index the index into the entry[] array of either * the found entry, or where the entry should have been (insert before * that entry). * * Don't change the args->value unless we find the attribute. */ int xfs_attr3_leaf_lookup_int( struct xfs_buf *bp, struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr ichdr; struct xfs_attr_leaf_entry *entry; struct xfs_attr_leaf_entry *entries; struct xfs_attr_leaf_name_local *name_loc; struct xfs_attr_leaf_name_remote *name_rmt; xfs_dahash_t hashval; int probe; int span; trace_xfs_attr_leaf_lookup(args); leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); entries = xfs_attr3_leaf_entryp(leaf); ASSERT(ichdr.count < args->geo->blksize / 8); /* * Binary search. (note: small blocks will skip this loop) */ hashval = args->hashval; probe = span = ichdr.count / 2; for (entry = &entries[probe]; span > 4; entry = &entries[probe]) { span /= 2; if (be32_to_cpu(entry->hashval) < hashval) probe += span; else if (be32_to_cpu(entry->hashval) > hashval) probe -= span; else break; } ASSERT(probe >= 0 && (!ichdr.count || probe < ichdr.count)); ASSERT(span <= 4 || be32_to_cpu(entry->hashval) == hashval); /* * Since we may have duplicate hashval's, find the first matching * hashval in the leaf. */ while (probe > 0 && be32_to_cpu(entry->hashval) >= hashval) { entry--; probe--; } while (probe < ichdr.count && be32_to_cpu(entry->hashval) < hashval) { entry++; probe++; } if (probe == ichdr.count || be32_to_cpu(entry->hashval) != hashval) { args->index = probe; return -ENOATTR; } /* * Duplicate keys may be present, so search all of them for a match. */ for (; probe < ichdr.count && (be32_to_cpu(entry->hashval) == hashval); entry++, probe++) { /* * GROT: Add code to remove incomplete entries. */ /* * If we are looking for INCOMPLETE entries, show only those. * If we are looking for complete entries, show only those. */ if ((args->flags & XFS_ATTR_INCOMPLETE) != (entry->flags & XFS_ATTR_INCOMPLETE)) { continue; } if (entry->flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf, probe); if (name_loc->namelen != args->namelen) continue; if (memcmp(args->name, name_loc->nameval, args->namelen) != 0) continue; if (!xfs_attr_namesp_match(args->flags, entry->flags)) continue; args->index = probe; return -EEXIST; } else { name_rmt = xfs_attr3_leaf_name_remote(leaf, probe); if (name_rmt->namelen != args->namelen) continue; if (memcmp(args->name, name_rmt->name, args->namelen) != 0) continue; if (!xfs_attr_namesp_match(args->flags, entry->flags)) continue; args->index = probe; args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = xfs_attr3_rmt_blocks( args->dp->i_mount, args->rmtvaluelen); return -EEXIST; } } args->index = probe; return -ENOATTR; } /* * Get the value associated with an attribute name from a leaf attribute * list structure. */ int xfs_attr3_leaf_getvalue( struct xfs_buf *bp, struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr ichdr; struct xfs_attr_leaf_entry *entry; struct xfs_attr_leaf_name_local *name_loc; struct xfs_attr_leaf_name_remote *name_rmt; int valuelen; leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); ASSERT(ichdr.count < args->geo->blksize / 8); ASSERT(args->index < ichdr.count); entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; if (entry->flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf, args->index); ASSERT(name_loc->namelen == args->namelen); ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0); valuelen = be16_to_cpu(name_loc->valuelen); if (args->flags & ATTR_KERNOVAL) { args->valuelen = valuelen; return 0; } if (args->valuelen < valuelen) { args->valuelen = valuelen; return -ERANGE; } args->valuelen = valuelen; memcpy(args->value, &name_loc->nameval[args->namelen], valuelen); } else { name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); ASSERT(name_rmt->namelen == args->namelen); ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount, args->rmtvaluelen); if (args->flags & ATTR_KERNOVAL) { args->valuelen = args->rmtvaluelen; return 0; } if (args->valuelen < args->rmtvaluelen) { args->valuelen = args->rmtvaluelen; return -ERANGE; } args->valuelen = args->rmtvaluelen; } return 0; } /*======================================================================== * Utility routines. *========================================================================*/ /* * Move the indicated entries from one leaf to another. * NOTE: this routine modifies both source and destination leaves. */ /*ARGSUSED*/ STATIC void xfs_attr3_leaf_moveents( struct xfs_da_args *args, struct xfs_attr_leafblock *leaf_s, struct xfs_attr3_icleaf_hdr *ichdr_s, int start_s, struct xfs_attr_leafblock *leaf_d, struct xfs_attr3_icleaf_hdr *ichdr_d, int start_d, int count) { struct xfs_attr_leaf_entry *entry_s; struct xfs_attr_leaf_entry *entry_d; int desti; int tmp; int i; /* * Check for nothing to do. */ if (count == 0) return; /* * Set up environment. */ ASSERT(ichdr_s->magic == XFS_ATTR_LEAF_MAGIC || ichdr_s->magic == XFS_ATTR3_LEAF_MAGIC); ASSERT(ichdr_s->magic == ichdr_d->magic); ASSERT(ichdr_s->count > 0 && ichdr_s->count < args->geo->blksize / 8); ASSERT(ichdr_s->firstused >= (ichdr_s->count * sizeof(*entry_s)) + xfs_attr3_leaf_hdr_size(leaf_s)); ASSERT(ichdr_d->count < args->geo->blksize / 8); ASSERT(ichdr_d->firstused >= (ichdr_d->count * sizeof(*entry_d)) + xfs_attr3_leaf_hdr_size(leaf_d)); ASSERT(start_s < ichdr_s->count); ASSERT(start_d <= ichdr_d->count); ASSERT(count <= ichdr_s->count); /* * Move the entries in the destination leaf up to make a hole? */ if (start_d < ichdr_d->count) { tmp = ichdr_d->count - start_d; tmp *= sizeof(xfs_attr_leaf_entry_t); entry_s = &xfs_attr3_leaf_entryp(leaf_d)[start_d]; entry_d = &xfs_attr3_leaf_entryp(leaf_d)[start_d + count]; memmove(entry_d, entry_s, tmp); } /* * Copy all entry's in the same (sorted) order, * but allocate attribute info packed and in sequence. */ entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; entry_d = &xfs_attr3_leaf_entryp(leaf_d)[start_d]; desti = start_d; for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) { ASSERT(be16_to_cpu(entry_s->nameidx) >= ichdr_s->firstused); tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i); #ifdef GROT /* * Code to drop INCOMPLETE entries. Difficult to use as we * may also need to change the insertion index. Code turned * off for 6.2, should be revisited later. */ if (entry_s->flags & XFS_ATTR_INCOMPLETE) { /* skip partials? */ memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp); ichdr_s->usedbytes -= tmp; ichdr_s->count -= 1; entry_d--; /* to compensate for ++ in loop hdr */ desti--; if ((start_s + i) < offset) result++; /* insertion index adjustment */ } else { #endif /* GROT */ ichdr_d->firstused -= tmp; /* both on-disk, don't endian flip twice */ entry_d->hashval = entry_s->hashval; entry_d->nameidx = cpu_to_be16(ichdr_d->firstused); entry_d->flags = entry_s->flags; ASSERT(be16_to_cpu(entry_d->nameidx) + tmp <= args->geo->blksize); memmove(xfs_attr3_leaf_name(leaf_d, desti), xfs_attr3_leaf_name(leaf_s, start_s + i), tmp); ASSERT(be16_to_cpu(entry_s->nameidx) + tmp <= args->geo->blksize); memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp); ichdr_s->usedbytes -= tmp; ichdr_d->usedbytes += tmp; ichdr_s->count -= 1; ichdr_d->count += 1; tmp = ichdr_d->count * sizeof(xfs_attr_leaf_entry_t) + xfs_attr3_leaf_hdr_size(leaf_d); ASSERT(ichdr_d->firstused >= tmp); #ifdef GROT } #endif /* GROT */ } /* * Zero out the entries we just copied. */ if (start_s == ichdr_s->count) { tmp = count * sizeof(xfs_attr_leaf_entry_t); entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; ASSERT(((char *)entry_s + tmp) <= ((char *)leaf_s + args->geo->blksize)); memset(entry_s, 0, tmp); } else { /* * Move the remaining entries down to fill the hole, * then zero the entries at the top. */ tmp = (ichdr_s->count - count) * sizeof(xfs_attr_leaf_entry_t); entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s + count]; entry_d = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; memmove(entry_d, entry_s, tmp); tmp = count * sizeof(xfs_attr_leaf_entry_t); entry_s = &xfs_attr3_leaf_entryp(leaf_s)[ichdr_s->count]; ASSERT(((char *)entry_s + tmp) <= ((char *)leaf_s + args->geo->blksize)); memset(entry_s, 0, tmp); } /* * Fill in the freemap information */ ichdr_d->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_d); ichdr_d->freemap[0].base += ichdr_d->count * sizeof(xfs_attr_leaf_entry_t); ichdr_d->freemap[0].size = ichdr_d->firstused - ichdr_d->freemap[0].base; ichdr_d->freemap[1].base = 0; ichdr_d->freemap[2].base = 0; ichdr_d->freemap[1].size = 0; ichdr_d->freemap[2].size = 0; ichdr_s->holes = 1; /* leaf may not be compact */ } /* * Pick up the last hashvalue from a leaf block. */ xfs_dahash_t xfs_attr_leaf_lasthash( struct xfs_buf *bp, int *count) { struct xfs_attr3_icleaf_hdr ichdr; struct xfs_attr_leaf_entry *entries; struct xfs_mount *mp = bp->b_target->bt_mount; xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, bp->b_addr); entries = xfs_attr3_leaf_entryp(bp->b_addr); if (count) *count = ichdr.count; if (!ichdr.count) return 0; return be32_to_cpu(entries[ichdr.count - 1].hashval); } /* * Calculate the number of bytes used to store the indicated attribute * (whether local or remote only calculate bytes in this block). */ STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) { struct xfs_attr_leaf_entry *entries; xfs_attr_leaf_name_local_t *name_loc; xfs_attr_leaf_name_remote_t *name_rmt; int size; entries = xfs_attr3_leaf_entryp(leaf); if (entries[index].flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf, index); size = xfs_attr_leaf_entsize_local(name_loc->namelen, be16_to_cpu(name_loc->valuelen)); } else { name_rmt = xfs_attr3_leaf_name_remote(leaf, index); size = xfs_attr_leaf_entsize_remote(name_rmt->namelen); } return size; } /* * Calculate the number of bytes that would be required to store the new * attribute (whether local or remote only calculate bytes in this block). * This routine decides as a side effect whether the attribute will be * a "local" or a "remote" attribute. */ int xfs_attr_leaf_newentsize( struct xfs_da_args *args, int *local) { int size; size = xfs_attr_leaf_entsize_local(args->namelen, args->valuelen); if (size < xfs_attr_leaf_entsize_local_max(args->geo->blksize)) { if (local) *local = 1; return size; } if (local) *local = 0; return xfs_attr_leaf_entsize_remote(args->namelen); } /*======================================================================== * Manage the INCOMPLETE flag in a leaf entry *========================================================================*/ /* * Clear the INCOMPLETE flag on an entry in a leaf block. */ int xfs_attr3_leaf_clearflag( struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf; struct xfs_attr_leaf_entry *entry; struct xfs_attr_leaf_name_remote *name_rmt; struct xfs_buf *bp; int error; #ifdef DEBUG struct xfs_attr3_icleaf_hdr ichdr; xfs_attr_leaf_name_local_t *name_loc; int namelen; char *name; #endif /* DEBUG */ trace_xfs_attr_leaf_clearflag(args); /* * Set up the operation. */ error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); if (error) return error; leaf = bp->b_addr; entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; ASSERT(entry->flags & XFS_ATTR_INCOMPLETE); #ifdef DEBUG xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); ASSERT(args->index < ichdr.count); ASSERT(args->index >= 0); if (entry->flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf, args->index); namelen = name_loc->namelen; name = (char *)name_loc->nameval; } else { name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); namelen = name_rmt->namelen; name = (char *)name_rmt->name; } ASSERT(be32_to_cpu(entry->hashval) == args->hashval); ASSERT(namelen == args->namelen); ASSERT(memcmp(name, args->name, namelen) == 0); #endif /* DEBUG */ entry->flags &= ~XFS_ATTR_INCOMPLETE; xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); if (args->rmtblkno) { ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0); name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); name_rmt->valueblk = cpu_to_be32(args->rmtblkno); name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen); xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); } /* * Commit the flag value change and start the next trans in series. */ return xfs_trans_roll(&args->trans, args->dp); } /* * Set the INCOMPLETE flag on an entry in a leaf block. */ int xfs_attr3_leaf_setflag( struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf; struct xfs_attr_leaf_entry *entry; struct xfs_attr_leaf_name_remote *name_rmt; struct xfs_buf *bp; int error; #ifdef DEBUG struct xfs_attr3_icleaf_hdr ichdr; #endif trace_xfs_attr_leaf_setflag(args); /* * Set up the operation. */ error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); if (error) return error; leaf = bp->b_addr; #ifdef DEBUG xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); ASSERT(args->index < ichdr.count); ASSERT(args->index >= 0); #endif entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0); entry->flags |= XFS_ATTR_INCOMPLETE; xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); if ((entry->flags & XFS_ATTR_LOCAL) == 0) { name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); name_rmt->valueblk = 0; name_rmt->valuelen = 0; xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); } /* * Commit the flag value change and start the next trans in series. */ return xfs_trans_roll(&args->trans, args->dp); } /* * In a single transaction, clear the INCOMPLETE flag on the leaf entry * given by args->blkno/index and set the INCOMPLETE flag on the leaf * entry given by args->blkno2/index2. * * Note that they could be in different blocks, or in the same block. */ int xfs_attr3_leaf_flipflags( struct xfs_da_args *args) { struct xfs_attr_leafblock *leaf1; struct xfs_attr_leafblock *leaf2; struct xfs_attr_leaf_entry *entry1; struct xfs_attr_leaf_entry *entry2; struct xfs_attr_leaf_name_remote *name_rmt; struct xfs_buf *bp1; struct xfs_buf *bp2; int error; #ifdef DEBUG struct xfs_attr3_icleaf_hdr ichdr1; struct xfs_attr3_icleaf_hdr ichdr2; xfs_attr_leaf_name_local_t *name_loc; int namelen1, namelen2; char *name1, *name2; #endif /* DEBUG */ trace_xfs_attr_leaf_flipflags(args); /* * Read the block containing the "old" attr */ error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp1); if (error) return error; /* * Read the block containing the "new" attr, if it is different */ if (args->blkno2 != args->blkno) { error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno2, -1, &bp2); if (error) return error; } else { bp2 = bp1; } leaf1 = bp1->b_addr; entry1 = &xfs_attr3_leaf_entryp(leaf1)[args->index]; leaf2 = bp2->b_addr; entry2 = &xfs_attr3_leaf_entryp(leaf2)[args->index2]; #ifdef DEBUG xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr1, leaf1); ASSERT(args->index < ichdr1.count); ASSERT(args->index >= 0); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr2, leaf2); ASSERT(args->index2 < ichdr2.count); ASSERT(args->index2 >= 0); if (entry1->flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf1, args->index); namelen1 = name_loc->namelen; name1 = (char *)name_loc->nameval; } else { name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index); namelen1 = name_rmt->namelen; name1 = (char *)name_rmt->name; } if (entry2->flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf2, args->index2); namelen2 = name_loc->namelen; name2 = (char *)name_loc->nameval; } else { name_rmt = xfs_attr3_leaf_name_remote(leaf2, args->index2); namelen2 = name_rmt->namelen; name2 = (char *)name_rmt->name; } ASSERT(be32_to_cpu(entry1->hashval) == be32_to_cpu(entry2->hashval)); ASSERT(namelen1 == namelen2); ASSERT(memcmp(name1, name2, namelen1) == 0); #endif /* DEBUG */ ASSERT(entry1->flags & XFS_ATTR_INCOMPLETE); ASSERT((entry2->flags & XFS_ATTR_INCOMPLETE) == 0); entry1->flags &= ~XFS_ATTR_INCOMPLETE; xfs_trans_log_buf(args->trans, bp1, XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1))); if (args->rmtblkno) { ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0); name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index); name_rmt->valueblk = cpu_to_be32(args->rmtblkno); name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen); xfs_trans_log_buf(args->trans, bp1, XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt))); } entry2->flags |= XFS_ATTR_INCOMPLETE; xfs_trans_log_buf(args->trans, bp2, XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2))); if ((entry2->flags & XFS_ATTR_LOCAL) == 0) { name_rmt = xfs_attr3_leaf_name_remote(leaf2, args->index2); name_rmt->valueblk = 0; name_rmt->valuelen = 0; xfs_trans_log_buf(args->trans, bp2, XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt))); } /* * Commit the flag value change and start the next trans in series. */ error = xfs_trans_roll(&args->trans, args->dp); return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_attr_leaf.h0000644000000000000000000000775313063067171016767 0ustar /* * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_ATTR_LEAF_H__ #define __XFS_ATTR_LEAF_H__ struct attrlist; struct attrlist_cursor_kern; struct xfs_attr_list_context; struct xfs_da_args; struct xfs_da_state; struct xfs_da_state_blk; struct xfs_inode; struct xfs_trans; /* * Used to keep a list of "remote value" extents when unlinking an inode. */ typedef struct xfs_attr_inactive_list { xfs_dablk_t valueblk; /* block number of value bytes */ int valuelen; /* number of bytes in value */ } xfs_attr_inactive_list_t; /*======================================================================== * Function prototypes for the kernel. *========================================================================*/ /* * Internal routines when attribute fork size < XFS_LITINO(mp). */ void xfs_attr_shortform_create(struct xfs_da_args *args); void xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff); int xfs_attr_shortform_lookup(struct xfs_da_args *args); int xfs_attr_shortform_getvalue(struct xfs_da_args *args); int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); int xfs_attr_shortform_remove(struct xfs_da_args *args); int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); int xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes); void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp); /* * Internal routines when attribute fork size == XFS_LBSIZE(mp). */ int xfs_attr3_leaf_to_node(struct xfs_da_args *args); int xfs_attr3_leaf_to_shortform(struct xfs_buf *bp, struct xfs_da_args *args, int forkoff); int xfs_attr3_leaf_clearflag(struct xfs_da_args *args); int xfs_attr3_leaf_setflag(struct xfs_da_args *args); int xfs_attr3_leaf_flipflags(struct xfs_da_args *args); /* * Routines used for growing the Btree. */ int xfs_attr3_leaf_split(struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk); int xfs_attr3_leaf_lookup_int(struct xfs_buf *leaf, struct xfs_da_args *args); int xfs_attr3_leaf_getvalue(struct xfs_buf *bp, struct xfs_da_args *args); int xfs_attr3_leaf_add(struct xfs_buf *leaf_buffer, struct xfs_da_args *args); int xfs_attr3_leaf_remove(struct xfs_buf *leaf_buffer, struct xfs_da_args *args); int xfs_attr3_leaf_list_int(struct xfs_buf *bp, struct xfs_attr_list_context *context); /* * Routines used for shrinking the Btree. */ int xfs_attr3_leaf_toosmall(struct xfs_da_state *state, int *retval); void xfs_attr3_leaf_unbalance(struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, struct xfs_da_state_blk *save_blk); /* * Utility routines. */ xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count); int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp, struct xfs_buf *leaf2_bp); int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local); int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp); void xfs_attr3_leaf_hdr_from_disk(struct xfs_da_geometry *geo, struct xfs_attr3_icleaf_hdr *to, struct xfs_attr_leafblock *from); void xfs_attr3_leaf_hdr_to_disk(struct xfs_da_geometry *geo, struct xfs_attr_leafblock *to, struct xfs_attr3_icleaf_hdr *from); #endif /* __XFS_ATTR_LEAF_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_attr_remote.c0000644000000000000000000003622513063067171017342 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_alloc.h" #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_attr_leaf.h" #include "xfs_attr_remote.h" #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_cksum.h" #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ /* * Each contiguous block has a header, so it is not just a simple attribute * length to FSB conversion. */ int xfs_attr3_rmt_blocks( struct xfs_mount *mp, int attrlen) { if (xfs_sb_version_hascrc(&mp->m_sb)) { int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize); return (attrlen + buflen - 1) / buflen; } return XFS_B_TO_FSB(mp, attrlen); } /* * Checking of the remote attribute header is split into two parts. The verifier * does CRC, location and bounds checking, the unpacking function checks the * attribute parameters and owner. */ static bool xfs_attr3_rmt_hdr_ok( void *ptr, xfs_ino_t ino, uint32_t offset, uint32_t size, xfs_daddr_t bno) { struct xfs_attr3_rmt_hdr *rmt = ptr; if (bno != be64_to_cpu(rmt->rm_blkno)) return false; if (offset != be32_to_cpu(rmt->rm_offset)) return false; if (size != be32_to_cpu(rmt->rm_bytes)) return false; if (ino != be64_to_cpu(rmt->rm_owner)) return false; /* ok */ return true; } static bool xfs_attr3_rmt_verify( struct xfs_mount *mp, void *ptr, int fsbsize, xfs_daddr_t bno) { struct xfs_attr3_rmt_hdr *rmt = ptr; if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (rmt->rm_magic != cpu_to_be32(XFS_ATTR3_RMT_MAGIC)) return false; if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(rmt->rm_blkno) != bno) return false; if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt)) return false; if (be32_to_cpu(rmt->rm_offset) + be32_to_cpu(rmt->rm_bytes) > XFS_XATTR_SIZE_MAX) return false; if (rmt->rm_owner == 0) return false; return true; } static void xfs_attr3_rmt_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; char *ptr; int len; xfs_daddr_t bno; int blksize = mp->m_attr_geo->blksize; /* no verification of non-crc buffers */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return; ptr = bp->b_addr; bno = bp->b_bn; len = BBTOB(bp->b_length); ASSERT(len >= blksize); while (len > 0) { if (!xfs_verify_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF)) { xfs_buf_ioerror(bp, -EFSBADCRC); break; } if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); break; } len -= blksize; ptr += blksize; bno += BTOBB(blksize); } if (bp->b_error) xfs_verifier_error(bp); else ASSERT(len == 0); } static void xfs_attr3_rmt_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; int blksize = mp->m_attr_geo->blksize; char *ptr; int len; xfs_daddr_t bno; /* no verification of non-crc buffers */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return; ptr = bp->b_addr; bno = bp->b_bn; len = BBTOB(bp->b_length); ASSERT(len >= blksize); while (len > 0) { struct xfs_attr3_rmt_hdr *rmt = (struct xfs_attr3_rmt_hdr *)ptr; if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } /* * Ensure we aren't writing bogus LSNs to disk. See * xfs_attr3_rmt_hdr_set() for the explanation. */ if (rmt->rm_lsn != cpu_to_be64(NULLCOMMITLSN)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF); len -= blksize; ptr += blksize; bno += BTOBB(blksize); } ASSERT(len == 0); } const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = { .name = "xfs_attr3_rmt", .verify_read = xfs_attr3_rmt_read_verify, .verify_write = xfs_attr3_rmt_write_verify, }; STATIC int xfs_attr3_rmt_hdr_set( struct xfs_mount *mp, void *ptr, xfs_ino_t ino, uint32_t offset, uint32_t size, xfs_daddr_t bno) { struct xfs_attr3_rmt_hdr *rmt = ptr; if (!xfs_sb_version_hascrc(&mp->m_sb)) return 0; rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC); rmt->rm_offset = cpu_to_be32(offset); rmt->rm_bytes = cpu_to_be32(size); uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid); rmt->rm_owner = cpu_to_be64(ino); rmt->rm_blkno = cpu_to_be64(bno); /* * Remote attribute blocks are written synchronously, so we don't * have an LSN that we can stamp in them that makes any sense to log * recovery. To ensure that log recovery handles overwrites of these * blocks sanely (i.e. once they've been freed and reallocated as some * other type of metadata) we need to ensure that the LSN has a value * that tells log recovery to ignore the LSN and overwrite the buffer * with whatever is in it's log. To do this, we use the magic * NULLCOMMITLSN to indicate that the LSN is invalid. */ rmt->rm_lsn = cpu_to_be64(NULLCOMMITLSN); return sizeof(struct xfs_attr3_rmt_hdr); } /* * Helper functions to copy attribute data in and out of the one disk extents */ STATIC int xfs_attr_rmtval_copyout( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino, int *offset, int *valuelen, __uint8_t **dst) { char *src = bp->b_addr; xfs_daddr_t bno = bp->b_bn; int len = BBTOB(bp->b_length); int blksize = mp->m_attr_geo->blksize; ASSERT(len >= blksize); while (len > 0 && *valuelen > 0) { int hdr_size = 0; int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); byte_cnt = min(*valuelen, byte_cnt); if (xfs_sb_version_hascrc(&mp->m_sb)) { if (!xfs_attr3_rmt_hdr_ok(src, ino, *offset, byte_cnt, bno)) { xfs_alert(mp, "remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)", bno, *offset, byte_cnt, ino); return -EFSCORRUPTED; } hdr_size = sizeof(struct xfs_attr3_rmt_hdr); } memcpy(*dst, src + hdr_size, byte_cnt); /* roll buffer forwards */ len -= blksize; src += blksize; bno += BTOBB(blksize); /* roll attribute data forwards */ *valuelen -= byte_cnt; *dst += byte_cnt; *offset += byte_cnt; } return 0; } STATIC void xfs_attr_rmtval_copyin( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino, int *offset, int *valuelen, __uint8_t **src) { char *dst = bp->b_addr; xfs_daddr_t bno = bp->b_bn; int len = BBTOB(bp->b_length); int blksize = mp->m_attr_geo->blksize; ASSERT(len >= blksize); while (len > 0 && *valuelen > 0) { int hdr_size; int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); byte_cnt = min(*valuelen, byte_cnt); hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset, byte_cnt, bno); memcpy(dst + hdr_size, *src, byte_cnt); /* * If this is the last block, zero the remainder of it. * Check that we are actually the last block, too. */ if (byte_cnt + hdr_size < blksize) { ASSERT(*valuelen - byte_cnt == 0); ASSERT(len == blksize); memset(dst + hdr_size + byte_cnt, 0, blksize - hdr_size - byte_cnt); } /* roll buffer forwards */ len -= blksize; dst += blksize; bno += BTOBB(blksize); /* roll attribute data forwards */ *valuelen -= byte_cnt; *src += byte_cnt; *offset += byte_cnt; } } /* * Read the value associated with an attribute from the out-of-line buffer * that we stored it in. */ int xfs_attr_rmtval_get( struct xfs_da_args *args) { struct xfs_bmbt_irec map[ATTR_RMTVALUE_MAPSIZE]; struct xfs_mount *mp = args->dp->i_mount; struct xfs_buf *bp; xfs_dablk_t lblkno = args->rmtblkno; __uint8_t *dst = args->value; int valuelen; int nmap; int error; int blkcnt = args->rmtblkcnt; int i; int offset = 0; trace_xfs_attr_rmtval_get(args); ASSERT(!(args->flags & ATTR_KERNOVAL)); ASSERT(args->rmtvaluelen == args->valuelen); valuelen = args->rmtvaluelen; while (valuelen > 0) { nmap = ATTR_RMTVALUE_MAPSIZE; error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, blkcnt, map, &nmap, XFS_BMAPI_ATTRFORK); if (error) return error; ASSERT(nmap >= 1); for (i = 0; (i < nmap) && (valuelen > 0); i++) { xfs_daddr_t dblkno; int dblkcnt; ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) && (map[i].br_startblock != HOLESTARTBLOCK)); dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dblkno, dblkcnt, 0, &bp, &xfs_attr3_rmt_buf_ops); if (error) return error; error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino, &offset, &valuelen, &dst); xfs_buf_relse(bp); if (error) return error; /* roll attribute extent map forwards */ lblkno += map[i].br_blockcount; blkcnt -= map[i].br_blockcount; } } ASSERT(valuelen == 0); return 0; } /* * Write the value associated with an attribute into the out-of-line buffer * that we have defined for it. */ int xfs_attr_rmtval_set( struct xfs_da_args *args) { struct xfs_inode *dp = args->dp; struct xfs_mount *mp = dp->i_mount; struct xfs_bmbt_irec map; xfs_dablk_t lblkno; xfs_fileoff_t lfileoff = 0; __uint8_t *src = args->value; int blkcnt; int valuelen; int nmap; int error; int offset = 0; trace_xfs_attr_rmtval_set(args); /* * Find a "hole" in the attribute address space large enough for * us to drop the new attribute's value into. Because CRC enable * attributes have headers, we can't just do a straight byte to FSB * conversion and have to take the header space into account. */ blkcnt = xfs_attr3_rmt_blocks(mp, args->rmtvaluelen); error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff, XFS_ATTR_FORK); if (error) return error; args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff; args->rmtblkcnt = blkcnt; /* * Roll through the "value", allocating blocks on disk as required. */ while (blkcnt > 0) { /* * Allocate a single extent, up to the size of the value. * * Note that we have to consider this a data allocation as we * write the remote attribute without logging the contents. * Hence we must ensure that we aren't using blocks that are on * the busy list so that we don't overwrite blocks which have * recently been freed but their transactions are not yet * committed to disk. If we overwrite the contents of a busy * extent and then crash then the block may not contain the * correct metadata after log recovery occurs. */ xfs_defer_init(args->dfops, args->firstblock); nmap = 1; error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, args->total, &map, &nmap, args->dfops); if (!error) error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); return error; } ASSERT(nmap == 1); ASSERT((map.br_startblock != DELAYSTARTBLOCK) && (map.br_startblock != HOLESTARTBLOCK)); lblkno += map.br_blockcount; blkcnt -= map.br_blockcount; /* * Start the next trans in the chain. */ error = xfs_trans_roll(&args->trans, dp); if (error) return error; } /* * Roll through the "value", copying the attribute value to the * already-allocated blocks. Blocks are written synchronously * so that we can know they are all on disk before we turn off * the INCOMPLETE flag. */ lblkno = args->rmtblkno; blkcnt = args->rmtblkcnt; valuelen = args->rmtvaluelen; while (valuelen > 0) { struct xfs_buf *bp; xfs_daddr_t dblkno; int dblkcnt; ASSERT(blkcnt > 0); xfs_defer_init(args->dfops, args->firstblock); nmap = 1; error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK); if (error) return error; ASSERT(nmap == 1); ASSERT((map.br_startblock != DELAYSTARTBLOCK) && (map.br_startblock != HOLESTARTBLOCK)); dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); bp = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt, 0); if (!bp) return -ENOMEM; bp->b_ops = &xfs_attr3_rmt_buf_ops; xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset, &valuelen, &src); error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */ xfs_buf_relse(bp); if (error) return error; /* roll attribute extent map forwards */ lblkno += map.br_blockcount; blkcnt -= map.br_blockcount; } ASSERT(valuelen == 0); return 0; } /* * Remove the value associated with an attribute by deleting the * out-of-line buffer that it is stored on. */ int xfs_attr_rmtval_remove( struct xfs_da_args *args) { struct xfs_mount *mp = args->dp->i_mount; xfs_dablk_t lblkno; int blkcnt; int error; int done; trace_xfs_attr_rmtval_remove(args); /* * Roll through the "value", invalidating the attribute value's blocks. */ lblkno = args->rmtblkno; blkcnt = args->rmtblkcnt; while (blkcnt > 0) { struct xfs_bmbt_irec map; struct xfs_buf *bp; xfs_daddr_t dblkno; int dblkcnt; int nmap; /* * Try to remember where we decided to put the value. */ nmap = 1; error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK); if (error) return error; ASSERT(nmap == 1); ASSERT((map.br_startblock != DELAYSTARTBLOCK) && (map.br_startblock != HOLESTARTBLOCK)); dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); /* * If the "remote" value is in the cache, remove it. */ bp = xfs_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK); if (bp) { xfs_buf_stale(bp); xfs_buf_relse(bp); bp = NULL; } lblkno += map.br_blockcount; blkcnt -= map.br_blockcount; } /* * Keep de-allocating extents until the remote-value region is gone. */ lblkno = args->rmtblkno; blkcnt = args->rmtblkcnt; done = 0; while (!done) { xfs_defer_init(args->dfops, args->firstblock); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, args->firstblock, args->dfops, &done); if (!error) error = xfs_defer_finish(&args->trans, args->dfops, args->dp); if (error) { args->trans = NULL; xfs_defer_cancel(args->dfops); return error; } /* * Close out trans and start the next one in the chain. */ error = xfs_trans_roll(&args->trans, args->dp); if (error) return error; } return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_attr_remote.h0000644000000000000000000000177713063067171017353 0ustar /* * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_ATTR_REMOTE_H__ #define __XFS_ATTR_REMOTE_H__ int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); int xfs_attr_rmtval_get(struct xfs_da_args *args); int xfs_attr_rmtval_set(struct xfs_da_args *args); int xfs_attr_rmtval_remove(struct xfs_da_args *args); #endif /* __XFS_ATTR_REMOTE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_attr_sf.h0000644000000000000000000000426013063067171016456 0ustar /* * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_ATTR_SF_H__ #define __XFS_ATTR_SF_H__ /* * Attribute storage when stored inside the inode. * * Small attribute lists are packed as tightly as possible so as * to fit into the literal area of the inode. */ typedef struct xfs_attr_sf_hdr xfs_attr_sf_hdr_t; typedef struct xfs_attr_sf_entry xfs_attr_sf_entry_t; /* * We generate this then sort it, attr_list() must return things in hash-order. */ typedef struct xfs_attr_sf_sort { __uint8_t entno; /* entry number in original list */ __uint8_t namelen; /* length of name value (no null) */ __uint8_t valuelen; /* length of value */ __uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */ xfs_dahash_t hash; /* this entry's hash value */ unsigned char *name; /* name value, pointer into buffer */ } xfs_attr_sf_sort_t; #define XFS_ATTR_SF_ENTSIZE_BYNAME(nlen,vlen) /* space name/value uses */ \ (((int)sizeof(xfs_attr_sf_entry_t)-1 + (nlen)+(vlen))) #define XFS_ATTR_SF_ENTSIZE_MAX /* max space for name&value */ \ ((1 << (NBBY*(int)sizeof(__uint8_t))) - 1) #define XFS_ATTR_SF_ENTSIZE(sfep) /* space an entry uses */ \ ((int)sizeof(xfs_attr_sf_entry_t)-1 + (sfep)->namelen+(sfep)->valuelen) #define XFS_ATTR_SF_NEXTENTRY(sfep) /* next entry in struct */ \ ((xfs_attr_sf_entry_t *)((char *)(sfep) + XFS_ATTR_SF_ENTSIZE(sfep))) #define XFS_ATTR_SF_TOTSIZE(dp) /* total space in use */ \ (be16_to_cpu(((xfs_attr_shortform_t *) \ ((dp)->i_afp->if_u1.if_data))->hdr.totsize)) #endif /* __XFS_ATTR_SF_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_bit.c0000644000000000000000000000543613063067171015573 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_log_format.h" #include "xfs_bit.h" /* * XFS bit manipulation routines, used in non-realtime code. */ /* * Return whether bitmap is empty. * Size is number of words in the bitmap, which is padded to word boundary * Returns 1 for empty, 0 for non-empty. */ int xfs_bitmap_empty(uint *map, uint size) { uint i; for (i = 0; i < size; i++) { if (map[i] != 0) return 0; } return 1; } /* * Count the number of contiguous bits set in the bitmap starting with bit * start_bit. Size is the size of the bitmap in words. */ int xfs_contig_bits(uint *map, uint size, uint start_bit) { uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT); uint result = 0; uint tmp; size <<= BIT_TO_WORD_SHIFT; ASSERT(start_bit < size); size -= start_bit & ~(NBWORD - 1); start_bit &= (NBWORD - 1); if (start_bit) { tmp = *p++; /* set to one first offset bits prior to start */ tmp |= (~0U >> (NBWORD-start_bit)); if (tmp != ~0U) goto found; result += NBWORD; size -= NBWORD; } while (size) { if ((tmp = *p++) != ~0U) goto found; result += NBWORD; size -= NBWORD; } return result - start_bit; found: return result + ffz(tmp) - start_bit; } /* * This takes the bit number to start looking from and * returns the next set bit from there. It returns -1 * if there are no more bits set or the start bit is * beyond the end of the bitmap. * * Size is the number of words, not bytes, in the bitmap. */ int xfs_next_bit(uint *map, uint size, uint start_bit) { uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT); uint result = start_bit & ~(NBWORD - 1); uint tmp; size <<= BIT_TO_WORD_SHIFT; if (start_bit >= size) return -1; size -= result; start_bit &= (NBWORD - 1); if (start_bit) { tmp = *p++; /* set to zero first offset bits prior to start */ tmp &= (~0U << start_bit); if (tmp != 0U) goto found; result += NBWORD; size -= NBWORD; } while (size) { if ((tmp = *p++) != 0U) goto found; result += NBWORD; size -= NBWORD; } return -1; found: return result + ffs(tmp) - 1; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_bit.h0000644000000000000000000000423513063067171015574 0ustar /* * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_BIT_H__ #define __XFS_BIT_H__ /* * XFS bit manipulation routines. */ /* * masks with n high/low bits set, 64-bit values */ static inline __uint64_t xfs_mask64hi(int n) { return (__uint64_t)-1 << (64 - (n)); } static inline __uint32_t xfs_mask32lo(int n) { return ((__uint32_t)1 << (n)) - 1; } static inline __uint64_t xfs_mask64lo(int n) { return ((__uint64_t)1 << (n)) - 1; } /* Get high bit set out of 32-bit argument, -1 if none set */ static inline int xfs_highbit32(__uint32_t v) { return fls(v) - 1; } /* Get high bit set out of 64-bit argument, -1 if none set */ static inline int xfs_highbit64(__uint64_t v) { return fls64(v) - 1; } /* Get low bit set out of 32-bit argument, -1 if none set */ static inline int xfs_lowbit32(__uint32_t v) { return ffs(v) - 1; } /* Get low bit set out of 64-bit argument, -1 if none set */ static inline int xfs_lowbit64(__uint64_t v) { __uint32_t w = (__uint32_t)v; int n = 0; if (w) { /* lower bits */ n = ffs(w); } else { /* upper bits */ w = (__uint32_t)(v >> 32); if (w) { n = ffs(w); if (n) n += 32; } } return n - 1; } /* Return whether bitmap is empty (1 == empty) */ extern int xfs_bitmap_empty(uint *map, uint size); /* Count continuous one bits in map starting with start_bit */ extern int xfs_contig_bits(uint *map, uint size, uint start_bit); /* Find next set bit in map */ extern int xfs_next_bit(uint *map, uint size, uint start_bit); #endif /* __XFS_BIT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_bmap.c0000644000000000000000000056615413063067171015745 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_trans.h" #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_bmap_btree.h" #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_attr_leaf.h" #include "xfs_quota_defs.h" #include "xfs_rmap.h" #include "xfs_ag_resv.h" #include "xfs_refcount.h" kmem_zone_t *xfs_bmap_free_item_zone; /* * Miscellaneous helper functions */ /* * Compute and fill in the value of the maximum depth of a bmap btree * in this filesystem. Done once, during mount. */ void xfs_bmap_compute_maxlevels( xfs_mount_t *mp, /* file system mount structure */ int whichfork) /* data or attr fork */ { int level; /* btree level */ uint maxblocks; /* max blocks at this level */ uint maxleafents; /* max leaf entries possible */ int maxrootrecs; /* max records in root block */ int minleafrecs; /* min records in leaf block */ int minnoderecs; /* min records in node block */ int sz; /* root block size */ /* * The maximum number of extents in a file, hence the maximum * number of leaf entries, is controlled by the type of di_nextents * (a signed 32-bit number, xfs_extnum_t), or by di_anextents * (a signed 16-bit number, xfs_aextnum_t). * * Note that we can no longer assume that if we are in ATTR1 that * the fork offset of all the inodes will be * (xfs_default_attroffset(ip) >> 3) because we could have mounted * with ATTR2 and then mounted back with ATTR1, keeping the * di_forkoff's fixed but probably at various positions. Therefore, * for both ATTR1 and ATTR2 we have to assume the worst case scenario * of a minimum size available. */ if (whichfork == XFS_DATA_FORK) { maxleafents = MAXEXTNUM; sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS); } else { maxleafents = MAXAEXTNUM; sz = XFS_BMDR_SPACE_CALC(MINABTPTRS); } maxrootrecs = xfs_bmdr_maxrecs(sz, 0); minleafrecs = mp->m_bmap_dmnr[0]; minnoderecs = mp->m_bmap_dmnr[1]; maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; for (level = 1; maxblocks > 1; level++) { if (maxblocks <= maxrootrecs) maxblocks = 1; else maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; } mp->m_bm_maxlevels[whichfork] = level; } STATIC int /* error */ xfs_bmbt_lookup_eq( struct xfs_btree_cur *cur, xfs_fileoff_t off, xfs_fsblock_t bno, xfs_filblks_t len, int *stat) /* success/failure */ { cur->bc_rec.b.br_startoff = off; cur->bc_rec.b.br_startblock = bno; cur->bc_rec.b.br_blockcount = len; return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); } STATIC int /* error */ xfs_bmbt_lookup_ge( struct xfs_btree_cur *cur, xfs_fileoff_t off, xfs_fsblock_t bno, xfs_filblks_t len, int *stat) /* success/failure */ { cur->bc_rec.b.br_startoff = off; cur->bc_rec.b.br_startblock = bno; cur->bc_rec.b.br_blockcount = len; return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); } /* * Check if the inode needs to be converted to btree format. */ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork) { return whichfork != XFS_COW_FORK && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && XFS_IFORK_NEXTENTS(ip, whichfork) > XFS_IFORK_MAXEXT(ip, whichfork); } /* * Check if the inode should be converted to extent format. */ static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork) { return whichfork != XFS_COW_FORK && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && XFS_IFORK_NEXTENTS(ip, whichfork) <= XFS_IFORK_MAXEXT(ip, whichfork); } /* * Update the record referred to by cur to the value given * by [off, bno, len, state]. * This either works (return 0) or gets an EFSCORRUPTED error. */ STATIC int xfs_bmbt_update( struct xfs_btree_cur *cur, xfs_fileoff_t off, xfs_fsblock_t bno, xfs_filblks_t len, xfs_exntst_t state) { union xfs_btree_rec rec; xfs_bmbt_disk_set_allf(&rec.bmbt, off, bno, len, state); return xfs_btree_update(cur, &rec); } /* * Compute the worst-case number of indirect blocks that will be used * for ip's delayed extent of length "len". */ STATIC xfs_filblks_t xfs_bmap_worst_indlen( xfs_inode_t *ip, /* incore inode pointer */ xfs_filblks_t len) /* delayed extent length */ { int level; /* btree level number */ int maxrecs; /* maximum record count at this level */ xfs_mount_t *mp; /* mount structure */ xfs_filblks_t rval; /* return value */ mp = ip->i_mount; maxrecs = mp->m_bmap_dmxr[0]; for (level = 0, rval = 0; level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK); level++) { len += maxrecs - 1; do_div(len, maxrecs); rval += len; if (len == 1) return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - level - 1; if (level == 0) maxrecs = mp->m_bmap_dmxr[1]; } return rval; } /* * Calculate the default attribute fork offset for newly created inodes. */ uint xfs_default_attroffset( struct xfs_inode *ip) { struct xfs_mount *mp = ip->i_mount; uint offset; if (mp->m_sb.sb_inodesize == 256) { offset = XFS_LITINO(mp, ip->i_d.di_version) - XFS_BMDR_SPACE_CALC(MINABTPTRS); } else { offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS); } ASSERT(offset < XFS_LITINO(mp, ip->i_d.di_version)); return offset; } /* * Helper routine to reset inode di_forkoff field when switching * attribute fork from local to extent format - we reset it where * possible to make space available for inline data fork extents. */ STATIC void xfs_bmap_forkoff_reset( xfs_inode_t *ip, int whichfork) { if (whichfork == XFS_ATTR_FORK && ip->i_d.di_format != XFS_DINODE_FMT_DEV && ip->i_d.di_format != XFS_DINODE_FMT_UUID && ip->i_d.di_format != XFS_DINODE_FMT_BTREE) { uint dfl_forkoff = xfs_default_attroffset(ip) >> 3; if (dfl_forkoff > ip->i_d.di_forkoff) ip->i_d.di_forkoff = dfl_forkoff; } } #ifdef DEBUG STATIC struct xfs_buf * xfs_bmap_get_bp( struct xfs_btree_cur *cur, xfs_fsblock_t bno) { struct xfs_log_item_desc *lidp; int i; if (!cur) return NULL; for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) { if (!cur->bc_bufs[i]) break; if (XFS_BUF_ADDR(cur->bc_bufs[i]) == bno) return cur->bc_bufs[i]; } /* Chase down all the log items to see if the bp is there */ list_for_each_entry(lidp, &cur->bc_tp->t_items, lid_trans) { struct xfs_buf_log_item *bip; bip = (struct xfs_buf_log_item *)lidp->lid_item; if (bip->bli_item.li_type == XFS_LI_BUF && XFS_BUF_ADDR(bip->bli_buf) == bno) return bip->bli_buf; } return NULL; } STATIC void xfs_check_block( struct xfs_btree_block *block, xfs_mount_t *mp, int root, short sz) { int i, j, dmxr; __be64 *pp, *thispa; /* pointer to block address */ xfs_bmbt_key_t *prevp, *keyp; ASSERT(be16_to_cpu(block->bb_level) > 0); prevp = NULL; for( i = 1; i <= xfs_btree_get_numrecs(block); i++) { dmxr = mp->m_bmap_dmxr[0]; keyp = XFS_BMBT_KEY_ADDR(mp, block, i); if (prevp) { ASSERT(be64_to_cpu(prevp->br_startoff) < be64_to_cpu(keyp->br_startoff)); } prevp = keyp; /* * Compare the block numbers to see if there are dups. */ if (root) pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, i, sz); else pp = XFS_BMBT_PTR_ADDR(mp, block, i, dmxr); for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) { if (root) thispa = XFS_BMAP_BROOT_PTR_ADDR(mp, block, j, sz); else thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr); if (*thispa == *pp) { xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld", __func__, j, i, (unsigned long long)be64_to_cpu(*thispa)); panic("%s: ptrs are equal in node\n", __func__); } } } } /* * Check that the extents for the inode ip are in the right order in all * btree leaves. THis becomes prohibitively expensive for large extent count * files, so don't bother with inodes that have more than 10,000 extents in * them. The btree record ordering checks will still be done, so for such large * bmapbt constructs that is going to catch most corruptions. */ STATIC void xfs_bmap_check_leaf_extents( xfs_btree_cur_t *cur, /* btree cursor or null */ xfs_inode_t *ip, /* incore inode pointer */ int whichfork) /* data or attr fork */ { struct xfs_btree_block *block; /* current btree block */ xfs_fsblock_t bno; /* block # of "block" */ xfs_buf_t *bp; /* buffer for "block" */ int error; /* error return value */ xfs_extnum_t i=0, j; /* index into the extents list */ xfs_ifork_t *ifp; /* fork structure */ int level; /* btree level, for checking */ xfs_mount_t *mp; /* file system mount structure */ __be64 *pp; /* pointer to block address */ xfs_bmbt_rec_t *ep; /* pointer to current extent */ xfs_bmbt_rec_t last = {0, 0}; /* last extent in prev block */ xfs_bmbt_rec_t *nextp; /* pointer to next extent */ int bp_release = 0; if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) { return; } /* skip large extent count inodes */ if (ip->i_d.di_nextents > 10000) return; bno = NULLFSBLOCK; mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); block = ifp->if_broot; /* * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out. */ level = be16_to_cpu(block->bb_level); ASSERT(level > 0); xfs_check_block(block, mp, 1, ifp->if_broot_bytes); pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); bno = be64_to_cpu(*pp); ASSERT(bno != NULLFSBLOCK); ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount); ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks); /* * Go down the tree until leaf level is reached, following the first * pointer (leftmost) at each level. */ while (level-- > 0) { /* See if buf is in cur first */ bp_release = 0; bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno)); if (!bp) { bp_release = 1; error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp, XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops); if (error) goto error_norelse; } block = XFS_BUF_TO_BLOCK(bp); if (level == 0) break; /* * Check this block for basic sanity (increasing keys and * no duplicate blocks). */ xfs_check_block(block, mp, 0, 0); pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); bno = be64_to_cpu(*pp); XFS_WANT_CORRUPTED_GOTO(mp, XFS_FSB_SANITY_CHECK(mp, bno), error0); if (bp_release) { bp_release = 0; xfs_trans_brelse(NULL, bp); } } /* * Here with bp and block set to the leftmost leaf node in the tree. */ i = 0; /* * Loop over all leaf nodes checking that all extents are in the right order. */ for (;;) { xfs_fsblock_t nextbno; xfs_extnum_t num_recs; num_recs = xfs_btree_get_numrecs(block); /* * Read-ahead the next leaf block, if any. */ nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); /* * Check all the extents to make sure they are OK. * If we had a previous block, the last entry should * conform with the first entry in this one. */ ep = XFS_BMBT_REC_ADDR(mp, block, 1); if (i) { ASSERT(xfs_bmbt_disk_get_startoff(&last) + xfs_bmbt_disk_get_blockcount(&last) <= xfs_bmbt_disk_get_startoff(ep)); } for (j = 1; j < num_recs; j++) { nextp = XFS_BMBT_REC_ADDR(mp, block, j + 1); ASSERT(xfs_bmbt_disk_get_startoff(ep) + xfs_bmbt_disk_get_blockcount(ep) <= xfs_bmbt_disk_get_startoff(nextp)); ep = nextp; } last = *ep; i += num_recs; if (bp_release) { bp_release = 0; xfs_trans_brelse(NULL, bp); } bno = nextbno; /* * If we've reached the end, stop. */ if (bno == NULLFSBLOCK) break; bp_release = 0; bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno)); if (!bp) { bp_release = 1; error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp, XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops); if (error) goto error_norelse; } block = XFS_BUF_TO_BLOCK(bp); } return; error0: xfs_warn(mp, "%s: at error0", __func__); if (bp_release) xfs_trans_brelse(NULL, bp); error_norelse: xfs_warn(mp, "%s: BAD after btree leaves for %d extents", __func__, i); panic("%s: CORRUPTED BTREE OR SOMETHING", __func__); return; } /* * Add bmap trace insert entries for all the contents of the extent records. */ void xfs_bmap_trace_exlist( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t cnt, /* count of entries in the list */ int whichfork, /* data or attr fork */ unsigned long caller_ip) { xfs_extnum_t idx; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ int state = 0; if (whichfork == XFS_ATTR_FORK) state |= BMAP_ATTRFORK; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))); for (idx = 0; idx < cnt; idx++) trace_xfs_extlist(ip, idx, whichfork, caller_ip); } /* * Validate that the bmbt_irecs being returned from bmapi are valid * given the caller's original parameters. Specifically check the * ranges of the returned irecs to ensure that they only extend beyond * the given parameters if the XFS_BMAPI_ENTIRE flag was set. */ STATIC void xfs_bmap_validate_ret( xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_bmbt_irec_t *mval, int nmap, int ret_nmap) { int i; /* index to map values */ ASSERT(ret_nmap <= nmap); for (i = 0; i < ret_nmap; i++) { ASSERT(mval[i].br_blockcount > 0); if (!(flags & XFS_BMAPI_ENTIRE)) { ASSERT(mval[i].br_startoff >= bno); ASSERT(mval[i].br_blockcount <= len); ASSERT(mval[i].br_startoff + mval[i].br_blockcount <= bno + len); } else { ASSERT(mval[i].br_startoff < bno + len); ASSERT(mval[i].br_startoff + mval[i].br_blockcount > bno); } ASSERT(i == 0 || mval[i - 1].br_startoff + mval[i - 1].br_blockcount == mval[i].br_startoff); ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK && mval[i].br_startblock != HOLESTARTBLOCK); ASSERT(mval[i].br_state == XFS_EXT_NORM || mval[i].br_state == XFS_EXT_UNWRITTEN); } } #else #define xfs_bmap_check_leaf_extents(cur, ip, whichfork) do { } while (0) #define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap) #endif /* DEBUG */ /* * bmap free list manipulation functions */ /* * Add the extent to the list of extents to be free at transaction end. * The list is maintained sorted (by block number). */ void xfs_bmap_add_free( struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t bno, xfs_filblks_t len, struct xfs_owner_info *oinfo) { struct xfs_extent_free_item *new; /* new element */ #ifdef DEBUG xfs_agnumber_t agno; xfs_agblock_t agbno; ASSERT(bno != NULLFSBLOCK); ASSERT(len > 0); ASSERT(len <= MAXEXTLEN); ASSERT(!isnullstartblock(bno)); agno = XFS_FSB_TO_AGNO(mp, bno); agbno = XFS_FSB_TO_AGBNO(mp, bno); ASSERT(agno < mp->m_sb.sb_agcount); ASSERT(agbno < mp->m_sb.sb_agblocks); ASSERT(len < mp->m_sb.sb_agblocks); ASSERT(agbno + len <= mp->m_sb.sb_agblocks); #endif ASSERT(xfs_bmap_free_item_zone != NULL); new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xefi_startblock = bno; new->xefi_blockcount = (xfs_extlen_t)len; if (oinfo) new->xefi_oinfo = *oinfo; else xfs_rmap_skip_owner_update(&new->xefi_oinfo); trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0, XFS_FSB_TO_AGBNO(mp, bno), len); xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list); } /* * Inode fork format manipulation functions */ /* * Transform a btree format file with only one leaf node, where the * extents list will fit in the inode, into an extents format file. * Since the file extents are already in-core, all we have to do is * give up the space for the btree root and pitch the leaf block. */ STATIC int /* error */ xfs_bmap_btree_to_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_btree_cur_t *cur, /* btree cursor */ int *logflagsp, /* inode logging flags */ int whichfork) /* data or attr fork */ { /* REFERENCED */ struct xfs_btree_block *cblock;/* child btree block */ xfs_fsblock_t cbno; /* child block number */ xfs_buf_t *cbp; /* child block's buffer */ int error; /* error return value */ xfs_ifork_t *ifp; /* inode fork data */ xfs_mount_t *mp; /* mount point structure */ __be64 *pp; /* ptr to block address */ struct xfs_btree_block *rblock;/* root btree block */ struct xfs_owner_info oinfo; mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(whichfork != XFS_COW_FORK); ASSERT(ifp->if_flags & XFS_IFEXTENTS); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE); rblock = ifp->if_broot; ASSERT(be16_to_cpu(rblock->bb_level) == 1); ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1); ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1); pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes); cbno = be64_to_cpu(*pp); *logflagsp = 0; #ifdef DEBUG if ((error = xfs_btree_check_lptr(cur, cbno, 1))) return error; #endif error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp, XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops); if (error) return error; cblock = XFS_BUF_TO_BLOCK(cbp); if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) return error; xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork); xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); if (cur->bc_bufs[0] == cbp) cur->bc_bufs[0] = NULL; xfs_iroot_realloc(ip, -1, whichfork); ASSERT(ifp->if_broot == NULL); ASSERT((ifp->if_flags & XFS_IFBROOT) == 0); XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); *logflagsp = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); return 0; } /* * Convert an extents-format file into a btree-format file. * The new file will have a root block (in the inode) and a single child block. */ STATIC int /* error */ xfs_bmap_extents_to_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first-block-allocated */ struct xfs_defer_ops *dfops, /* blocks freed in xaction */ xfs_btree_cur_t **curp, /* cursor returned to caller */ int wasdel, /* converting a delayed alloc */ int *logflagsp, /* inode logging flags */ int whichfork) /* data or attr fork */ { struct xfs_btree_block *ablock; /* allocated (child) bt block */ xfs_buf_t *abp; /* buffer for ablock */ xfs_alloc_arg_t args; /* allocation arguments */ xfs_bmbt_rec_t *arp; /* child record pointer */ struct xfs_btree_block *block; /* btree root block */ xfs_btree_cur_t *cur; /* bmap btree cursor */ xfs_bmbt_rec_host_t *ep; /* extent record pointer */ int error; /* error return value */ xfs_extnum_t i, cnt; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_key_t *kp; /* root block key pointer */ xfs_mount_t *mp; /* mount structure */ xfs_extnum_t nextents; /* number of file extents */ xfs_bmbt_ptr_t *pp; /* root block address pointer */ mp = ip->i_mount; ASSERT(whichfork != XFS_COW_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS); /* * Make space in the inode incore. */ xfs_iroot_realloc(ip, 1, whichfork); ifp->if_flags |= XFS_IFBROOT; /* * Fill in the root. */ block = ifp->if_broot; if (xfs_sb_version_hascrc(&mp->m_sb)) xfs_btree_init_block_int(mp, block, XFS_BUF_DADDR_NULL, XFS_BMAP_CRC_MAGIC, 1, 1, ip->i_ino, XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS); else xfs_btree_init_block_int(mp, block, XFS_BUF_DADDR_NULL, XFS_BMAP_MAGIC, 1, 1, ip->i_ino, XFS_BTREE_LONG_PTRS); /* * Need a cursor. Can't allocate until bb_level is filled in. */ cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0; /* * Convert to a btree with two levels, one record in root. */ XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE); memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = mp; xfs_rmap_ino_bmbt_owner(&args.oinfo, ip->i_ino, whichfork); args.firstblock = *firstblock; if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); } else if (dfops->dop_low) { try_another_ag: args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = *firstblock; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; args.fsbno = *firstblock; } args.minlen = args.maxlen = args.prod = 1; args.wasdel = wasdel; *logflagsp = 0; if ((error = xfs_alloc_vextent(&args))) { xfs_iroot_realloc(ip, -1, whichfork); xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } /* * During a CoW operation, the allocation and bmbt updates occur in * different transactions. The mapping code tries to put new bmbt * blocks near extents being mapped, but the only way to guarantee this * is if the alloc and the mapping happen in a single transaction that * has a block reservation. That isn't the case here, so if we run out * of space we'll try again with another AG. */ if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && args.fsbno == NULLFSBLOCK && args.type == XFS_ALLOCTYPE_NEAR_BNO) { dfops->dop_low = true; goto try_another_ag; } /* * Allocation can't fail, the space was reserved. */ ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(*firstblock == NULLFSBLOCK || args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) || (dfops->dop_low && args.agno > XFS_FSB_TO_AGNO(mp, *firstblock))); *firstblock = cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; ip->i_d.di_nblocks++; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L); abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0); /* * Fill in the child block. */ abp->b_ops = &xfs_bmbt_buf_ops; ablock = XFS_BUF_TO_BLOCK(abp); if (xfs_sb_version_hascrc(&mp->m_sb)) xfs_btree_init_block_int(mp, ablock, abp->b_bn, XFS_BMAP_CRC_MAGIC, 0, 0, ip->i_ino, XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS); else xfs_btree_init_block_int(mp, ablock, abp->b_bn, XFS_BMAP_MAGIC, 0, 0, ip->i_ino, XFS_BTREE_LONG_PTRS); arp = XFS_BMBT_REC_ADDR(mp, ablock, 1); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); for (cnt = i = 0; i < nextents; i++) { ep = xfs_iext_get_ext(ifp, i); if (!isnullstartblock(xfs_bmbt_get_startblock(ep))) { arp->l0 = cpu_to_be64(ep->l0); arp->l1 = cpu_to_be64(ep->l1); arp++; cnt++; } } ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork)); xfs_btree_set_numrecs(ablock, cnt); /* * Fill in the root key and pointer. */ kp = XFS_BMBT_KEY_ADDR(mp, block, 1); arp = XFS_BMBT_REC_ADDR(mp, ablock, 1); kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp)); pp = XFS_BMBT_PTR_ADDR(mp, block, 1, xfs_bmbt_get_maxrecs(cur, be16_to_cpu(block->bb_level))); *pp = cpu_to_be64(args.fsbno); /* * Do all this logging at the end so that * the root is at the right level. */ xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS); xfs_btree_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs)); ASSERT(*curp == NULL); *curp = cur; *logflagsp = XFS_ILOG_CORE | xfs_ilog_fbroot(whichfork); return 0; } /* * Convert a local file to an extents file. * This code is out of bounds for data forks of regular files, * since the file data needs to get logged so things will stay consistent. * (The bmap-level manipulations are ok, though). */ void xfs_bmap_local_to_extents_empty( struct xfs_inode *ip, int whichfork) { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(whichfork != XFS_COW_FORK); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); ASSERT(ifp->if_bytes == 0); ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); xfs_bmap_forkoff_reset(ip, whichfork); ifp->if_flags &= ~XFS_IFINLINE; ifp->if_flags |= XFS_IFEXTENTS; XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); } STATIC int /* error */ xfs_bmap_local_to_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated in xaction */ xfs_extlen_t total, /* total blocks needed by transaction */ int *logflagsp, /* inode logging flags */ int whichfork, void (*init_fn)(struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_inode *ip, struct xfs_ifork *ifp)) { int error = 0; int flags; /* logging flags returned */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_alloc_arg_t args; /* allocation arguments */ xfs_buf_t *bp; /* buffer for extent block */ xfs_bmbt_rec_host_t *ep; /* extent record pointer */ /* * We don't want to deal with the case of keeping inode data inline yet. * So sending the data fork of a regular inode is invalid. */ ASSERT(!(S_ISREG(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK)); ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); if (!ifp->if_bytes) { xfs_bmap_local_to_extents_empty(ip, whichfork); flags = XFS_ILOG_CORE; goto done; } flags = 0; error = 0; ASSERT((ifp->if_flags & (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = ip->i_mount; xfs_rmap_ino_owner(&args.oinfo, ip->i_ino, whichfork, 0); args.firstblock = *firstblock; /* * Allocate a block. We know we need only one, since the * file currently fits in an inode. */ if (*firstblock == NULLFSBLOCK) { try_another_ag: args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino); args.type = XFS_ALLOCTYPE_START_BNO; } else { args.fsbno = *firstblock; args.type = XFS_ALLOCTYPE_NEAR_BNO; } args.total = total; args.minlen = args.maxlen = args.prod = 1; error = xfs_alloc_vextent(&args); if (error) goto done; /* * During a CoW operation, the allocation and bmbt updates occur in * different transactions. The mapping code tries to put new bmbt * blocks near extents being mapped, but the only way to guarantee this * is if the alloc and the mapping happen in a single transaction that * has a block reservation. That isn't the case here, so if we run out * of space we'll try again with another AG. */ if (xfs_sb_version_hasreflink(&ip->i_mount->m_sb) && args.fsbno == NULLFSBLOCK && args.type == XFS_ALLOCTYPE_NEAR_BNO) { goto try_another_ag; } /* Can't fail, the space was reserved. */ ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(args.len == 1); *firstblock = args.fsbno; bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0); /* * Initialize the block, copy the data and log the remote buffer. * * The callout is responsible for logging because the remote format * might differ from the local format and thus we don't know how much to * log here. Note that init_fn must also set the buffer log item type * correctly. */ init_fn(tp, bp, ip, ifp); /* account for the change in fork size */ xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); xfs_bmap_local_to_extents_empty(ip, whichfork); flags |= XFS_ILOG_CORE; xfs_iext_add(ifp, 0, 1); ep = xfs_iext_get_ext(ifp, 0); xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM); trace_xfs_bmap_post_update(ip, 0, whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0, _THIS_IP_); XFS_IFORK_NEXT_SET(ip, whichfork, 1); ip->i_d.di_nblocks = 1; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L); flags |= xfs_ilog_fext(whichfork); done: *logflagsp = flags; return error; } /* * Called from xfs_bmap_add_attrfork to handle btree format files. */ STATIC int /* error */ xfs_bmap_add_attrfork_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ int error; /* error return value */ xfs_mount_t *mp; /* file system mount struct */ int stat; /* newroot status */ mp = ip->i_mount; if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip)) *flags |= XFS_ILOG_DBROOT; else { cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK); cur->bc_private.b.dfops = dfops; cur->bc_private.b.firstblock = *firstblock; if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat))) goto error0; /* must be at least one entry */ XFS_WANT_CORRUPTED_GOTO(mp, stat == 1, error0); if ((error = xfs_btree_new_iroot(cur, flags, &stat))) goto error0; if (stat == 0) { xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return -ENOSPC; } *firstblock = cur->bc_private.b.firstblock; cur->bc_private.b.allocated = 0; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); } return 0; error0: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } /* * Called from xfs_bmap_add_attrfork to handle extents format files. */ STATIC int /* error */ xfs_bmap_add_attrfork_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ int error; /* error return value */ if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip)) return 0; cur = NULL; error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops, &cur, 0, flags, XFS_DATA_FORK); if (cur) { cur->bc_private.b.allocated = 0; xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); } return error; } /* * Called from xfs_bmap_add_attrfork to handle local format files. Each * different data fork content type needs a different callout to do the * conversion. Some are basic and only require special block initialisation * callouts for the data formating, others (directories) are so specialised they * handle everything themselves. * * XXX (dgc): investigate whether directory conversion can use the generic * formatting callout. It should be possible - it's just a very complex * formatter. */ STATIC int /* error */ xfs_bmap_add_attrfork_local( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_da_args_t dargs; /* args for dir/attr code */ if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip)) return 0; if (S_ISDIR(VFS_I(ip)->i_mode)) { memset(&dargs, 0, sizeof(dargs)); dargs.geo = ip->i_mount->m_dir_geo; dargs.dp = ip; dargs.firstblock = firstblock; dargs.dfops = dfops; dargs.total = dargs.geo->fsbcount; dargs.whichfork = XFS_DATA_FORK; dargs.trans = tp; return xfs_dir2_sf_to_block(&dargs); } if (S_ISLNK(VFS_I(ip)->i_mode)) return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, XFS_DATA_FORK, xfs_symlink_local_to_remote); /* should only be called for types that support local format data */ ASSERT(0); return -EFSCORRUPTED; } /* * Convert inode from non-attributed to attributed. * Must not be in a transaction, ip must not be locked. */ int /* error code */ xfs_bmap_add_attrfork( xfs_inode_t *ip, /* incore inode pointer */ int size, /* space new attribute needs */ int rsvd) /* xact may use reserved blks */ { xfs_fsblock_t firstblock; /* 1st block/ag allocated */ struct xfs_defer_ops dfops; /* freed extent records */ xfs_mount_t *mp; /* mount structure */ xfs_trans_t *tp; /* transaction pointer */ int blks; /* space reservation */ int version = 1; /* superblock attr version */ int logflags; /* logging flags */ int error; /* error return value */ ASSERT(XFS_IFORK_Q(ip) == 0); mp = ip->i_mount; ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); blks = XFS_ADDAFORK_SPACE_RES(mp); error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0, rsvd ? XFS_TRANS_RESERVE : 0, &tp); if (error) return error; xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : XFS_QMOPT_RES_REGBLKS); if (error) goto trans_cancel; if (XFS_IFORK_Q(ip)) goto trans_cancel; if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) { /* * For inodes coming from pre-6.2 filesystems. */ ASSERT(ip->i_d.di_aformat == 0); ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; } ASSERT(ip->i_d.di_anextents == 0); xfs_trans_ijoin(tp, ip, 0); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); switch (ip->i_d.di_format) { case XFS_DINODE_FMT_DEV: ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; break; case XFS_DINODE_FMT_UUID: ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3; break; case XFS_DINODE_FMT_LOCAL: case XFS_DINODE_FMT_EXTENTS: case XFS_DINODE_FMT_BTREE: ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size); if (!ip->i_d.di_forkoff) ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3; else if (mp->m_flags & XFS_MOUNT_ATTR2) version = 2; break; default: ASSERT(0); error = -EINVAL; goto trans_cancel; } ASSERT(ip->i_afp == NULL); ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); ip->i_afp->if_flags = XFS_IFEXTENTS; logflags = 0; xfs_defer_init(&dfops, &firstblock); switch (ip->i_d.di_format) { case XFS_DINODE_FMT_LOCAL: error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &dfops, &logflags); break; case XFS_DINODE_FMT_EXTENTS: error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock, &dfops, &logflags); break; case XFS_DINODE_FMT_BTREE: error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &dfops, &logflags); break; default: error = 0; break; } if (logflags) xfs_trans_log_inode(tp, ip, logflags); if (error) goto bmap_cancel; if (!xfs_sb_version_hasattr(&mp->m_sb) || (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) { bool log_sb = false; spin_lock(&mp->m_sb_lock); if (!xfs_sb_version_hasattr(&mp->m_sb)) { xfs_sb_version_addattr(&mp->m_sb); log_sb = true; } if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) { xfs_sb_version_addattr2(&mp->m_sb); log_sb = true; } spin_unlock(&mp->m_sb_lock); if (log_sb) xfs_log_sb(tp); } error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto bmap_cancel; error = xfs_trans_commit(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); return error; bmap_cancel: xfs_defer_cancel(&dfops); trans_cancel: xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); return error; } /* * Internal and external extent tree search functions. */ /* * Read in the extents to if_extents. * All inode fields are set up by caller, we just traverse the btree * and copy the records in. If the file system cannot contain unwritten * extents, the records are checked for no "state" flags. */ int /* error */ xfs_bmap_read_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode */ int whichfork) /* data or attr fork */ { struct xfs_btree_block *block; /* current btree block */ xfs_fsblock_t bno; /* block # of "block" */ xfs_buf_t *bp; /* buffer for "block" */ int error; /* error return value */ xfs_exntfmt_t exntf; /* XFS_EXTFMT_NOSTATE, if checking */ xfs_extnum_t i, j; /* index into the extents list */ xfs_ifork_t *ifp; /* fork structure */ int level; /* btree level, for checking */ xfs_mount_t *mp; /* file system mount structure */ __be64 *pp; /* pointer to block address */ /* REFERENCED */ xfs_extnum_t room; /* number of entries there's room for */ bno = NULLFSBLOCK; mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE : XFS_EXTFMT_INODE(ip); block = ifp->if_broot; /* * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out. */ level = be16_to_cpu(block->bb_level); ASSERT(level > 0); pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); bno = be64_to_cpu(*pp); ASSERT(bno != NULLFSBLOCK); ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount); ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks); /* * Go down the tree until leaf level is reached, following the first * pointer (leftmost) at each level. */ while (level-- > 0) { error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops); if (error) return error; block = XFS_BUF_TO_BLOCK(bp); if (level == 0) break; pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); bno = be64_to_cpu(*pp); XFS_WANT_CORRUPTED_GOTO(mp, XFS_FSB_SANITY_CHECK(mp, bno), error0); xfs_trans_brelse(tp, bp); } /* * Here with bp and block set to the leftmost leaf node in the tree. */ room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); i = 0; /* * Loop over all leaf nodes. Copy information to the extent records. */ for (;;) { xfs_bmbt_rec_t *frp; xfs_fsblock_t nextbno; xfs_extnum_t num_recs; xfs_extnum_t start; num_recs = xfs_btree_get_numrecs(block); if (unlikely(i + num_recs > room)) { ASSERT(i + num_recs <= room); xfs_warn(ip->i_mount, "corrupt dinode %Lu, (btree extents).", (unsigned long long) ip->i_ino); XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)", XFS_ERRLEVEL_LOW, ip->i_mount, block); goto error0; } /* * Read-ahead the next leaf block, if any. */ nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); if (nextbno != NULLFSBLOCK) xfs_btree_reada_bufl(mp, nextbno, 1, &xfs_bmbt_buf_ops); /* * Copy records into the extent records. */ frp = XFS_BMBT_REC_ADDR(mp, block, 1); start = i; for (j = 0; j < num_recs; j++, i++, frp++) { xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i); trp->l0 = be64_to_cpu(frp->l0); trp->l1 = be64_to_cpu(frp->l1); } if (exntf == XFS_EXTFMT_NOSTATE) { /* * Check all attribute bmap btree records and * any "older" data bmap btree records for a * set bit in the "extent flag" position. */ if (unlikely(xfs_check_nostate_extents(ifp, start, num_recs))) { XFS_ERROR_REPORT("xfs_bmap_read_extents(2)", XFS_ERRLEVEL_LOW, ip->i_mount); goto error0; } } xfs_trans_brelse(tp, bp); bno = nextbno; /* * If we've reached the end, stop. */ if (bno == NULLFSBLOCK) break; error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops); if (error) return error; block = XFS_BUF_TO_BLOCK(bp); } ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))); ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork)); XFS_BMAP_TRACE_EXLIST(ip, i, whichfork); return 0; error0: xfs_trans_brelse(tp, bp); return -EFSCORRUPTED; } /* * Search the extent records for the entry containing block bno. * If bno lies in a hole, point to the next entry. If bno lies * past eof, *eofp will be set, and *prevp will contain the last * entry (null if none). Else, *lastxp will be set to the index * of the found entry; *gotp will contain the entry. */ STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */ xfs_bmap_search_multi_extents( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_fileoff_t bno, /* block number searched for */ int *eofp, /* out: end of file found */ xfs_extnum_t *lastxp, /* out: last extent index */ xfs_bmbt_irec_t *gotp, /* out: extent entry found */ xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ { xfs_bmbt_rec_host_t *ep; /* extent record pointer */ xfs_extnum_t lastx; /* last extent index */ /* * Initialize the extent entry structure to catch access to * uninitialized br_startblock field. */ gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL; gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL; gotp->br_state = XFS_EXT_INVALID; gotp->br_startblock = 0xffffa5a5a5a5a5a5LL; prevp->br_startoff = NULLFILEOFF; ep = xfs_iext_bno_to_ext(ifp, bno, &lastx); if (lastx > 0) { xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp); } if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) { xfs_bmbt_get_all(ep, gotp); *eofp = 0; } else { if (lastx > 0) { *gotp = *prevp; } *eofp = 1; ep = NULL; } *lastxp = lastx; return ep; } /* * Search the extents list for the inode, for the extent containing bno. * If bno lies in a hole, point to the next entry. If bno lies past eof, * *eofp will be set, and *prevp will contain the last entry (null if none). * Else, *lastxp will be set to the index of the found * entry; *gotp will contain the entry. */ xfs_bmbt_rec_host_t * /* pointer to found extent entry */ xfs_bmap_search_extents( xfs_inode_t *ip, /* incore inode pointer */ xfs_fileoff_t bno, /* block number searched for */ int fork, /* data or attr fork */ int *eofp, /* out: end of file found */ xfs_extnum_t *lastxp, /* out: last extent index */ xfs_bmbt_irec_t *gotp, /* out: extent entry found */ xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ { xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_rec_host_t *ep; /* extent record pointer */ XFS_STATS_INC(ip->i_mount, xs_look_exlist); ifp = XFS_IFORK_PTR(ip, fork); ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp); if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) && !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) { xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, "Access to block zero in inode %llu " "start_block: %llx start_off: %llx " "blkcnt: %llx extent-state: %x lastx: %x", (unsigned long long)ip->i_ino, (unsigned long long)gotp->br_startblock, (unsigned long long)gotp->br_startoff, (unsigned long long)gotp->br_blockcount, gotp->br_state, *lastxp); *lastxp = NULLEXTNUM; *eofp = 1; return NULL; } return ep; } /* * Returns the file-relative block number of the first unused block(s) * in the file with at least "len" logically contiguous blocks free. * This is the lowest-address hole if the file has holes, else the first block * past the end of file. * Return 0 if the file is currently local (in-inode). */ int /* error */ xfs_bmap_first_unused( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode */ xfs_extlen_t len, /* size of hole to find */ xfs_fileoff_t *first_unused, /* unused block */ int whichfork) /* data or attr fork */ { int error; /* error return value */ int idx; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_fileoff_t lastaddr; /* last block number seen */ xfs_fileoff_t lowest; /* lowest useful block */ xfs_fileoff_t max; /* starting useful block */ xfs_fileoff_t off; /* offset for this block */ xfs_extnum_t nextents; /* number of extent entries */ ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE || XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS || XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { *first_unused = 0; return 0; } ifp = XFS_IFORK_PTR(ip, whichfork); if (!(ifp->if_flags & XFS_IFEXTENTS) && (error = xfs_iread_extents(tp, ip, whichfork))) return error; lowest = *first_unused; nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) { xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx); off = xfs_bmbt_get_startoff(ep); /* * See if the hole before this extent will work. */ if (off >= lowest + len && off - max >= len) { *first_unused = max; return 0; } lastaddr = off + xfs_bmbt_get_blockcount(ep); max = XFS_FILEOFF_MAX(lastaddr, lowest); } *first_unused = max; return 0; } /* * Returns the file-relative block number of the last block - 1 before * last_block (input value) in the file. * This is not based on i_size, it is based on the extent records. * Returns 0 for local files, as they do not have extent records. */ int /* error */ xfs_bmap_last_before( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode */ xfs_fileoff_t *last_block, /* last block */ int whichfork) /* data or attr fork */ { xfs_fileoff_t bno; /* input file offset */ int eof; /* hit end of file */ xfs_bmbt_rec_host_t *ep; /* pointer to last extent */ int error; /* error return value */ xfs_bmbt_irec_t got; /* current extent value */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_extnum_t lastx; /* last extent used */ xfs_bmbt_irec_t prev; /* previous extent value */ if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL) return -EIO; if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { *last_block = 0; return 0; } ifp = XFS_IFORK_PTR(ip, whichfork); if (!(ifp->if_flags & XFS_IFEXTENTS) && (error = xfs_iread_extents(tp, ip, whichfork))) return error; bno = *last_block - 1; ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); if (eof || xfs_bmbt_get_startoff(ep) > bno) { if (prev.br_startoff == NULLFILEOFF) *last_block = 0; else *last_block = prev.br_startoff + prev.br_blockcount; } /* * Otherwise *last_block is already the right answer. */ return 0; } int xfs_bmap_last_extent( struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *rec, int *is_empty) { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); int error; int nextents; if (!(ifp->if_flags & XFS_IFEXTENTS)) { error = xfs_iread_extents(tp, ip, whichfork); if (error) return error; } nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); if (nextents == 0) { *is_empty = 1; return 0; } xfs_bmbt_get_all(xfs_iext_get_ext(ifp, nextents - 1), rec); *is_empty = 0; return 0; } /* * Check the last inode extent to determine whether this allocation will result * in blocks being allocated at the end of the file. When we allocate new data * blocks at the end of the file which do not start at the previous data block, * we will try to align the new blocks at stripe unit boundaries. * * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be * at, or past the EOF. */ STATIC int xfs_bmap_isaeof( struct xfs_bmalloca *bma, int whichfork) { struct xfs_bmbt_irec rec; int is_empty; int error; bma->aeof = 0; error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec, &is_empty); if (error) return error; if (is_empty) { bma->aeof = 1; return 0; } /* * Check if we are allocation or past the last extent, or at least into * the last delayed allocated extent. */ bma->aeof = bma->offset >= rec.br_startoff + rec.br_blockcount || (bma->offset >= rec.br_startoff && isnullstartblock(rec.br_startblock)); return 0; } /* * Returns the file-relative block number of the first block past eof in * the file. This is not based on i_size, it is based on the extent records. * Returns 0 for local files, as they do not have extent records. */ int xfs_bmap_last_offset( struct xfs_inode *ip, xfs_fileoff_t *last_block, int whichfork) { struct xfs_bmbt_irec rec; int is_empty; int error; *last_block = 0; if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) return 0; if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) return -EIO; error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty); if (error || is_empty) return error; *last_block = rec.br_startoff + rec.br_blockcount; return 0; } /* * Returns whether the selected fork of the inode has exactly one * block or not. For the data fork we check this matches di_size, * implying the file's range is 0..bsize-1. */ int /* 1=>1 block, 0=>otherwise */ xfs_bmap_one_block( xfs_inode_t *ip, /* incore inode */ int whichfork) /* data or attr fork */ { xfs_bmbt_rec_host_t *ep; /* ptr to fork's extent */ xfs_ifork_t *ifp; /* inode fork pointer */ int rval; /* return value */ xfs_bmbt_irec_t s; /* internal version of extent */ #ifndef DEBUG if (whichfork == XFS_DATA_FORK) return XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize; #endif /* !DEBUG */ if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1) return 0; if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) return 0; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(ifp->if_flags & XFS_IFEXTENTS); ep = xfs_iext_get_ext(ifp, 0); xfs_bmbt_get_all(ep, &s); rval = s.br_startoff == 0 && s.br_blockcount == 1; if (rval && whichfork == XFS_DATA_FORK) ASSERT(XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize); return rval; } /* * Extent tree manipulation functions used during allocation. */ /* * Convert a delayed allocation to a real allocation. */ STATIC int /* error */ xfs_bmap_add_extent_delay_real( struct xfs_bmalloca *bma, int whichfork) { struct xfs_bmbt_irec *new = &bma->got; int diff; /* temp value */ xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ int error; /* error return value */ int i; /* temp state */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_fileoff_t new_endoff; /* end offset of new entry */ xfs_bmbt_irec_t r[3]; /* neighbor extent entries */ /* left is 0, right is 1, prev is 2 */ int rval=0; /* return value (logging flags) */ int state = 0;/* state bits, accessed thru macros */ xfs_filblks_t da_new; /* new count del alloc blocks used */ xfs_filblks_t da_old; /* old count del alloc blocks used */ xfs_filblks_t temp=0; /* value for da_new calculations */ xfs_filblks_t temp2=0;/* value for da_new calculations */ int tmp_rval; /* partial logging flags */ struct xfs_mount *mp; xfs_extnum_t *nextents; mp = bma->ip->i_mount; ifp = XFS_IFORK_PTR(bma->ip, whichfork); ASSERT(whichfork != XFS_ATTR_FORK); nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents : &bma->ip->i_d.di_nextents); ASSERT(bma->idx >= 0); ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); ASSERT(!isnullstartblock(new->br_startblock)); ASSERT(!bma->cur || (bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); XFS_STATS_INC(mp, xs_add_exlist); #define LEFT r[0] #define RIGHT r[1] #define PREV r[2] if (whichfork == XFS_COW_FORK) state |= BMAP_COWFORK; /* * Set up a bunch of variables to make the tests simpler. */ ep = xfs_iext_get_ext(ifp, bma->idx); xfs_bmbt_get_all(ep, &PREV); new_endoff = new->br_startoff + new->br_blockcount; ASSERT(PREV.br_startoff <= new->br_startoff); ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); da_old = startblockval(PREV.br_startblock); da_new = 0; /* * Set flags determining what part of the previous delayed allocation * extent is being replaced by a real allocation. */ if (PREV.br_startoff == new->br_startoff) state |= BMAP_LEFT_FILLING; if (PREV.br_startoff + PREV.br_blockcount == new_endoff) state |= BMAP_RIGHT_FILLING; /* * Check and set flags if this segment has a left neighbor. * Don't set contiguous if the combined extent would be too large. */ if (bma->idx > 0) { state |= BMAP_LEFT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &LEFT); if (isnullstartblock(LEFT.br_startblock)) state |= BMAP_LEFT_DELAY; } if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) && LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff && LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock && LEFT.br_state == new->br_state && LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN) state |= BMAP_LEFT_CONTIG; /* * Check and set flags if this segment has a right neighbor. * Don't set contiguous if the combined extent would be too large. * Also check for all-three-contiguous being too large. */ if (bma->idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { state |= BMAP_RIGHT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx + 1), &RIGHT); if (isnullstartblock(RIGHT.br_startblock)) state |= BMAP_RIGHT_DELAY; } if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) && new_endoff == RIGHT.br_startoff && new->br_startblock + new->br_blockcount == RIGHT.br_startblock && new->br_state == RIGHT.br_state && new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN && ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING)) != (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING) || LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN)) state |= BMAP_RIGHT_CONTIG; error = 0; /* * Switch out based on the FILLING and CONTIG state bits. */ switch (state & (BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG)) { case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: /* * Filling in all of a previously delayed allocation extent. * The left and right neighbors are both contiguous with new. */ bma->idx--; trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_iext_remove(bma->ip, bma->idx + 1, 2, state); (*nextents)--; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, RIGHT.br_startblock, RIGHT.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_delete(bma->cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_decrement(bma->cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount, LEFT.br_state); if (error) goto done; } break; case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: /* * Filling in all of a previously delayed allocation extent. * The left neighbor is contiguous, the right is not. */ bma->idx--; trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), LEFT.br_blockcount + PREV.br_blockcount); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); if (bma->cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + PREV.br_blockcount, LEFT.br_state); if (error) goto done; } break; case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: /* * Filling in all of a previously delayed allocation extent. * The right neighbor is contiguous, the left is not. */ trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, new->br_startblock); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount + RIGHT.br_blockcount); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); if (bma->cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, RIGHT.br_startblock, RIGHT.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, PREV.br_startoff, new->br_startblock, PREV.br_blockcount + RIGHT.br_blockcount, PREV.br_state); if (error) goto done; } break; case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: /* * Filling in all of a previously delayed allocation extent. * Neither the left nor right neighbors are contiguous with * the new one. */ trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, new->br_startblock); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; error = xfs_btree_insert(bma->cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } break; case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: /* * Filling in the first part of a previous delayed allocation. * The left neighbor is contiguous. */ trace_xfs_bmap_pre_update(bma->ip, bma->idx - 1, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx - 1), LEFT.br_blockcount + new->br_blockcount); xfs_bmbt_set_startoff(ep, PREV.br_startoff + new->br_blockcount); trace_xfs_bmap_post_update(bma->ip, bma->idx - 1, state, _THIS_IP_); temp = PREV.br_blockcount - new->br_blockcount; trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); if (bma->cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + new->br_blockcount, LEFT.br_state); if (error) goto done; } da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), startblockval(PREV.br_startblock)); xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); bma->idx--; break; case BMAP_LEFT_FILLING: /* * Filling in the first part of a previous delayed allocation. * The left neighbor is not contiguous. */ trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_startoff(ep, new_endoff); temp = PREV.br_blockcount - new->br_blockcount; xfs_bmbt_set_blockcount(ep, temp); xfs_iext_insert(bma->ip, bma->idx, 1, new, state); (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; error = xfs_btree_insert(bma->cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) goto done; } da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), startblockval(PREV.br_startblock) - (bma->cur ? bma->cur->bc_private.b.allocated : 0)); ep = xfs_iext_get_ext(ifp, bma->idx + 1); xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_); break; case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: /* * Filling in the last part of a previous delayed allocation. * The right neighbor is contiguous with the new allocation. */ temp = PREV.br_blockcount - new->br_blockcount; trace_xfs_bmap_pre_update(bma->ip, bma->idx + 1, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx + 1), new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, RIGHT.br_state); trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_); if (bma->cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, RIGHT.br_startblock, RIGHT.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, RIGHT.br_state); if (error) goto done; } da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), startblockval(PREV.br_startblock)); trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); bma->idx++; break; case BMAP_RIGHT_FILLING: /* * Filling in the last part of a previous delayed allocation. * The right neighbor is not contiguous. */ temp = PREV.br_blockcount - new->br_blockcount; trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state); (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; error = xfs_btree_insert(bma->cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) goto done; } da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), startblockval(PREV.br_startblock) - (bma->cur ? bma->cur->bc_private.b.allocated : 0)); ep = xfs_iext_get_ext(ifp, bma->idx); xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); bma->idx++; break; case 0: /* * Filling in the middle part of a previous delayed allocation. * Contiguity is impossible here. * This case is avoided almost all the time. * * We start with a delayed allocation: * * +ddddddddddddddddddddddddddddddddddddddddddddddddddddddd+ * PREV @ idx * * and we are allocating: * +rrrrrrrrrrrrrrrrr+ * new * * and we set it up for insertion as: * +ddddddddddddddddddd+rrrrrrrrrrrrrrrrr+ddddddddddddddddd+ * new * PREV @ idx LEFT RIGHT * inserted at idx + 1 */ temp = new->br_startoff - PREV.br_startoff; temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; trace_xfs_bmap_pre_update(bma->ip, bma->idx, 0, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ LEFT = *new; RIGHT.br_state = PREV.br_state; RIGHT.br_startblock = nullstartblock( (int)xfs_bmap_worst_indlen(bma->ip, temp2)); RIGHT.br_startoff = new_endoff; RIGHT.br_blockcount = temp2; /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state); (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; error = xfs_btree_insert(bma->cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) goto done; } temp = xfs_bmap_worst_indlen(bma->ip, temp); temp2 = xfs_bmap_worst_indlen(bma->ip, temp2); diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - (bma->cur ? bma->cur->bc_private.b.allocated : 0)); if (diff > 0) { error = xfs_mod_fdblocks(bma->ip->i_mount, -((int64_t)diff), false); ASSERT(!error); if (error) goto done; } ep = xfs_iext_get_ext(ifp, bma->idx); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); trace_xfs_bmap_pre_update(bma->ip, bma->idx + 2, state, _THIS_IP_); xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, bma->idx + 2), nullstartblock((int)temp2)); trace_xfs_bmap_post_update(bma->ip, bma->idx + 2, state, _THIS_IP_); bma->idx++; da_new = temp + temp2; break; case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: case BMAP_LEFT_FILLING | BMAP_RIGHT_CONTIG: case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: case BMAP_LEFT_CONTIG: case BMAP_RIGHT_CONTIG: /* * These cases are all impossible. */ ASSERT(0); } /* add reverse mapping */ error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new); if (error) goto done; /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(bma->ip, whichfork)) { int tmp_logflags; /* partial log flag return val */ ASSERT(bma->cur == NULL); error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, bma->firstblock, bma->dfops, &bma->cur, da_old > 0, &tmp_logflags, whichfork); bma->logflags |= tmp_logflags; if (error) goto done; } /* adjust for changes in reserved delayed indirect blocks */ if (da_old || da_new) { temp = da_new; if (bma->cur) temp += bma->cur->bc_private.b.allocated; ASSERT(temp <= da_old); if (temp < da_old) xfs_mod_fdblocks(bma->ip->i_mount, (int64_t)(da_old - temp), false); } /* clear out the allocated field, done with it now in any case. */ if (bma->cur) bma->cur->bc_private.b.allocated = 0; xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork); done: if (whichfork != XFS_COW_FORK) bma->logflags |= rval; return error; #undef LEFT #undef RIGHT #undef PREV } /* * Convert an unwritten allocation to a real allocation or vice versa. */ STATIC int /* error */ xfs_bmap_add_extent_unwritten_real( struct xfs_trans *tp, xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t *idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ struct xfs_defer_ops *dfops, /* list of extents to be freed */ int *logflagsp) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ int error; /* error return value */ int i; /* temp state */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_fileoff_t new_endoff; /* end offset of new entry */ xfs_exntst_t newext; /* new extent state */ xfs_exntst_t oldext; /* old extent state */ xfs_bmbt_irec_t r[3]; /* neighbor extent entries */ /* left is 0, right is 1, prev is 2 */ int rval=0; /* return value (logging flags) */ int state = 0;/* state bits, accessed thru macros */ struct xfs_mount *mp = tp->t_mountp; *logflagsp = 0; cur = *curp; ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); ASSERT(*idx >= 0); ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); ASSERT(!isnullstartblock(new->br_startblock)); XFS_STATS_INC(mp, xs_add_exlist); #define LEFT r[0] #define RIGHT r[1] #define PREV r[2] /* * Set up a bunch of variables to make the tests simpler. */ error = 0; ep = xfs_iext_get_ext(ifp, *idx); xfs_bmbt_get_all(ep, &PREV); newext = new->br_state; oldext = (newext == XFS_EXT_UNWRITTEN) ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; ASSERT(PREV.br_state == oldext); new_endoff = new->br_startoff + new->br_blockcount; ASSERT(PREV.br_startoff <= new->br_startoff); ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); /* * Set flags determining what part of the previous oldext allocation * extent is being replaced by a newext allocation. */ if (PREV.br_startoff == new->br_startoff) state |= BMAP_LEFT_FILLING; if (PREV.br_startoff + PREV.br_blockcount == new_endoff) state |= BMAP_RIGHT_FILLING; /* * Check and set flags if this segment has a left neighbor. * Don't set contiguous if the combined extent would be too large. */ if (*idx > 0) { state |= BMAP_LEFT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &LEFT); if (isnullstartblock(LEFT.br_startblock)) state |= BMAP_LEFT_DELAY; } if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) && LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff && LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock && LEFT.br_state == newext && LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN) state |= BMAP_LEFT_CONTIG; /* * Check and set flags if this segment has a right neighbor. * Don't set contiguous if the combined extent would be too large. * Also check for all-three-contiguous being too large. */ if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { state |= BMAP_RIGHT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT); if (isnullstartblock(RIGHT.br_startblock)) state |= BMAP_RIGHT_DELAY; } if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) && new_endoff == RIGHT.br_startoff && new->br_startblock + new->br_blockcount == RIGHT.br_startblock && newext == RIGHT.br_state && new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN && ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING)) != (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING) || LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN)) state |= BMAP_RIGHT_CONTIG; /* * Switch out based on the FILLING and CONTIG state bits. */ switch (state & (BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG)) { case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The left and right neighbors are both contiguous with new. */ --*idx; trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); xfs_iext_remove(ip, *idx + 1, 2, state); ip->i_d.di_nextents -= 2; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, RIGHT.br_startblock, RIGHT.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_delete(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_delete(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount, LEFT.br_state))) goto done; } break; case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The left neighbor is contiguous, the right is not. */ --*idx; trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), LEFT.br_blockcount + PREV.br_blockcount); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); xfs_iext_remove(ip, *idx + 1, 1, state); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_delete(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + PREV.br_blockcount, LEFT.br_state))) goto done; } break; case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The right neighbor is contiguous, the left is not. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount + RIGHT.br_blockcount); xfs_bmbt_set_state(ep, newext); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); xfs_iext_remove(ip, *idx + 1, 1, state); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, RIGHT.br_startblock, RIGHT.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_delete(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext))) goto done; } break; case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: /* * Setting all of a previous oldext extent to newext. * Neither the left nor right neighbors are contiguous with * the new one. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_state(ep, newext); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); if (cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, new->br_startoff, new->br_startblock, new->br_blockcount, newext))) goto done; } break; case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is contiguous. */ trace_xfs_bmap_pre_update(ip, *idx - 1, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx - 1), LEFT.br_blockcount + new->br_blockcount); xfs_bmbt_set_startoff(ep, PREV.br_startoff + new->br_blockcount); trace_xfs_bmap_post_update(ip, *idx - 1, state, _THIS_IP_); trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, new->br_startblock + new->br_blockcount); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); --*idx; if (cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, PREV.br_startoff + new->br_blockcount, PREV.br_startblock + new->br_blockcount, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; error = xfs_bmbt_update(cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + new->br_blockcount, LEFT.br_state); if (error) goto done; } break; case BMAP_LEFT_FILLING: /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is not contiguous. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); ASSERT(ep && xfs_bmbt_get_state(ep) == oldext); xfs_bmbt_set_startoff(ep, new_endoff); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); xfs_bmbt_set_startblock(ep, new->br_startblock + new->br_blockcount); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); xfs_iext_insert(ip, *idx, 1, new, state); ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, PREV.br_startoff + new->br_blockcount, PREV.br_startblock + new->br_blockcount, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; cur->bc_rec.b = *new; if ((error = xfs_btree_insert(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } break; case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is contiguous with the new allocation. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); ++*idx; trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); if (cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; if ((error = xfs_btree_increment(cur, 0, &i))) goto done; if ((error = xfs_bmbt_update(cur, new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext))) goto done; } break; case BMAP_RIGHT_FILLING: /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is not contiguous. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); ++*idx; xfs_iext_insert(ip, *idx, 1, new, state); ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); if ((error = xfs_bmbt_update(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); cur->bc_rec.b.br_state = XFS_EXT_NORM; if ((error = xfs_btree_insert(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } break; case 0: /* * Setting the middle part of a previous oldext extent to * newext. Contiguity is impossible here. * One extent becomes three extents. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, new->br_startoff - PREV.br_startoff); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); r[0] = *new; r[1].br_startoff = new_endoff; r[1].br_blockcount = PREV.br_startoff + PREV.br_blockcount - new_endoff; r[1].br_startblock = new->br_startblock + new->br_blockcount; r[1].br_state = oldext; ++*idx; xfs_iext_insert(ip, *idx, 2, &r[0], state); ip->i_d.di_nextents += 2; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); /* new right extent - oldext */ if ((error = xfs_bmbt_update(cur, r[1].br_startoff, r[1].br_startblock, r[1].br_blockcount, r[1].br_state))) goto done; /* new left extent - oldext */ cur->bc_rec.b = PREV; cur->bc_rec.b.br_blockcount = new->br_startoff - PREV.br_startoff; if ((error = xfs_btree_insert(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); /* * Reset the cursor to the position of the new extent * we are about to insert as we can't trust it after * the previous insert. */ if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); /* new middle extent - newext */ cur->bc_rec.b.br_state = new->br_state; if ((error = xfs_btree_insert(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } break; case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: case BMAP_LEFT_FILLING | BMAP_RIGHT_CONTIG: case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: case BMAP_LEFT_CONTIG: case BMAP_RIGHT_CONTIG: /* * These cases are all impossible. */ ASSERT(0); } /* update reverse mappings */ error = xfs_rmap_convert_extent(mp, dfops, ip, XFS_DATA_FORK, new); if (error) goto done; /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) { int tmp_logflags; /* partial log flag return val */ ASSERT(cur == NULL); error = xfs_bmap_extents_to_btree(tp, ip, first, dfops, &cur, 0, &tmp_logflags, XFS_DATA_FORK); *logflagsp |= tmp_logflags; if (error) goto done; } /* clear out the allocated field, done with it now in any case. */ if (cur) { cur->bc_private.b.allocated = 0; *curp = cur; } xfs_bmap_check_leaf_extents(*curp, ip, XFS_DATA_FORK); done: *logflagsp |= rval; return error; #undef LEFT #undef RIGHT #undef PREV } /* * Convert a hole to a delayed allocation. */ STATIC void xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ int whichfork, xfs_extnum_t *idx, /* extent number to update/insert */ xfs_bmbt_irec_t *new) /* new data to add to file extents */ { xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_irec_t left; /* left neighbor extent entry */ xfs_filblks_t newlen=0; /* new indirect size */ xfs_filblks_t oldlen=0; /* old indirect size */ xfs_bmbt_irec_t right; /* right neighbor extent entry */ int state; /* state bits, accessed thru macros */ xfs_filblks_t temp=0; /* temp for indirect calculations */ ifp = XFS_IFORK_PTR(ip, whichfork); state = 0; if (whichfork == XFS_COW_FORK) state |= BMAP_COWFORK; ASSERT(isnullstartblock(new->br_startblock)); /* * Check and set flags if this segment has a left neighbor */ if (*idx > 0) { state |= BMAP_LEFT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &left); if (isnullstartblock(left.br_startblock)) state |= BMAP_LEFT_DELAY; } /* * Check and set flags if the current (right) segment exists. * If it doesn't exist, we're converting the hole at end-of-file. */ if (*idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { state |= BMAP_RIGHT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right); if (isnullstartblock(right.br_startblock)) state |= BMAP_RIGHT_DELAY; } /* * Set contiguity flags on the left and right neighbors. * Don't let extents get too large, even if the pieces are contiguous. */ if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) && left.br_startoff + left.br_blockcount == new->br_startoff && left.br_blockcount + new->br_blockcount <= MAXEXTLEN) state |= BMAP_LEFT_CONTIG; if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) && new->br_startoff + new->br_blockcount == right.br_startoff && new->br_blockcount + right.br_blockcount <= MAXEXTLEN && (!(state & BMAP_LEFT_CONTIG) || (left.br_blockcount + new->br_blockcount + right.br_blockcount <= MAXEXTLEN))) state |= BMAP_RIGHT_CONTIG; /* * Switch out based on the contiguity flags. */ switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) { case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: /* * New allocation is contiguous with delayed allocations * on the left and on the right. * Merge all three into a single extent record. */ --*idx; temp = left.br_blockcount + new->br_blockcount + right.br_blockcount; trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp); oldlen = startblockval(left.br_startblock) + startblockval(new->br_startblock) + startblockval(right.br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), nullstartblock((int)newlen)); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); xfs_iext_remove(ip, *idx + 1, 1, state); break; case BMAP_LEFT_CONTIG: /* * New allocation is contiguous with a delayed allocation * on the left. * Merge the new allocation with the left neighbor. */ --*idx; temp = left.br_blockcount + new->br_blockcount; trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp); oldlen = startblockval(left.br_startblock) + startblockval(new->br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), nullstartblock((int)newlen)); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); break; case BMAP_RIGHT_CONTIG: /* * New allocation is contiguous with a delayed allocation * on the right. * Merge the new allocation with the right neighbor. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); temp = new->br_blockcount + right.br_blockcount; oldlen = startblockval(new->br_startblock) + startblockval(right.br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), new->br_startoff, nullstartblock((int)newlen), temp, right.br_state); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); break; case 0: /* * New allocation is not contiguous with another * delayed allocation. * Insert a new entry. */ oldlen = newlen = 0; xfs_iext_insert(ip, *idx, 1, new, state); break; } if (oldlen != newlen) { ASSERT(oldlen > newlen); xfs_mod_fdblocks(ip->i_mount, (int64_t)(oldlen - newlen), false); /* * Nothing to do for disk quota accounting here. */ } } /* * Convert a hole to a real allocation. */ STATIC int /* error */ xfs_bmap_add_extent_hole_real( struct xfs_bmalloca *bma, int whichfork) { struct xfs_bmbt_irec *new = &bma->got; int error; /* error return value */ int i; /* temp state */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_irec_t left; /* left neighbor extent entry */ xfs_bmbt_irec_t right; /* right neighbor extent entry */ int rval=0; /* return value (logging flags) */ int state; /* state bits, accessed thru macros */ struct xfs_mount *mp; mp = bma->ip->i_mount; ifp = XFS_IFORK_PTR(bma->ip, whichfork); ASSERT(bma->idx >= 0); ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); ASSERT(!isnullstartblock(new->br_startblock)); ASSERT(!bma->cur || !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); ASSERT(whichfork != XFS_COW_FORK); XFS_STATS_INC(mp, xs_add_exlist); state = 0; if (whichfork == XFS_ATTR_FORK) state |= BMAP_ATTRFORK; /* * Check and set flags if this segment has a left neighbor. */ if (bma->idx > 0) { state |= BMAP_LEFT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &left); if (isnullstartblock(left.br_startblock)) state |= BMAP_LEFT_DELAY; } /* * Check and set flags if this segment has a current value. * Not true if we're inserting into the "hole" at eof. */ if (bma->idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { state |= BMAP_RIGHT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &right); if (isnullstartblock(right.br_startblock)) state |= BMAP_RIGHT_DELAY; } /* * We're inserting a real allocation between "left" and "right". * Set the contiguity flags. Don't let extents get too large. */ if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) && left.br_startoff + left.br_blockcount == new->br_startoff && left.br_startblock + left.br_blockcount == new->br_startblock && left.br_state == new->br_state && left.br_blockcount + new->br_blockcount <= MAXEXTLEN) state |= BMAP_LEFT_CONTIG; if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) && new->br_startoff + new->br_blockcount == right.br_startoff && new->br_startblock + new->br_blockcount == right.br_startblock && new->br_state == right.br_state && new->br_blockcount + right.br_blockcount <= MAXEXTLEN && (!(state & BMAP_LEFT_CONTIG) || left.br_blockcount + new->br_blockcount + right.br_blockcount <= MAXEXTLEN)) state |= BMAP_RIGHT_CONTIG; error = 0; /* * Select which case we're in here, and implement it. */ switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) { case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: /* * New allocation is contiguous with real allocations on the * left and on the right. * Merge all three into a single extent record. */ --bma->idx; trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), left.br_blockcount + new->br_blockcount + right.br_blockcount); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); XFS_IFORK_NEXT_SET(bma->ip, whichfork, XFS_IFORK_NEXTENTS(bma->ip, whichfork) - 1); if (bma->cur == NULL) { rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); } else { rval = XFS_ILOG_CORE; error = xfs_bmbt_lookup_eq(bma->cur, right.br_startoff, right.br_startblock, right.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_delete(bma->cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_decrement(bma->cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, left.br_startoff, left.br_startblock, left.br_blockcount + new->br_blockcount + right.br_blockcount, left.br_state); if (error) goto done; } break; case BMAP_LEFT_CONTIG: /* * New allocation is contiguous with a real allocation * on the left. * Merge the new allocation with the left neighbor. */ --bma->idx; trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), left.br_blockcount + new->br_blockcount); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); if (bma->cur == NULL) { rval = xfs_ilog_fext(whichfork); } else { rval = 0; error = xfs_bmbt_lookup_eq(bma->cur, left.br_startoff, left.br_startblock, left.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, left.br_startoff, left.br_startblock, left.br_blockcount + new->br_blockcount, left.br_state); if (error) goto done; } break; case BMAP_RIGHT_CONTIG: /* * New allocation is contiguous with a real allocation * on the right. * Merge the new allocation with the right neighbor. */ trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx), new->br_startoff, new->br_startblock, new->br_blockcount + right.br_blockcount, right.br_state); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); if (bma->cur == NULL) { rval = xfs_ilog_fext(whichfork); } else { rval = 0; error = xfs_bmbt_lookup_eq(bma->cur, right.br_startoff, right.br_startblock, right.br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_bmbt_update(bma->cur, new->br_startoff, new->br_startblock, new->br_blockcount + right.br_blockcount, right.br_state); if (error) goto done; } break; case 0: /* * New allocation is not contiguous with another * real allocation. * Insert a new entry. */ xfs_iext_insert(bma->ip, bma->idx, 1, new, state); XFS_IFORK_NEXT_SET(bma->ip, whichfork, XFS_IFORK_NEXTENTS(bma->ip, whichfork) + 1); if (bma->cur == NULL) { rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); } else { rval = XFS_ILOG_CORE; error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); bma->cur->bc_rec.b.br_state = new->br_state; error = xfs_btree_insert(bma->cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } break; } /* add reverse mapping */ error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new); if (error) goto done; /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(bma->ip, whichfork)) { int tmp_logflags; /* partial log flag return val */ ASSERT(bma->cur == NULL); error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, bma->firstblock, bma->dfops, &bma->cur, 0, &tmp_logflags, whichfork); bma->logflags |= tmp_logflags; if (error) goto done; } /* clear out the allocated field, done with it now in any case. */ if (bma->cur) bma->cur->bc_private.b.allocated = 0; xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork); done: bma->logflags |= rval; return error; } /* * Functions used in the extent read, allocate and remove paths */ /* * Adjust the size of the new extent based on di_extsize and rt extsize. */ int xfs_bmap_extsize_align( xfs_mount_t *mp, xfs_bmbt_irec_t *gotp, /* next extent pointer */ xfs_bmbt_irec_t *prevp, /* previous extent pointer */ xfs_extlen_t extsz, /* align to this extent size */ int rt, /* is this a realtime inode? */ int eof, /* is extent at end-of-file? */ int delay, /* creating delalloc extent? */ int convert, /* overwriting unwritten extent? */ xfs_fileoff_t *offp, /* in/out: aligned offset */ xfs_extlen_t *lenp) /* in/out: aligned length */ { xfs_fileoff_t orig_off; /* original offset */ xfs_extlen_t orig_alen; /* original length */ xfs_fileoff_t orig_end; /* original off+len */ xfs_fileoff_t nexto; /* next file offset */ xfs_fileoff_t prevo; /* previous file offset */ xfs_fileoff_t align_off; /* temp for offset */ xfs_extlen_t align_alen; /* temp for length */ xfs_extlen_t temp; /* temp for calculations */ if (convert) return 0; orig_off = align_off = *offp; orig_alen = align_alen = *lenp; orig_end = orig_off + orig_alen; /* * If this request overlaps an existing extent, then don't * attempt to perform any additional alignment. */ if (!delay && !eof && (orig_off >= gotp->br_startoff) && (orig_end <= gotp->br_startoff + gotp->br_blockcount)) { return 0; } /* * If the file offset is unaligned vs. the extent size * we need to align it. This will be possible unless * the file was previously written with a kernel that didn't * perform this alignment, or if a truncate shot us in the * foot. */ temp = do_mod(orig_off, extsz); if (temp) { align_alen += temp; align_off -= temp; } /* Same adjustment for the end of the requested area. */ temp = (align_alen % extsz); if (temp) align_alen += extsz - temp; /* * For large extent hint sizes, the aligned extent might be larger than * MAXEXTLEN. In that case, reduce the size by an extsz so that it pulls * the length back under MAXEXTLEN. The outer allocation loops handle * short allocation just fine, so it is safe to do this. We only want to * do it when we are forced to, though, because it means more allocation * operations are required. */ while (align_alen > MAXEXTLEN) align_alen -= extsz; ASSERT(align_alen <= MAXEXTLEN); /* * If the previous block overlaps with this proposed allocation * then move the start forward without adjusting the length. */ if (prevp->br_startoff != NULLFILEOFF) { if (prevp->br_startblock == HOLESTARTBLOCK) prevo = prevp->br_startoff; else prevo = prevp->br_startoff + prevp->br_blockcount; } else prevo = 0; if (align_off != orig_off && align_off < prevo) align_off = prevo; /* * If the next block overlaps with this proposed allocation * then move the start back without adjusting the length, * but not before offset 0. * This may of course make the start overlap previous block, * and if we hit the offset 0 limit then the next block * can still overlap too. */ if (!eof && gotp->br_startoff != NULLFILEOFF) { if ((delay && gotp->br_startblock == HOLESTARTBLOCK) || (!delay && gotp->br_startblock == DELAYSTARTBLOCK)) nexto = gotp->br_startoff + gotp->br_blockcount; else nexto = gotp->br_startoff; } else nexto = NULLFILEOFF; if (!eof && align_off + align_alen != orig_end && align_off + align_alen > nexto) align_off = nexto > align_alen ? nexto - align_alen : 0; /* * If we're now overlapping the next or previous extent that * means we can't fit an extsz piece in this hole. Just move * the start forward to the first valid spot and set * the length so we hit the end. */ if (align_off != orig_off && align_off < prevo) align_off = prevo; if (align_off + align_alen != orig_end && align_off + align_alen > nexto && nexto != NULLFILEOFF) { ASSERT(nexto > prevo); align_alen = nexto - align_off; } /* * If realtime, and the result isn't a multiple of the realtime * extent size we need to remove blocks until it is. */ if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) { /* * We're not covering the original request, or * we won't be able to once we fix the length. */ if (orig_off < align_off || orig_end > align_off + align_alen || align_alen - temp < orig_alen) return -EINVAL; /* * Try to fix it by moving the start up. */ if (align_off + temp <= orig_off) { align_alen -= temp; align_off += temp; } /* * Try to fix it by moving the end in. */ else if (align_off + align_alen - temp >= orig_end) align_alen -= temp; /* * Set the start to the minimum then trim the length. */ else { align_alen -= orig_off - align_off; align_off = orig_off; align_alen -= align_alen % mp->m_sb.sb_rextsize; } /* * Result doesn't cover the request, fail it. */ if (orig_off < align_off || orig_end > align_off + align_alen) return -EINVAL; } else { ASSERT(orig_off >= align_off); /* see MAXEXTLEN handling above */ ASSERT(orig_end <= align_off + align_alen || align_alen + extsz > MAXEXTLEN); } #ifdef DEBUG if (!eof && gotp->br_startoff != NULLFILEOFF) ASSERT(align_off + align_alen <= gotp->br_startoff); if (prevp->br_startoff != NULLFILEOFF) ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount); #endif *lenp = align_alen; *offp = align_off; return 0; } #define XFS_ALLOC_GAP_UNITS 4 void xfs_bmap_adjacent( struct xfs_bmalloca *ap) /* bmap alloc argument struct */ { xfs_fsblock_t adjust; /* adjustment to block numbers */ xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */ xfs_mount_t *mp; /* mount point structure */ int nullfb; /* true if ap->firstblock isn't set */ int rt; /* true if inode is realtime */ #define ISVALID(x,y) \ (rt ? \ (x) < mp->m_sb.sb_rblocks : \ XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \ XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \ XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) mp = ap->ip->i_mount; nullfb = *ap->firstblock == NULLFSBLOCK; rt = XFS_IS_REALTIME_INODE(ap->ip) && xfs_alloc_is_userdata(ap->datatype); fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); /* * If allocating at eof, and there's a previous real block, * try to use its last block as our starting point. */ if (ap->eof && ap->prev.br_startoff != NULLFILEOFF && !isnullstartblock(ap->prev.br_startblock) && ISVALID(ap->prev.br_startblock + ap->prev.br_blockcount, ap->prev.br_startblock)) { ap->blkno = ap->prev.br_startblock + ap->prev.br_blockcount; /* * Adjust for the gap between prevp and us. */ adjust = ap->offset - (ap->prev.br_startoff + ap->prev.br_blockcount); if (adjust && ISVALID(ap->blkno + adjust, ap->prev.br_startblock)) ap->blkno += adjust; } /* * If not at eof, then compare the two neighbor blocks. * Figure out whether either one gives us a good starting point, * and pick the better one. */ else if (!ap->eof) { xfs_fsblock_t gotbno; /* right side block number */ xfs_fsblock_t gotdiff=0; /* right side difference */ xfs_fsblock_t prevbno; /* left side block number */ xfs_fsblock_t prevdiff=0; /* left side difference */ /* * If there's a previous (left) block, select a requested * start block based on it. */ if (ap->prev.br_startoff != NULLFILEOFF && !isnullstartblock(ap->prev.br_startblock) && (prevbno = ap->prev.br_startblock + ap->prev.br_blockcount) && ISVALID(prevbno, ap->prev.br_startblock)) { /* * Calculate gap to end of previous block. */ adjust = prevdiff = ap->offset - (ap->prev.br_startoff + ap->prev.br_blockcount); /* * Figure the startblock based on the previous block's * end and the gap size. * Heuristic! * If the gap is large relative to the piece we're * allocating, or using it gives us an invalid block * number, then just use the end of the previous block. */ if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->length && ISVALID(prevbno + prevdiff, ap->prev.br_startblock)) prevbno += adjust; else prevdiff += adjust; /* * If the firstblock forbids it, can't use it, * must use default. */ if (!rt && !nullfb && XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno) prevbno = NULLFSBLOCK; } /* * No previous block or can't follow it, just default. */ else prevbno = NULLFSBLOCK; /* * If there's a following (right) block, select a requested * start block based on it. */ if (!isnullstartblock(ap->got.br_startblock)) { /* * Calculate gap to start of next block. */ adjust = gotdiff = ap->got.br_startoff - ap->offset; /* * Figure the startblock based on the next block's * start and the gap size. */ gotbno = ap->got.br_startblock; /* * Heuristic! * If the gap is large relative to the piece we're * allocating, or using it gives us an invalid block * number, then just use the start of the next block * offset by our length. */ if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->length && ISVALID(gotbno - gotdiff, gotbno)) gotbno -= adjust; else if (ISVALID(gotbno - ap->length, gotbno)) { gotbno -= ap->length; gotdiff += adjust - ap->length; } else gotdiff += adjust; /* * If the firstblock forbids it, can't use it, * must use default. */ if (!rt && !nullfb && XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno) gotbno = NULLFSBLOCK; } /* * No next block, just default. */ else gotbno = NULLFSBLOCK; /* * If both valid, pick the better one, else the only good * one, else ap->blkno is already set (to 0 or the inode block). */ if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK) ap->blkno = prevdiff <= gotdiff ? prevbno : gotbno; else if (prevbno != NULLFSBLOCK) ap->blkno = prevbno; else if (gotbno != NULLFSBLOCK) ap->blkno = gotbno; } #undef ISVALID } static int xfs_bmap_longest_free_extent( struct xfs_trans *tp, xfs_agnumber_t ag, xfs_extlen_t *blen, int *notinit) { struct xfs_mount *mp = tp->t_mountp; struct xfs_perag *pag; xfs_extlen_t longest; int error = 0; pag = xfs_perag_get(mp, ag); if (!pag->pagf_init) { error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK); if (error) goto out; if (!pag->pagf_init) { *notinit = 1; goto out; } } longest = xfs_alloc_longest_free_extent(mp, pag, xfs_alloc_min_freelist(mp, pag), xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE)); if (*blen < longest) *blen = longest; out: xfs_perag_put(pag); return error; } static void xfs_bmap_select_minlen( struct xfs_bmalloca *ap, struct xfs_alloc_arg *args, xfs_extlen_t *blen, int notinit) { if (notinit || *blen < ap->minlen) { /* * Since we did a BUF_TRYLOCK above, it is possible that * there is space for this request. */ args->minlen = ap->minlen; } else if (*blen < args->maxlen) { /* * If the best seen length is less than the request length, * use the best as the minimum. */ args->minlen = *blen; } else { /* * Otherwise we've seen an extent as big as maxlen, use that * as the minimum. */ args->minlen = args->maxlen; } } STATIC int xfs_bmap_btalloc_nullfb( struct xfs_bmalloca *ap, struct xfs_alloc_arg *args, xfs_extlen_t *blen) { struct xfs_mount *mp = ap->ip->i_mount; xfs_agnumber_t ag, startag; int notinit = 0; int error; args->type = XFS_ALLOCTYPE_START_BNO; args->total = ap->total; startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno); if (startag == NULLAGNUMBER) startag = ag = 0; while (*blen < args->maxlen) { error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; if (++ag == mp->m_sb.sb_agcount) ag = 0; if (ag == startag) break; } xfs_bmap_select_minlen(ap, args, blen, notinit); return 0; } STATIC int xfs_bmap_btalloc_filestreams( struct xfs_bmalloca *ap, struct xfs_alloc_arg *args, xfs_extlen_t *blen) { struct xfs_mount *mp = ap->ip->i_mount; xfs_agnumber_t ag; int notinit = 0; int error; args->type = XFS_ALLOCTYPE_NEAR_BNO; args->total = ap->total; ag = XFS_FSB_TO_AGNO(mp, args->fsbno); if (ag == NULLAGNUMBER) ag = 0; error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; if (*blen < args->maxlen) { error = xfs_filestream_new_ag(ap, &ag); if (error) return error; error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; } xfs_bmap_select_minlen(ap, args, blen, notinit); /* * Set the failure fallback case to look in the selected AG as stream * may have moved. */ ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); return 0; } STATIC int xfs_bmap_btalloc( struct xfs_bmalloca *ap) /* bmap alloc argument struct */ { xfs_mount_t *mp; /* mount point structure */ xfs_alloctype_t atype = 0; /* type for allocation routines */ xfs_extlen_t align = 0; /* minimum allocation alignment */ xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */ xfs_agnumber_t ag; xfs_alloc_arg_t args; xfs_extlen_t blen; xfs_extlen_t nextminlen = 0; int nullfb; /* true if ap->firstblock isn't set */ int isaligned; int tryagain; int error; int stripe_align; ASSERT(ap->length); mp = ap->ip->i_mount; /* stripe alignment for allocation is determined by mount parameters */ stripe_align = 0; if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC)) stripe_align = mp->m_swidth; else if (mp->m_dalign) stripe_align = mp->m_dalign; if (ap->flags & XFS_BMAPI_COWFORK) align = xfs_get_cowextsz_hint(ap->ip); else if (xfs_alloc_is_userdata(ap->datatype)) align = xfs_get_extsz_hint(ap->ip); if (unlikely(align)) { error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, align, 0, ap->eof, 0, ap->conv, &ap->offset, &ap->length); ASSERT(!error); ASSERT(ap->length); } nullfb = *ap->firstblock == NULLFSBLOCK; fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); if (nullfb) { if (xfs_alloc_is_userdata(ap->datatype) && xfs_inode_is_filestream(ap->ip)) { ag = xfs_filestream_lookup_ag(ap->ip); ag = (ag != NULLAGNUMBER) ? ag : 0; ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0); } else { ap->blkno = XFS_INO_TO_FSB(mp, ap->ip->i_ino); } } else ap->blkno = *ap->firstblock; xfs_bmap_adjacent(ap); /* * If allowed, use ap->blkno; otherwise must use firstblock since * it's in the right allocation group. */ if (nullfb || XFS_FSB_TO_AGNO(mp, ap->blkno) == fb_agno) ; else ap->blkno = *ap->firstblock; /* * Normal allocation, done through xfs_alloc_vextent. */ tryagain = isaligned = 0; memset(&args, 0, sizeof(args)); args.tp = ap->tp; args.mp = mp; args.fsbno = ap->blkno; xfs_rmap_skip_owner_update(&args.oinfo); /* Trim the allocation back to the maximum an AG can fit. */ args.maxlen = MIN(ap->length, mp->m_ag_max_usable); args.firstblock = *ap->firstblock; blen = 0; if (nullfb) { /* * Search for an allocation group with a single extent large * enough for the request. If one isn't found, then adjust * the minimum allocation size to the largest space found. */ if (xfs_alloc_is_userdata(ap->datatype) && xfs_inode_is_filestream(ap->ip)) error = xfs_bmap_btalloc_filestreams(ap, &args, &blen); else error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; } else if (ap->dfops->dop_low) { if (xfs_inode_is_filestream(ap->ip)) args.type = XFS_ALLOCTYPE_FIRST_AG; else args.type = XFS_ALLOCTYPE_START_BNO; args.total = args.minlen = ap->minlen; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; args.total = ap->total; args.minlen = ap->minlen; } /* apply extent size hints if obtained earlier */ if (unlikely(align)) { args.prod = align; if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod))) args.mod = (xfs_extlen_t)(args.prod - args.mod); } else if (mp->m_sb.sb_blocksize >= PAGE_SIZE) { args.prod = 1; args.mod = 0; } else { args.prod = PAGE_SIZE >> mp->m_sb.sb_blocklog; if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod)))) args.mod = (xfs_extlen_t)(args.prod - args.mod); } /* * If we are not low on available data blocks, and the * underlying logical volume manager is a stripe, and * the file offset is zero then try to allocate data * blocks on stripe unit boundary. * NOTE: ap->aeof is only set if the allocation length * is >= the stripe unit and the allocation offset is * at the end of file. */ if (!ap->dfops->dop_low && ap->aeof) { if (!ap->offset) { args.alignment = stripe_align; atype = args.type; isaligned = 1; /* * Adjust for alignment */ if (blen > args.alignment && blen <= args.maxlen) args.minlen = blen - args.alignment; args.minalignslop = 0; } else { /* * First try an exact bno allocation. * If it fails then do a near or start bno * allocation with alignment turned on. */ atype = args.type; tryagain = 1; args.type = XFS_ALLOCTYPE_THIS_BNO; args.alignment = 1; /* * Compute the minlen+alignment for the * next case. Set slop so that the value * of minlen+alignment+slop doesn't go up * between the calls. */ if (blen > stripe_align && blen <= args.maxlen) nextminlen = blen - stripe_align; else nextminlen = args.minlen; if (nextminlen + stripe_align > args.minlen + 1) args.minalignslop = nextminlen + stripe_align - args.minlen - 1; else args.minalignslop = 0; } } else { args.alignment = 1; args.minalignslop = 0; } args.minleft = ap->minleft; args.wasdel = ap->wasdel; args.resv = XFS_AG_RESV_NONE; args.datatype = ap->datatype; if (ap->datatype & XFS_ALLOC_USERDATA_ZERO) args.ip = ap->ip; error = xfs_alloc_vextent(&args); if (error) return error; if (tryagain && args.fsbno == NULLFSBLOCK) { /* * Exact allocation failed. Now try with alignment * turned on. */ args.type = atype; args.fsbno = ap->blkno; args.alignment = stripe_align; args.minlen = nextminlen; args.minalignslop = 0; isaligned = 1; if ((error = xfs_alloc_vextent(&args))) return error; } if (isaligned && args.fsbno == NULLFSBLOCK) { /* * allocation failed, so turn off alignment and * try again. */ args.type = atype; args.fsbno = ap->blkno; args.alignment = 0; if ((error = xfs_alloc_vextent(&args))) return error; } if (args.fsbno == NULLFSBLOCK && nullfb && args.minlen > ap->minlen) { args.minlen = ap->minlen; args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = ap->blkno; if ((error = xfs_alloc_vextent(&args))) return error; } if (args.fsbno == NULLFSBLOCK && nullfb) { args.fsbno = 0; args.type = XFS_ALLOCTYPE_FIRST_AG; args.total = ap->minlen; args.minleft = 0; if ((error = xfs_alloc_vextent(&args))) return error; ap->dfops->dop_low = true; } if (args.fsbno != NULLFSBLOCK) { /* * check the allocation happened at the same or higher AG than * the first block that was allocated. */ ASSERT(*ap->firstblock == NULLFSBLOCK || XFS_FSB_TO_AGNO(mp, *ap->firstblock) == XFS_FSB_TO_AGNO(mp, args.fsbno) || (ap->dfops->dop_low && XFS_FSB_TO_AGNO(mp, *ap->firstblock) < XFS_FSB_TO_AGNO(mp, args.fsbno))); ap->blkno = args.fsbno; if (*ap->firstblock == NULLFSBLOCK) *ap->firstblock = args.fsbno; ASSERT(nullfb || fb_agno == args.agno || (ap->dfops->dop_low && fb_agno < args.agno)); ap->length = args.len; if (!(ap->flags & XFS_BMAPI_COWFORK)) ap->ip->i_d.di_nblocks += args.len; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); if (ap->wasdel) ap->ip->i_delayed_blks -= args.len; /* * Adjust the disk quota also. This was reserved * earlier. */ xfs_trans_mod_dquot_byino(ap->tp, ap->ip, ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT : XFS_TRANS_DQ_BCOUNT, (long) args.len); } else { ap->blkno = NULLFSBLOCK; ap->length = 0; } return 0; } /* * For a remap operation, just "allocate" an extent at the address that the * caller passed in, and ensure that the AGFL is the right size. The caller * will then map the "allocated" extent into the file somewhere. */ STATIC int xfs_bmap_remap_alloc( struct xfs_bmalloca *ap) { struct xfs_trans *tp = ap->tp; struct xfs_mount *mp = tp->t_mountp; xfs_agblock_t bno; struct xfs_alloc_arg args; int error; /* * validate that the block number is legal - the enables us to detect * and handle a silent filesystem corruption rather than crashing. */ memset(&args, 0, sizeof(struct xfs_alloc_arg)); args.tp = ap->tp; args.mp = ap->tp->t_mountp; bno = *ap->firstblock; args.agno = XFS_FSB_TO_AGNO(mp, bno); args.agbno = XFS_FSB_TO_AGBNO(mp, bno); if (args.agno >= mp->m_sb.sb_agcount || args.agbno >= mp->m_sb.sb_agblocks) return -EFSCORRUPTED; /* "Allocate" the extent from the range we passed in. */ trace_xfs_bmap_remap_alloc(ap->ip, *ap->firstblock, ap->length); ap->blkno = bno; ap->ip->i_d.di_nblocks += ap->length; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); /* Fix the freelist, like a real allocator does. */ args.datatype = ap->datatype; args.pag = xfs_perag_get(args.mp, args.agno); ASSERT(args.pag); /* * The freelist fixing code will decline the allocation if * the size and shape of the free space doesn't allow for * allocating the extent and updating all the metadata that * happens during an allocation. We're remapping, not * allocating, so skip that check by pretending to be freeing. */ error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); xfs_perag_put(args.pag); if (error) trace_xfs_bmap_remap_alloc_error(ap->ip, error, _RET_IP_); return error; } /* * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. * It figures out where to ask the underlying allocator to put the new extent. */ STATIC int xfs_bmap_alloc( struct xfs_bmalloca *ap) /* bmap alloc argument struct */ { if (ap->flags & XFS_BMAPI_REMAP) return xfs_bmap_remap_alloc(ap); if (XFS_IS_REALTIME_INODE(ap->ip) && xfs_alloc_is_userdata(ap->datatype)) return xfs_bmap_rtalloc(ap); return xfs_bmap_btalloc(ap); } /* Trim extent to fit a logical block range. */ void xfs_trim_extent( struct xfs_bmbt_irec *irec, xfs_fileoff_t bno, xfs_filblks_t len) { xfs_fileoff_t distance; xfs_fileoff_t end = bno + len; if (irec->br_startoff + irec->br_blockcount <= bno || irec->br_startoff >= end) { irec->br_blockcount = 0; return; } if (irec->br_startoff < bno) { distance = bno - irec->br_startoff; if (isnullstartblock(irec->br_startblock)) irec->br_startblock = DELAYSTARTBLOCK; if (irec->br_startblock != DELAYSTARTBLOCK && irec->br_startblock != HOLESTARTBLOCK) irec->br_startblock += distance; irec->br_startoff += distance; irec->br_blockcount -= distance; } if (end < irec->br_startoff + irec->br_blockcount) { distance = irec->br_startoff + irec->br_blockcount - end; irec->br_blockcount -= distance; } } /* * Trim the returned map to the required bounds */ STATIC void xfs_bmapi_trim_map( struct xfs_bmbt_irec *mval, struct xfs_bmbt_irec *got, xfs_fileoff_t *bno, xfs_filblks_t len, xfs_fileoff_t obno, xfs_fileoff_t end, int n, int flags) { if ((flags & XFS_BMAPI_ENTIRE) || got->br_startoff + got->br_blockcount <= obno) { *mval = *got; if (isnullstartblock(got->br_startblock)) mval->br_startblock = DELAYSTARTBLOCK; return; } if (obno > *bno) *bno = obno; ASSERT((*bno >= obno) || (n == 0)); ASSERT(*bno < end); mval->br_startoff = *bno; if (isnullstartblock(got->br_startblock)) mval->br_startblock = DELAYSTARTBLOCK; else mval->br_startblock = got->br_startblock + (*bno - got->br_startoff); /* * Return the minimum of what we got and what we asked for for * the length. We can use the len variable here because it is * modified below and we could have been there before coming * here if the first part of the allocation didn't overlap what * was asked for. */ mval->br_blockcount = XFS_FILBLKS_MIN(end - *bno, got->br_blockcount - (*bno - got->br_startoff)); mval->br_state = got->br_state; ASSERT(mval->br_blockcount <= len); return; } /* * Update and validate the extent map to return */ STATIC void xfs_bmapi_update_map( struct xfs_bmbt_irec **map, xfs_fileoff_t *bno, xfs_filblks_t *len, xfs_fileoff_t obno, xfs_fileoff_t end, int *n, int flags) { xfs_bmbt_irec_t *mval = *map; ASSERT((flags & XFS_BMAPI_ENTIRE) || ((mval->br_startoff + mval->br_blockcount) <= end)); ASSERT((flags & XFS_BMAPI_ENTIRE) || (mval->br_blockcount <= *len) || (mval->br_startoff < obno)); *bno = mval->br_startoff + mval->br_blockcount; *len = end - *bno; if (*n > 0 && mval->br_startoff == mval[-1].br_startoff) { /* update previous map with new information */ ASSERT(mval->br_startblock == mval[-1].br_startblock); ASSERT(mval->br_blockcount > mval[-1].br_blockcount); ASSERT(mval->br_state == mval[-1].br_state); mval[-1].br_blockcount = mval->br_blockcount; mval[-1].br_state = mval->br_state; } else if (*n > 0 && mval->br_startblock != DELAYSTARTBLOCK && mval[-1].br_startblock != DELAYSTARTBLOCK && mval[-1].br_startblock != HOLESTARTBLOCK && mval->br_startblock == mval[-1].br_startblock + mval[-1].br_blockcount && ((flags & XFS_BMAPI_IGSTATE) || mval[-1].br_state == mval->br_state)) { ASSERT(mval->br_startoff == mval[-1].br_startoff + mval[-1].br_blockcount); mval[-1].br_blockcount += mval->br_blockcount; } else if (*n > 0 && mval->br_startblock == DELAYSTARTBLOCK && mval[-1].br_startblock == DELAYSTARTBLOCK && mval->br_startoff == mval[-1].br_startoff + mval[-1].br_blockcount) { mval[-1].br_blockcount += mval->br_blockcount; mval[-1].br_state = mval->br_state; } else if (!((*n == 0) && ((mval->br_startoff + mval->br_blockcount) <= obno))) { mval++; (*n)++; } *map = mval; } /* * Map file blocks to filesystem blocks without allocation. */ int xfs_bmapi_read( struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, struct xfs_bmbt_irec *mval, int *nmap, int flags) { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; struct xfs_bmbt_irec got; struct xfs_bmbt_irec prev; xfs_fileoff_t obno; xfs_fileoff_t end; xfs_extnum_t lastx; int error; int eof; int n = 0; int whichfork = xfs_bmapi_whichfork(flags); ASSERT(*nmap >= 1); ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE| XFS_BMAPI_IGSTATE|XFS_BMAPI_COWFORK))); ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)); if (unlikely(XFS_TEST_ERROR( (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; XFS_STATS_INC(mp, xs_blk_mapr); ifp = XFS_IFORK_PTR(ip, whichfork); /* No CoW fork? Return a hole. */ if (whichfork == XFS_COW_FORK && !ifp) { mval->br_startoff = bno; mval->br_startblock = HOLESTARTBLOCK; mval->br_blockcount = len; mval->br_state = XFS_EXT_NORM; *nmap = 1; return 0; } if (!(ifp->if_flags & XFS_IFEXTENTS)) { error = xfs_iread_extents(NULL, ip, whichfork); if (error) return error; } xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); end = bno + len; obno = bno; while (bno < end && n < *nmap) { /* Reading past eof, act as though there's a hole up to end. */ if (eof) got.br_startoff = end; if (got.br_startoff > bno) { /* Reading in a hole. */ mval->br_startoff = bno; mval->br_startblock = HOLESTARTBLOCK; mval->br_blockcount = XFS_FILBLKS_MIN(len, got.br_startoff - bno); mval->br_state = XFS_EXT_NORM; bno += mval->br_blockcount; len -= mval->br_blockcount; mval++; n++; continue; } /* set up the extent map to return. */ xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); /* If we're done, stop now. */ if (bno >= end || n >= *nmap) break; /* Else go on to the next record. */ if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got); else eof = 1; } *nmap = n; return 0; } int xfs_bmapi_reserve_delalloc( struct xfs_inode *ip, int whichfork, xfs_fileoff_t aoff, xfs_filblks_t len, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *prev, xfs_extnum_t *lastx, int eof) { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); xfs_extlen_t alen; xfs_extlen_t indlen; char rt = XFS_IS_REALTIME_INODE(ip); xfs_extlen_t extsz; int error; alen = XFS_FILBLKS_MIN(len, MAXEXTLEN); if (!eof) alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff); /* Figure out the extent size, adjust alen */ if (whichfork == XFS_COW_FORK) extsz = xfs_get_cowextsz_hint(ip); else extsz = xfs_get_extsz_hint(ip); if (extsz) { error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof, 1, 0, &aoff, &alen); ASSERT(!error); } if (rt) extsz = alen / mp->m_sb.sb_rextsize; /* * Make a transaction-less quota reservation for delayed allocation * blocks. This number gets adjusted later. We return if we haven't * allocated blocks already inside this loop. */ error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0, rt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); if (error) return error; /* * Split changing sb for alen and indlen since they could be coming * from different places. */ indlen = (xfs_extlen_t)xfs_bmap_worst_indlen(ip, alen); ASSERT(indlen > 0); if (rt) { error = xfs_mod_frextents(mp, -((int64_t)extsz)); } else { error = xfs_mod_fdblocks(mp, -((int64_t)alen), false); } if (error) goto out_unreserve_quota; error = xfs_mod_fdblocks(mp, -((int64_t)indlen), false); if (error) goto out_unreserve_blocks; ip->i_delayed_blks += alen; got->br_startoff = aoff; got->br_startblock = nullstartblock(indlen); got->br_blockcount = alen; got->br_state = XFS_EXT_NORM; xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got); /* * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay * might have merged it into one of the neighbouring ones. */ xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got); ASSERT(got->br_startoff <= aoff); ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen); ASSERT(isnullstartblock(got->br_startblock)); ASSERT(got->br_state == XFS_EXT_NORM); return 0; out_unreserve_blocks: if (rt) xfs_mod_frextents(mp, extsz); else xfs_mod_fdblocks(mp, alen, false); out_unreserve_quota: if (XFS_IS_QUOTA_ON(mp)) xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); return error; } static int xfs_bmapi_allocate( struct xfs_bmalloca *bma) { struct xfs_mount *mp = bma->ip->i_mount; int whichfork = xfs_bmapi_whichfork(bma->flags); struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); int tmp_logflags = 0; int error; ASSERT(bma->length > 0); /* * For the wasdelay case, we could also just allocate the stuff asked * for in this bmap call but that wouldn't be as good. */ if (bma->wasdel) { bma->length = (xfs_extlen_t)bma->got.br_blockcount; bma->offset = bma->got.br_startoff; if (bma->idx != NULLEXTNUM && bma->idx) { xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &bma->prev); } } else { bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN); if (!bma->eof) bma->length = XFS_FILBLKS_MIN(bma->length, bma->got.br_startoff - bma->offset); } /* * Set the data type being allocated. For the data fork, the first data * in the file is treated differently to all other allocations. For the * attribute fork, we only need to ensure the allocated range is not on * the busy list. */ if (!(bma->flags & XFS_BMAPI_METADATA)) { bma->datatype = XFS_ALLOC_NOBUSY; if (whichfork == XFS_DATA_FORK) { if (bma->offset == 0) bma->datatype |= XFS_ALLOC_INITIAL_USER_DATA; else bma->datatype |= XFS_ALLOC_USERDATA; } if (bma->flags & XFS_BMAPI_ZERO) bma->datatype |= XFS_ALLOC_USERDATA_ZERO; } bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1; /* * Only want to do the alignment at the eof if it is userdata and * allocation length is larger than a stripe unit. */ if (mp->m_dalign && bma->length >= mp->m_dalign && !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { error = xfs_bmap_isaeof(bma, whichfork); if (error) return error; } error = xfs_bmap_alloc(bma); if (error) return error; if (bma->dfops->dop_low) bma->minleft = 0; if (bma->cur) bma->cur->bc_private.b.firstblock = *bma->firstblock; if (bma->blkno == NULLFSBLOCK) return 0; if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork); bma->cur->bc_private.b.firstblock = *bma->firstblock; bma->cur->bc_private.b.dfops = bma->dfops; } /* * Bump the number of extents we've allocated * in this call. */ bma->nallocs++; if (bma->cur) bma->cur->bc_private.b.flags = bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0; bma->got.br_startoff = bma->offset; bma->got.br_startblock = bma->blkno; bma->got.br_blockcount = bma->length; bma->got.br_state = XFS_EXT_NORM; /* * A wasdelay extent has been initialized, so shouldn't be flagged * as unwritten. */ if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) && xfs_sb_version_hasextflgbit(&mp->m_sb)) bma->got.br_state = XFS_EXT_UNWRITTEN; if (bma->wasdel) error = xfs_bmap_add_extent_delay_real(bma, whichfork); else error = xfs_bmap_add_extent_hole_real(bma, whichfork); bma->logflags |= tmp_logflags; if (error) return error; /* * Update our extent pointer, given that xfs_bmap_add_extent_delay_real * or xfs_bmap_add_extent_hole_real might have merged it into one of * the neighbouring ones. */ xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got); ASSERT(bma->got.br_startoff <= bma->offset); ASSERT(bma->got.br_startoff + bma->got.br_blockcount >= bma->offset + bma->length); ASSERT(bma->got.br_state == XFS_EXT_NORM || bma->got.br_state == XFS_EXT_UNWRITTEN); return 0; } STATIC int xfs_bmapi_convert_unwritten( struct xfs_bmalloca *bma, struct xfs_bmbt_irec *mval, xfs_filblks_t len, int flags) { int whichfork = xfs_bmapi_whichfork(flags); struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); int tmp_logflags = 0; int error; /* check if we need to do unwritten->real conversion */ if (mval->br_state == XFS_EXT_UNWRITTEN && (flags & XFS_BMAPI_PREALLOC)) return 0; /* check if we need to do real->unwritten conversion */ if (mval->br_state == XFS_EXT_NORM && (flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) != (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) return 0; ASSERT(whichfork != XFS_COW_FORK); /* * Modify (by adding) the state flag, if writing. */ ASSERT(mval->br_blockcount <= len); if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp, bma->ip, whichfork); bma->cur->bc_private.b.firstblock = *bma->firstblock; bma->cur->bc_private.b.dfops = bma->dfops; } mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; /* * Before insertion into the bmbt, zero the range being converted * if required. */ if (flags & XFS_BMAPI_ZERO) { error = xfs_zero_extent(bma->ip, mval->br_startblock, mval->br_blockcount); if (error) return error; } error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx, &bma->cur, mval, bma->firstblock, bma->dfops, &tmp_logflags); /* * Log the inode core unconditionally in the unwritten extent conversion * path because the conversion might not have done so (e.g., if the * extent count hasn't changed). We need to make sure the inode is dirty * in the transaction for the sake of fsync(), even if nothing has * changed, because fsync() will not force the log for this transaction * unless it sees the inode pinned. */ bma->logflags |= tmp_logflags | XFS_ILOG_CORE; if (error) return error; /* * Update our extent pointer, given that * xfs_bmap_add_extent_unwritten_real might have merged it into one * of the neighbouring ones. */ xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got); /* * We may have combined previously unwritten space with written space, * so generate another request. */ if (mval->br_blockcount < len) return -EAGAIN; return 0; } /* * Map file blocks to filesystem blocks, and allocate blocks or convert the * extent state if necessary. Details behaviour is controlled by the flags * parameter. Only allocates blocks from a single allocation group, to avoid * locking problems. * * The returned value in "firstblock" from the first call in a transaction * must be remembered and presented to subsequent calls in "firstblock". * An upper bound for the number of blocks to be allocated is supplied to * the first call in "total"; if no allocation group has that many free * blocks then the call will fail (return NULLFSBLOCK in "firstblock"). */ int xfs_bmapi_write( struct xfs_trans *tp, /* transaction pointer */ struct xfs_inode *ip, /* incore inode */ xfs_fileoff_t bno, /* starting file offs. mapped */ xfs_filblks_t len, /* length to map in file */ int flags, /* XFS_BMAPI_... */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ xfs_extlen_t total, /* total blocks needed */ struct xfs_bmbt_irec *mval, /* output: map values */ int *nmap, /* i/o: mval size/count */ struct xfs_defer_ops *dfops) /* i/o: list extents to free */ { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; struct xfs_bmalloca bma = { NULL }; /* args for xfs_bmap_alloc */ xfs_fileoff_t end; /* end of mapped file region */ int eof; /* after the end of extents */ int error; /* error return */ int n; /* current extent index */ xfs_fileoff_t obno; /* old block number (offset) */ int whichfork; /* data or attr fork */ char inhole; /* current location is hole in file */ char wasdelay; /* old extent was delayed */ #ifdef DEBUG xfs_fileoff_t orig_bno; /* original block number value */ int orig_flags; /* original flags arg value */ xfs_filblks_t orig_len; /* original value of len arg */ struct xfs_bmbt_irec *orig_mval; /* original value of mval */ int orig_nmap; /* original value of *nmap */ orig_bno = bno; orig_len = len; orig_flags = flags; orig_mval = mval; orig_nmap = *nmap; #endif whichfork = xfs_bmapi_whichfork(flags); ASSERT(*nmap >= 1); ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); ASSERT(!(flags & XFS_BMAPI_IGSTATE)); ASSERT(tp != NULL); ASSERT(len > 0); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(!(flags & XFS_BMAPI_REMAP) || whichfork == XFS_DATA_FORK); ASSERT(!(flags & XFS_BMAPI_PREALLOC) || !(flags & XFS_BMAPI_REMAP)); ASSERT(!(flags & XFS_BMAPI_CONVERT) || !(flags & XFS_BMAPI_REMAP)); ASSERT(!(flags & XFS_BMAPI_PREALLOC) || whichfork != XFS_COW_FORK); ASSERT(!(flags & XFS_BMAPI_CONVERT) || whichfork != XFS_COW_FORK); /* zeroing is for currently only for data extents, not metadata */ ASSERT((flags & (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)) != (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)); /* * we can allocate unwritten extents or pre-zero allocated blocks, * but it makes no sense to do both at once. This would result in * zeroing the unwritten extent twice, but it still being an * unwritten extent.... */ ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) != (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)); if (unlikely(XFS_TEST_ERROR( (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; ifp = XFS_IFORK_PTR(ip, whichfork); XFS_STATS_INC(mp, xs_blk_mapw); if (*firstblock == NULLFSBLOCK) { if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; else bma.minleft = 1; } else { bma.minleft = 0; } if (!(ifp->if_flags & XFS_IFEXTENTS)) { error = xfs_iread_extents(tp, ip, whichfork); if (error) goto error0; } xfs_bmap_search_extents(ip, bno, whichfork, &eof, &bma.idx, &bma.got, &bma.prev); n = 0; end = bno + len; obno = bno; bma.tp = tp; bma.ip = ip; bma.total = total; bma.datatype = 0; bma.dfops = dfops; bma.firstblock = firstblock; while (bno < end && n < *nmap) { inhole = eof || bma.got.br_startoff > bno; wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); /* * Make sure we only reflink into a hole. */ if (flags & XFS_BMAPI_REMAP) ASSERT(inhole); if (flags & XFS_BMAPI_COWFORK) ASSERT(!inhole); /* * First, deal with the hole before the allocated space * that we found, if any. */ if (inhole || wasdelay) { bma.eof = eof; bma.conv = !!(flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; bma.offset = bno; bma.flags = flags; /* * There's a 32/64 bit type mismatch between the * allocation length request (which can be 64 bits in * length) and the bma length request, which is * xfs_extlen_t and therefore 32 bits. Hence we have to * check for 32-bit overflows and handle them here. */ if (len > (xfs_filblks_t)MAXEXTLEN) bma.length = MAXEXTLEN; else bma.length = len; ASSERT(len > 0); ASSERT(bma.length > 0); error = xfs_bmapi_allocate(&bma); if (error) goto error0; if (bma.blkno == NULLFSBLOCK) break; /* * If this is a CoW allocation, record the data in * the refcount btree for orphan recovery. */ if (whichfork == XFS_COW_FORK) { error = xfs_refcount_alloc_cow_extent(mp, dfops, bma.blkno, bma.length); if (error) goto error0; } } /* Deal with the allocated space we found. */ xfs_bmapi_trim_map(mval, &bma.got, &bno, len, obno, end, n, flags); /* Execute unwritten extent conversion if necessary */ error = xfs_bmapi_convert_unwritten(&bma, mval, len, flags); if (error == -EAGAIN) continue; if (error) goto error0; /* update the extent map to return */ xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); /* * If we're done, stop now. Stop when we've allocated * XFS_BMAP_MAX_NMAP extents no matter what. Otherwise * the transaction may get too big. */ if (bno >= end || n >= *nmap || bma.nallocs >= *nmap) break; /* Else go on to the next record. */ bma.prev = bma.got; if (++bma.idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) { xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma.idx), &bma.got); } else eof = 1; } *nmap = n; /* * Transform from btree to extents, give it cur. */ if (xfs_bmap_wants_extents(ip, whichfork)) { int tmp_logflags = 0; ASSERT(bma.cur); error = xfs_bmap_btree_to_extents(tp, ip, bma.cur, &tmp_logflags, whichfork); bma.logflags |= tmp_logflags; if (error) goto error0; } ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE || XFS_IFORK_NEXTENTS(ip, whichfork) > XFS_IFORK_MAXEXT(ip, whichfork)); error = 0; error0: /* * Log everything. Do this after conversion, there's no point in * logging the extent records if we've converted to btree format. */ if ((bma.logflags & xfs_ilog_fext(whichfork)) && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) bma.logflags &= ~xfs_ilog_fext(whichfork); else if ((bma.logflags & xfs_ilog_fbroot(whichfork)) && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) bma.logflags &= ~xfs_ilog_fbroot(whichfork); /* * Log whatever the flags say, even if error. Otherwise we might miss * detecting a case where the data is changed, there's an error, * and it's not logged so we don't shutdown when we should. */ if (bma.logflags) xfs_trans_log_inode(tp, ip, bma.logflags); if (bma.cur) { if (!error) { ASSERT(*firstblock == NULLFSBLOCK || XFS_FSB_TO_AGNO(mp, *firstblock) == XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock) || (dfops->dop_low && XFS_FSB_TO_AGNO(mp, *firstblock) < XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock))); *firstblock = bma.cur->bc_private.b.firstblock; } xfs_btree_del_cursor(bma.cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); } if (!error) xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval, orig_nmap, *nmap); return error; } /* * When a delalloc extent is split (e.g., due to a hole punch), the original * indlen reservation must be shared across the two new extents that are left * behind. * * Given the original reservation and the worst case indlen for the two new * extents (as calculated by xfs_bmap_worst_indlen()), split the original * reservation fairly across the two new extents. If necessary, steal available * blocks from a deleted extent to make up a reservation deficiency (e.g., if * ores == 1). The number of stolen blocks is returned. The availability and * subsequent accounting of stolen blocks is the responsibility of the caller. */ static xfs_filblks_t xfs_bmap_split_indlen( xfs_filblks_t ores, /* original res. */ xfs_filblks_t *indlen1, /* ext1 worst indlen */ xfs_filblks_t *indlen2, /* ext2 worst indlen */ xfs_filblks_t avail) /* stealable blocks */ { xfs_filblks_t len1 = *indlen1; xfs_filblks_t len2 = *indlen2; xfs_filblks_t nres = len1 + len2; /* new total res. */ xfs_filblks_t stolen = 0; /* * Steal as many blocks as we can to try and satisfy the worst case * indlen for both new extents. */ while (nres > ores && avail) { nres--; avail--; stolen++; } /* * The only blocks available are those reserved for the original * extent and what we can steal from the extent being removed. * If this still isn't enough to satisfy the combined * requirements for the two new extents, skim blocks off of each * of the new reservations until they match what is available. */ while (nres > ores) { if (len1) { len1--; nres--; } if (nres == ores) break; if (len2) { len2--; nres--; } } *indlen1 = len1; *indlen2 = len2; return stolen; } int xfs_bmap_del_extent_delay( struct xfs_inode *ip, int whichfork, xfs_extnum_t *idx, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del) { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_bmbt_irec new; int64_t da_old, da_new, da_diff = 0; xfs_fileoff_t del_endoff, got_endoff; xfs_filblks_t got_indlen, new_indlen, stolen; int error = 0, state = 0; bool isrt; XFS_STATS_INC(mp, xs_del_exlist); isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); del_endoff = del->br_startoff + del->br_blockcount; got_endoff = got->br_startoff + got->br_blockcount; da_old = startblockval(got->br_startblock); da_new = 0; ASSERT(*idx >= 0); ASSERT(*idx < ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); ASSERT(del->br_blockcount > 0); ASSERT(got->br_startoff <= del->br_startoff); ASSERT(got_endoff >= del_endoff); if (isrt) { int64_t rtexts = XFS_FSB_TO_B(mp, del->br_blockcount); do_div(rtexts, mp->m_sb.sb_rextsize); xfs_mod_frextents(mp, rtexts); } /* * Update the inode delalloc counter now and wait to update the * sb counters as we might have to borrow some blocks for the * indirect block accounting. */ error = xfs_trans_reserve_quota_nblks(NULL, ip, -((long)del->br_blockcount), 0, isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); ip->i_delayed_blks -= del->br_blockcount; if (whichfork == XFS_COW_FORK) state |= BMAP_COWFORK; if (got->br_startoff == del->br_startoff) state |= BMAP_LEFT_CONTIG; if (got_endoff == del_endoff) state |= BMAP_RIGHT_CONTIG; switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) { case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: /* * Matches the whole extent. Delete the entry. */ xfs_iext_remove(ip, *idx, 1, state); --*idx; break; case BMAP_LEFT_CONTIG: /* * Deleting the first part of the extent. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); got->br_startoff = del_endoff; got->br_blockcount -= del->br_blockcount; da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, got->br_blockcount), da_old); got->br_startblock = nullstartblock((int)da_new); xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); break; case BMAP_RIGHT_CONTIG: /* * Deleting the last part of the extent. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); got->br_blockcount = got->br_blockcount - del->br_blockcount; da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, got->br_blockcount), da_old); got->br_startblock = nullstartblock((int)da_new); xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); break; case 0: /* * Deleting the middle of the extent. * * Distribute the original indlen reservation across the two new * extents. Steal blocks from the deleted extent if necessary. * Stealing blocks simply fudges the fdblocks accounting below. * Warn if either of the new indlen reservations is zero as this * can lead to delalloc problems. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); got->br_blockcount = del->br_startoff - got->br_startoff; got_indlen = xfs_bmap_worst_indlen(ip, got->br_blockcount); new.br_blockcount = got_endoff - del_endoff; new_indlen = xfs_bmap_worst_indlen(ip, new.br_blockcount); WARN_ON_ONCE(!got_indlen || !new_indlen); stolen = xfs_bmap_split_indlen(da_old, &got_indlen, &new_indlen, del->br_blockcount); got->br_startblock = nullstartblock((int)got_indlen); xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got); trace_xfs_bmap_post_update(ip, *idx, 0, _THIS_IP_); new.br_startoff = del_endoff; new.br_state = got->br_state; new.br_startblock = nullstartblock((int)new_indlen); ++*idx; xfs_iext_insert(ip, *idx, 1, &new, state); da_new = got_indlen + new_indlen - stolen; del->br_blockcount -= stolen; break; } ASSERT(da_old >= da_new); da_diff = da_old - da_new; if (!isrt) da_diff += del->br_blockcount; if (da_diff) xfs_mod_fdblocks(mp, da_diff, false); return error; } void xfs_bmap_del_extent_cow( struct xfs_inode *ip, xfs_extnum_t *idx, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del) { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); struct xfs_bmbt_irec new; xfs_fileoff_t del_endoff, got_endoff; int state = BMAP_COWFORK; XFS_STATS_INC(mp, xs_del_exlist); del_endoff = del->br_startoff + del->br_blockcount; got_endoff = got->br_startoff + got->br_blockcount; ASSERT(*idx >= 0); ASSERT(*idx < ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); ASSERT(del->br_blockcount > 0); ASSERT(got->br_startoff <= del->br_startoff); ASSERT(got_endoff >= del_endoff); ASSERT(!isnullstartblock(got->br_startblock)); if (got->br_startoff == del->br_startoff) state |= BMAP_LEFT_CONTIG; if (got_endoff == del_endoff) state |= BMAP_RIGHT_CONTIG; switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) { case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: /* * Matches the whole extent. Delete the entry. */ xfs_iext_remove(ip, *idx, 1, state); --*idx; break; case BMAP_LEFT_CONTIG: /* * Deleting the first part of the extent. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); got->br_startoff = del_endoff; got->br_blockcount -= del->br_blockcount; got->br_startblock = del->br_startblock + del->br_blockcount; xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); break; case BMAP_RIGHT_CONTIG: /* * Deleting the last part of the extent. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); got->br_blockcount -= del->br_blockcount; xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); break; case 0: /* * Deleting the middle of the extent. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); got->br_blockcount = del->br_startoff - got->br_startoff; xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); new.br_startoff = del_endoff; new.br_blockcount = got_endoff - del_endoff; new.br_state = got->br_state; new.br_startblock = del->br_startblock + del->br_blockcount; ++*idx; xfs_iext_insert(ip, *idx, 1, &new, state); break; } } /* * Called by xfs_bmapi to update file extent records and the btree * after removing space (or undoing a delayed allocation). */ STATIC int /* error */ xfs_bmap_del_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current transaction pointer */ xfs_extnum_t *idx, /* extent number to update/delete */ struct xfs_defer_ops *dfops, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ int whichfork, /* data or attr fork */ int bflags) /* bmapi flags */ { xfs_filblks_t da_new; /* new delay-alloc indirect blocks */ xfs_filblks_t da_old; /* old delay-alloc indirect blocks */ xfs_fsblock_t del_endblock=0; /* first block past del */ xfs_fileoff_t del_endoff; /* first offset past del */ int delay; /* current block is delayed allocated */ int do_fx; /* free extent at end of routine */ xfs_bmbt_rec_host_t *ep; /* current extent entry pointer */ int error; /* error return value */ int flags; /* inode logging flags */ xfs_bmbt_irec_t got; /* current extent entry */ xfs_fileoff_t got_endoff; /* first offset past got */ int i; /* temp state */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_mount_t *mp; /* mount structure */ xfs_filblks_t nblks; /* quota/sb block count */ xfs_bmbt_irec_t new; /* new record to be inserted */ /* REFERENCED */ uint qfield; /* quota field to update */ xfs_filblks_t temp; /* for indirect length calculations */ xfs_filblks_t temp2; /* for indirect length calculations */ int state = 0; mp = ip->i_mount; XFS_STATS_INC(mp, xs_del_exlist); if (whichfork == XFS_ATTR_FORK) state |= BMAP_ATTRFORK; else if (whichfork == XFS_COW_FORK) state |= BMAP_COWFORK; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT((*idx >= 0) && (*idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))); ASSERT(del->br_blockcount > 0); ep = xfs_iext_get_ext(ifp, *idx); xfs_bmbt_get_all(ep, &got); ASSERT(got.br_startoff <= del->br_startoff); del_endoff = del->br_startoff + del->br_blockcount; got_endoff = got.br_startoff + got.br_blockcount; ASSERT(got_endoff >= del_endoff); delay = isnullstartblock(got.br_startblock); ASSERT(isnullstartblock(del->br_startblock) == delay); flags = 0; qfield = 0; error = 0; /* * If deleting a real allocation, must free up the disk space. */ if (!delay) { flags = XFS_ILOG_CORE; /* * Realtime allocation. Free it and record di_nblocks update. */ if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) { xfs_fsblock_t bno; xfs_filblks_t len; ASSERT(do_mod(del->br_blockcount, mp->m_sb.sb_rextsize) == 0); ASSERT(do_mod(del->br_startblock, mp->m_sb.sb_rextsize) == 0); bno = del->br_startblock; len = del->br_blockcount; do_div(bno, mp->m_sb.sb_rextsize); do_div(len, mp->m_sb.sb_rextsize); error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len); if (error) goto done; do_fx = 0; nblks = len * mp->m_sb.sb_rextsize; qfield = XFS_TRANS_DQ_RTBCOUNT; } /* * Ordinary allocation. */ else { do_fx = 1; nblks = del->br_blockcount; qfield = XFS_TRANS_DQ_BCOUNT; } /* * Set up del_endblock and cur for later. */ del_endblock = del->br_startblock + del->br_blockcount; if (cur) { if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, got.br_blockcount, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } da_old = da_new = 0; } else { da_old = startblockval(got.br_startblock); da_new = 0; nblks = 0; do_fx = 0; } /* * Set flag value to use in switch statement. * Left-contig is 2, right-contig is 1. */ switch (((got.br_startoff == del->br_startoff) << 1) | (got_endoff == del_endoff)) { case 3: /* * Matches the whole extent. Delete the entry. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_iext_remove(ip, *idx, 1, whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0); --*idx; if (delay) break; XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); flags |= XFS_ILOG_CORE; if (!cur) { flags |= xfs_ilog_fext(whichfork); break; } if ((error = xfs_btree_delete(cur, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); break; case 2: /* * Deleting the first part of the extent. */ trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_startoff(ep, del_endoff); temp = got.br_blockcount - del->br_blockcount; xfs_bmbt_set_blockcount(ep, temp); if (delay) { temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), da_old); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); da_new = temp; break; } xfs_bmbt_set_startblock(ep, del_endblock); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); if (!cur) { flags |= xfs_ilog_fext(whichfork); break; } if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock, got.br_blockcount - del->br_blockcount, got.br_state))) goto done; break; case 1: /* * Deleting the last part of the extent. */ temp = got.br_blockcount - del->br_blockcount; trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); if (delay) { temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), da_old); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); da_new = temp; break; } trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); if (!cur) { flags |= xfs_ilog_fext(whichfork); break; } if ((error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, got.br_blockcount - del->br_blockcount, got.br_state))) goto done; break; case 0: /* * Deleting the middle of the extent. */ temp = del->br_startoff - got.br_startoff; trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); new.br_startoff = del_endoff; temp2 = got_endoff - del_endoff; new.br_blockcount = temp2; new.br_state = got.br_state; if (!delay) { new.br_startblock = del_endblock; flags |= XFS_ILOG_CORE; if (cur) { if ((error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, temp, got.br_state))) goto done; if ((error = xfs_btree_increment(cur, 0, &i))) goto done; cur->bc_rec.b = new; error = xfs_btree_insert(cur, &i); if (error && error != -ENOSPC) goto done; /* * If get no-space back from btree insert, * it tried a split, and we have a zero * block reservation. * Fix up our state and return the error. */ if (error == -ENOSPC) { /* * Reset the cursor, don't trust * it after any insert operation. */ if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, temp, &i))) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); /* * Update the btree record back * to the original value. */ if ((error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, got.br_blockcount, got.br_state))) goto done; /* * Reset the extent record back * to the original value. */ xfs_bmbt_set_blockcount(ep, got.br_blockcount); flags = 0; error = -ENOSPC; goto done; } XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); } else flags |= xfs_ilog_fext(whichfork); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); } else { xfs_filblks_t stolen; ASSERT(whichfork == XFS_DATA_FORK); /* * Distribute the original indlen reservation across the * two new extents. Steal blocks from the deleted extent * if necessary. Stealing blocks simply fudges the * fdblocks accounting in xfs_bunmapi(). */ temp = xfs_bmap_worst_indlen(ip, got.br_blockcount); temp2 = xfs_bmap_worst_indlen(ip, new.br_blockcount); stolen = xfs_bmap_split_indlen(da_old, &temp, &temp2, del->br_blockcount); da_new = temp + temp2 - stolen; del->br_blockcount -= stolen; /* * Set the reservation for each extent. Warn if either * is zero as this can lead to delalloc problems. */ WARN_ON_ONCE(!temp || !temp2); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); new.br_startblock = nullstartblock((int)temp2); } trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); xfs_iext_insert(ip, *idx + 1, 1, &new, state); ++*idx; break; } /* remove reverse mapping */ if (!delay) { error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del); if (error) goto done; } /* * If we need to, add to list of extents to delete. */ if (do_fx && !(bflags & XFS_BMAPI_REMAP)) { if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) { error = xfs_refcount_decrease_extent(mp, dfops, del); if (error) goto done; } else xfs_bmap_add_free(mp, dfops, del->br_startblock, del->br_blockcount, NULL); } /* * Adjust inode # blocks in the file. */ if (nblks) ip->i_d.di_nblocks -= nblks; /* * Adjust quota data. */ if (qfield && !(bflags & XFS_BMAPI_REMAP)) xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks); /* * Account for change in delayed indirect blocks. * Nothing to do for disk quota accounting here. */ ASSERT(da_old >= da_new); if (da_old > da_new) xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false); done: *logflagsp = flags; return error; } /* * Unmap (remove) blocks from a file. * If nexts is nonzero then the number of extents to remove is limited to * that value. If not all extents in the block range can be removed then * *done is set. */ int /* error */ __xfs_bunmapi( xfs_trans_t *tp, /* transaction pointer */ struct xfs_inode *ip, /* incore inode */ xfs_fileoff_t bno, /* starting offset to unmap */ xfs_filblks_t *rlen, /* i/o: amount remaining */ int flags, /* misc flags */ xfs_extnum_t nexts, /* number of extents max */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ struct xfs_defer_ops *dfops) /* i/o: deferred updates */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ xfs_bmbt_irec_t del; /* extent being deleted */ int eof; /* is deleting at eof */ xfs_bmbt_rec_host_t *ep; /* extent record pointer */ int error; /* error return value */ xfs_extnum_t extno; /* extent number in list */ xfs_bmbt_irec_t got; /* current extent record */ xfs_ifork_t *ifp; /* inode fork pointer */ int isrt; /* freeing in rt area */ xfs_extnum_t lastx; /* last extent index used */ int logflags; /* transaction logging flags */ xfs_extlen_t mod; /* rt extent offset */ xfs_mount_t *mp; /* mount structure */ xfs_extnum_t nextents; /* number of file extents */ xfs_bmbt_irec_t prev; /* previous extent record */ xfs_fileoff_t start; /* first file offset deleted */ int tmp_logflags; /* partial logging flags */ int wasdel; /* was a delayed alloc extent */ int whichfork; /* data or attribute fork */ xfs_fsblock_t sum; xfs_filblks_t len = *rlen; /* length to unmap in file */ trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); whichfork = xfs_bmapi_whichfork(flags); ASSERT(whichfork != XFS_COW_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); if (unlikely( XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) { XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW, ip->i_mount); return -EFSCORRUPTED; } mp = ip->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(len > 0); ASSERT(nexts >= 0); if (!(ifp->if_flags & XFS_IFEXTENTS) && (error = xfs_iread_extents(tp, ip, whichfork))) return error; nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); if (nextents == 0) { *rlen = 0; return 0; } XFS_STATS_INC(mp, xs_blk_unmap); isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); start = bno; bno = start + len - 1; ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); /* * Check to see if the given block number is past the end of the * file, back up to the last block if so... */ if (eof) { ep = xfs_iext_get_ext(ifp, --lastx); xfs_bmbt_get_all(ep, &got); bno = got.br_startoff + got.br_blockcount - 1; } logflags = 0; if (ifp->if_flags & XFS_IFBROOT) { ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE); cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; } else cur = NULL; if (isrt) { /* * Synchronize by locking the bitmap inode. */ xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP); xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL|XFS_ILOCK_RTSUM); xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); } extno = 0; while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 && (nexts == 0 || extno < nexts)) { /* * Is the found extent after a hole in which bno lives? * Just back up to the previous extent, if so. */ if (got.br_startoff > bno) { if (--lastx < 0) break; ep = xfs_iext_get_ext(ifp, lastx); xfs_bmbt_get_all(ep, &got); } /* * Is the last block of this extent before the range * we're supposed to delete? If so, we're done. */ bno = XFS_FILEOFF_MIN(bno, got.br_startoff + got.br_blockcount - 1); if (bno < start) break; /* * Then deal with the (possibly delayed) allocated space * we found. */ ASSERT(ep != NULL); del = got; wasdel = isnullstartblock(del.br_startblock); if (got.br_startoff < start) { del.br_startoff = start; del.br_blockcount -= start - got.br_startoff; if (!wasdel) del.br_startblock += start - got.br_startoff; } if (del.br_startoff + del.br_blockcount > bno + 1) del.br_blockcount = bno + 1 - del.br_startoff; sum = del.br_startblock + del.br_blockcount; if (isrt && (mod = do_mod(sum, mp->m_sb.sb_rextsize))) { /* * Realtime extent not lined up at the end. * The extent could have been split into written * and unwritten pieces, or we could just be * unmapping part of it. But we can't really * get rid of part of a realtime extent. */ if (del.br_state == XFS_EXT_UNWRITTEN || !xfs_sb_version_hasextflgbit(&mp->m_sb)) { /* * This piece is unwritten, or we're not * using unwritten extents. Skip over it. */ ASSERT(bno >= mod); bno -= mod > del.br_blockcount ? del.br_blockcount : mod; if (bno < got.br_startoff) { if (--lastx >= 0) xfs_bmbt_get_all(xfs_iext_get_ext( ifp, lastx), &got); } continue; } /* * It's written, turn it unwritten. * This is better than zeroing it. */ ASSERT(del.br_state == XFS_EXT_NORM); ASSERT(tp->t_blk_res > 0); /* * If this spans a realtime extent boundary, * chop it back to the start of the one we end at. */ if (del.br_blockcount > mod) { del.br_startoff += del.br_blockcount - mod; del.br_startblock += del.br_blockcount - mod; del.br_blockcount = mod; } del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, ip, &lastx, &cur, &del, firstblock, dfops, &logflags); if (error) goto error0; goto nodelete; } if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) { /* * Realtime extent is lined up at the end but not * at the front. We'll get rid of full extents if * we can. */ mod = mp->m_sb.sb_rextsize - mod; if (del.br_blockcount > mod) { del.br_blockcount -= mod; del.br_startoff += mod; del.br_startblock += mod; } else if ((del.br_startoff == start && (del.br_state == XFS_EXT_UNWRITTEN || tp->t_blk_res == 0)) || !xfs_sb_version_hasextflgbit(&mp->m_sb)) { /* * Can't make it unwritten. There isn't * a full extent here so just skip it. */ ASSERT(bno >= del.br_blockcount); bno -= del.br_blockcount; if (got.br_startoff > bno) { if (--lastx >= 0) { ep = xfs_iext_get_ext(ifp, lastx); xfs_bmbt_get_all(ep, &got); } } continue; } else if (del.br_state == XFS_EXT_UNWRITTEN) { /* * This one is already unwritten. * It must have a written left neighbor. * Unwrite the killed part of that one and * try again. */ ASSERT(lastx > 0); xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), &prev); ASSERT(prev.br_state == XFS_EXT_NORM); ASSERT(!isnullstartblock(prev.br_startblock)); ASSERT(del.br_startblock == prev.br_startblock + prev.br_blockcount); if (prev.br_startoff < start) { mod = start - prev.br_startoff; prev.br_blockcount -= mod; prev.br_startblock += mod; prev.br_startoff = start; } prev.br_state = XFS_EXT_UNWRITTEN; lastx--; error = xfs_bmap_add_extent_unwritten_real(tp, ip, &lastx, &cur, &prev, firstblock, dfops, &logflags); if (error) goto error0; goto nodelete; } else { ASSERT(del.br_state == XFS_EXT_NORM); del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, ip, &lastx, &cur, &del, firstblock, dfops, &logflags); if (error) goto error0; goto nodelete; } } /* * If it's the case where the directory code is running * with no block reservation, and the deleted block is in * the middle of its extent, and the resulting insert * of an extent would cause transformation to btree format, * then reject it. The calling code will then swap * blocks around instead. * We have to do this now, rather than waiting for the * conversion to btree format, since the transaction * will be dirty. */ if (!wasdel && tp->t_blk_res == 0 && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && XFS_IFORK_NEXTENTS(ip, whichfork) >= /* Note the >= */ XFS_IFORK_MAXEXT(ip, whichfork) && del.br_startoff > got.br_startoff && del.br_startoff + del.br_blockcount < got.br_startoff + got.br_blockcount) { error = -ENOSPC; goto error0; } /* * Unreserve quota and update realtime free space, if * appropriate. If delayed allocation, update the inode delalloc * counter now and wait to update the sb counters as * xfs_bmap_del_extent() might need to borrow some blocks. */ if (wasdel) { ASSERT(startblockval(del.br_startblock) > 0); if (isrt) { xfs_filblks_t rtexts; rtexts = XFS_FSB_TO_B(mp, del.br_blockcount); do_div(rtexts, mp->m_sb.sb_rextsize); xfs_mod_frextents(mp, (int64_t)rtexts); (void)xfs_trans_reserve_quota_nblks(NULL, ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_RTBLKS); } else { (void)xfs_trans_reserve_quota_nblks(NULL, ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_REGBLKS); } ip->i_delayed_blks -= del.br_blockcount; if (cur) cur->bc_private.b.flags |= XFS_BTCUR_BPRV_WASDEL; } else if (cur) cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL; error = xfs_bmap_del_extent(ip, tp, &lastx, dfops, cur, &del, &tmp_logflags, whichfork, flags); logflags |= tmp_logflags; if (error) goto error0; if (!isrt && wasdel) xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount, false); bno = del.br_startoff - 1; nodelete: /* * If not done go on to the next (previous) record. */ if (bno != (xfs_fileoff_t)-1 && bno >= start) { if (lastx >= 0) { ep = xfs_iext_get_ext(ifp, lastx); if (xfs_bmbt_get_startoff(ep) > bno) { if (--lastx >= 0) ep = xfs_iext_get_ext(ifp, lastx); } xfs_bmbt_get_all(ep, &got); } extno++; } } if (bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0) *rlen = 0; else *rlen = bno - start + 1; /* * Convert to a btree if necessary. */ if (xfs_bmap_needs_btree(ip, whichfork)) { ASSERT(cur == NULL); error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops, &cur, 0, &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) goto error0; } /* * transform from btree to extents, give it cur */ else if (xfs_bmap_wants_extents(ip, whichfork)) { ASSERT(cur != NULL); error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) goto error0; } /* * transform from extents to local? */ error = 0; error0: /* * Log everything. Do this after conversion, there's no point in * logging the extent records if we've converted to btree format. */ if ((logflags & xfs_ilog_fext(whichfork)) && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) logflags &= ~xfs_ilog_fext(whichfork); else if ((logflags & xfs_ilog_fbroot(whichfork)) && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) logflags &= ~xfs_ilog_fbroot(whichfork); /* * Log inode even in the error case, if the transaction * is dirty we'll need to shut down the filesystem. */ if (logflags) xfs_trans_log_inode(tp, ip, logflags); if (cur) { if (!error) { *firstblock = cur->bc_private.b.firstblock; cur->bc_private.b.allocated = 0; } xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); } return error; } /* Unmap a range of a file. */ int xfs_bunmapi( xfs_trans_t *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, struct xfs_defer_ops *dfops, int *done) { int error; error = __xfs_bunmapi(tp, ip, bno, &len, flags, nexts, firstblock, dfops); *done = (len == 0); return error; } /* * Determine whether an extent shift can be accomplished by a merge with the * extent that precedes the target hole of the shift. */ STATIC bool xfs_bmse_can_merge( struct xfs_bmbt_irec *left, /* preceding extent */ struct xfs_bmbt_irec *got, /* current extent to shift */ xfs_fileoff_t shift) /* shift fsb */ { xfs_fileoff_t startoff; startoff = got->br_startoff - shift; /* * The extent, once shifted, must be adjacent in-file and on-disk with * the preceding extent. */ if ((left->br_startoff + left->br_blockcount != startoff) || (left->br_startblock + left->br_blockcount != got->br_startblock) || (left->br_state != got->br_state) || (left->br_blockcount + got->br_blockcount > MAXEXTLEN)) return false; return true; } /* * A bmap extent shift adjusts the file offset of an extent to fill a preceding * hole in the file. If an extent shift would result in the extent being fully * adjacent to the extent that currently precedes the hole, we can merge with * the preceding extent rather than do the shift. * * This function assumes the caller has verified a shift-by-merge is possible * with the provided extents via xfs_bmse_can_merge(). */ STATIC int xfs_bmse_merge( struct xfs_inode *ip, int whichfork, xfs_fileoff_t shift, /* shift fsb */ int current_ext, /* idx of gotp */ struct xfs_bmbt_rec_host *gotp, /* extent to shift */ struct xfs_bmbt_rec_host *leftp, /* preceding extent */ struct xfs_btree_cur *cur, int *logflags) /* output */ { struct xfs_bmbt_irec got; struct xfs_bmbt_irec left; xfs_filblks_t blockcount; int error, i; struct xfs_mount *mp = ip->i_mount; xfs_bmbt_get_all(gotp, &got); xfs_bmbt_get_all(leftp, &left); blockcount = left.br_blockcount + got.br_blockcount; ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(xfs_bmse_can_merge(&left, &got, shift)); /* * Merge the in-core extents. Note that the host record pointers and * current_ext index are invalid once the extent has been removed via * xfs_iext_remove(). */ xfs_bmbt_set_blockcount(leftp, blockcount); xfs_iext_remove(ip, current_ext, 1, 0); /* * Update the on-disk extent count, the btree if necessary and log the * inode. */ XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); *logflags |= XFS_ILOG_CORE; if (!cur) { *logflags |= XFS_ILOG_DEXT; return 0; } /* lookup and remove the extent to merge */ error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, got.br_blockcount, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); error = xfs_btree_delete(cur, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); /* lookup and update size of the previous extent */ error = xfs_bmbt_lookup_eq(cur, left.br_startoff, left.br_startblock, left.br_blockcount, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); left.br_blockcount = blockcount; return xfs_bmbt_update(cur, left.br_startoff, left.br_startblock, left.br_blockcount, left.br_state); } /* * Shift a single extent. */ STATIC int xfs_bmse_shift_one( struct xfs_inode *ip, int whichfork, xfs_fileoff_t offset_shift_fsb, int *current_ext, struct xfs_bmbt_rec_host *gotp, struct xfs_btree_cur *cur, int *logflags, enum shift_direction direction, struct xfs_defer_ops *dfops) { struct xfs_ifork *ifp; struct xfs_mount *mp; xfs_fileoff_t startoff; struct xfs_bmbt_rec_host *adj_irecp; struct xfs_bmbt_irec got; struct xfs_bmbt_irec adj_irec; int error; int i; int total_extents; mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); xfs_bmbt_get_all(gotp, &got); /* delalloc extents should be prevented by caller */ XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock)); if (direction == SHIFT_LEFT) { startoff = got.br_startoff - offset_shift_fsb; /* * Check for merge if we've got an extent to the left, * otherwise make sure there's enough room at the start * of the file for the shift. */ if (!*current_ext) { if (got.br_startoff < offset_shift_fsb) return -EINVAL; goto update_current_ext; } /* * grab the left extent and check for a large * enough hole. */ adj_irecp = xfs_iext_get_ext(ifp, *current_ext - 1); xfs_bmbt_get_all(adj_irecp, &adj_irec); if (startoff < adj_irec.br_startoff + adj_irec.br_blockcount) return -EINVAL; /* check whether to merge the extent or shift it down */ if (xfs_bmse_can_merge(&adj_irec, &got, offset_shift_fsb)) { error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb, *current_ext, gotp, adj_irecp, cur, logflags); if (error) return error; adj_irec = got; goto update_rmap; } } else { startoff = got.br_startoff + offset_shift_fsb; /* nothing to move if this is the last extent */ if (*current_ext >= (total_extents - 1)) goto update_current_ext; /* * If this is not the last extent in the file, make sure there * is enough room between current extent and next extent for * accommodating the shift. */ adj_irecp = xfs_iext_get_ext(ifp, *current_ext + 1); xfs_bmbt_get_all(adj_irecp, &adj_irec); if (startoff + got.br_blockcount > adj_irec.br_startoff) return -EINVAL; /* * Unlike a left shift (which involves a hole punch), * a right shift does not modify extent neighbors * in any way. We should never find mergeable extents * in this scenario. Check anyways and warn if we * encounter two extents that could be one. */ if (xfs_bmse_can_merge(&got, &adj_irec, offset_shift_fsb)) WARN_ON_ONCE(1); } /* * Increment the extent index for the next iteration, update the start * offset of the in-core extent and update the btree if applicable. */ update_current_ext: if (direction == SHIFT_LEFT) (*current_ext)++; else (*current_ext)--; xfs_bmbt_set_startoff(gotp, startoff); *logflags |= XFS_ILOG_CORE; adj_irec = got; if (!cur) { *logflags |= XFS_ILOG_DEXT; goto update_rmap; } error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, got.br_blockcount, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(mp, i == 1); got.br_startoff = startoff; error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, got.br_blockcount, got.br_state); if (error) return error; update_rmap: /* update reverse mapping */ error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &adj_irec); if (error) return error; adj_irec.br_startoff = startoff; return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &adj_irec); } /* * Shift extent records to the left/right to cover/create a hole. * * The maximum number of extents to be shifted in a single operation is * @num_exts. @stop_fsb specifies the file offset at which to stop shift and the * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb * is the length by which each extent is shifted. If there is no hole to shift * the extents into, this will be considered invalid operation and we abort * immediately. */ int xfs_bmap_shift_extents( struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, struct xfs_defer_ops *dfops, enum shift_direction direction, int num_exts) { struct xfs_btree_cur *cur = NULL; struct xfs_bmbt_rec_host *gotp; struct xfs_bmbt_irec got; struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; xfs_extnum_t nexts = 0; xfs_extnum_t current_ext; xfs_extnum_t total_extents; xfs_extnum_t stop_extent; int error = 0; int whichfork = XFS_DATA_FORK; int logflags = 0; if (unlikely(XFS_TEST_ERROR( (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { XFS_ERROR_REPORT("xfs_bmap_shift_extents", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT); ASSERT(*next_fsb != NULLFSBLOCK || direction == SHIFT_RIGHT); ifp = XFS_IFORK_PTR(ip, whichfork); if (!(ifp->if_flags & XFS_IFEXTENTS)) { /* Read in all the extents */ error = xfs_iread_extents(tp, ip, whichfork); if (error) return error; } if (ifp->if_flags & XFS_IFBROOT) { cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; } /* * There may be delalloc extents in the data fork before the range we * are collapsing out, so we cannot use the count of real extents here. * Instead we have to calculate it from the incore fork. */ total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); if (total_extents == 0) { *done = 1; goto del_cursor; } /* * In case of first right shift, we need to initialize next_fsb */ if (*next_fsb == NULLFSBLOCK) { gotp = xfs_iext_get_ext(ifp, total_extents - 1); xfs_bmbt_get_all(gotp, &got); *next_fsb = got.br_startoff; if (stop_fsb > *next_fsb) { *done = 1; goto del_cursor; } } /* Lookup the extent index at which we have to stop */ if (direction == SHIFT_RIGHT) { gotp = xfs_iext_bno_to_ext(ifp, stop_fsb, &stop_extent); /* Make stop_extent exclusive of shift range */ stop_extent--; } else stop_extent = total_extents; /* * Look up the extent index for the fsb where we start shifting. We can * henceforth iterate with current_ext as extent list changes are locked * out via ilock. * * gotp can be null in 2 cases: 1) if there are no extents or 2) * *next_fsb lies in a hole beyond which there are no extents. Either * way, we are done. */ gotp = xfs_iext_bno_to_ext(ifp, *next_fsb, ¤t_ext); if (!gotp) { *done = 1; goto del_cursor; } /* some sanity checking before we finally start shifting extents */ if ((direction == SHIFT_LEFT && current_ext >= stop_extent) || (direction == SHIFT_RIGHT && current_ext <= stop_extent)) { error = -EIO; goto del_cursor; } while (nexts++ < num_exts) { error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, ¤t_ext, gotp, cur, &logflags, direction, dfops); if (error) goto del_cursor; /* * If there was an extent merge during the shift, the extent * count can change. Update the total and grade the next record. */ if (direction == SHIFT_LEFT) { total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); stop_extent = total_extents; } if (current_ext == stop_extent) { *done = 1; *next_fsb = NULLFSBLOCK; break; } gotp = xfs_iext_get_ext(ifp, current_ext); } if (!*done) { xfs_bmbt_get_all(gotp, &got); *next_fsb = got.br_startoff; } del_cursor: if (cur) xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); if (logflags) xfs_trans_log_inode(tp, ip, logflags); return error; } /* * Splits an extent into two extents at split_fsb block such that it is * the first block of the current_ext. @current_ext is a target extent * to be split. @split_fsb is a block where the extents is split. * If split_fsb lies in a hole or the first block of extents, just return 0. */ STATIC int xfs_bmap_split_extent_at( struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t split_fsb, xfs_fsblock_t *firstfsb, struct xfs_defer_ops *dfops) { int whichfork = XFS_DATA_FORK; struct xfs_btree_cur *cur = NULL; struct xfs_bmbt_rec_host *gotp; struct xfs_bmbt_irec got; struct xfs_bmbt_irec new; /* split extent */ struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; xfs_fsblock_t gotblkcnt; /* new block count for got */ xfs_extnum_t current_ext; int error = 0; int logflags = 0; int i = 0; if (unlikely(XFS_TEST_ERROR( (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { XFS_ERROR_REPORT("xfs_bmap_split_extent_at", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; ifp = XFS_IFORK_PTR(ip, whichfork); if (!(ifp->if_flags & XFS_IFEXTENTS)) { /* Read in all the extents */ error = xfs_iread_extents(tp, ip, whichfork); if (error) return error; } /* * gotp can be null in 2 cases: 1) if there are no extents * or 2) split_fsb lies in a hole beyond which there are * no extents. Either way, we are done. */ gotp = xfs_iext_bno_to_ext(ifp, split_fsb, ¤t_ext); if (!gotp) return 0; xfs_bmbt_get_all(gotp, &got); /* * Check split_fsb lies in a hole or the start boundary offset * of the extent. */ if (got.br_startoff >= split_fsb) return 0; gotblkcnt = split_fsb - got.br_startoff; new.br_startoff = split_fsb; new.br_startblock = got.br_startblock + gotblkcnt; new.br_blockcount = got.br_blockcount - gotblkcnt; new.br_state = got.br_state; if (ifp->if_flags & XFS_IFBROOT) { cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstfsb; cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, got.br_blockcount, &i); if (error) goto del_cursor; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor); } xfs_bmbt_set_blockcount(gotp, gotblkcnt); got.br_blockcount = gotblkcnt; logflags = XFS_ILOG_CORE; if (cur) { error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, got.br_blockcount, got.br_state); if (error) goto del_cursor; } else logflags |= XFS_ILOG_DEXT; /* Add new extent */ current_ext++; xfs_iext_insert(ip, current_ext, 1, &new, 0); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); if (cur) { error = xfs_bmbt_lookup_eq(cur, new.br_startoff, new.br_startblock, new.br_blockcount, &i); if (error) goto del_cursor; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, del_cursor); cur->bc_rec.b.br_state = new.br_state; error = xfs_btree_insert(cur, &i); if (error) goto del_cursor; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor); } /* * Convert to a btree if necessary. */ if (xfs_bmap_needs_btree(ip, whichfork)) { int tmp_logflags; /* partial log flag return val */ ASSERT(cur == NULL); error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, dfops, &cur, 0, &tmp_logflags, whichfork); logflags |= tmp_logflags; } del_cursor: if (cur) { cur->bc_private.b.allocated = 0; xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); } if (logflags) xfs_trans_log_inode(tp, ip, logflags); return error; } int xfs_bmap_split_extent( struct xfs_inode *ip, xfs_fileoff_t split_fsb) { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; struct xfs_defer_ops dfops; xfs_fsblock_t firstfsb; int error; error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp); if (error) return error; xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_defer_init(&dfops, &firstfsb); error = xfs_bmap_split_extent_at(tp, ip, split_fsb, &firstfsb, &dfops); if (error) goto out; error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out; return xfs_trans_commit(tp); out: xfs_defer_cancel(&dfops); xfs_trans_cancel(tp); return error; } /* Deferred mapping is only for real extents in the data fork. */ static bool xfs_bmap_is_update_needed( struct xfs_bmbt_irec *bmap) { return bmap->br_startblock != HOLESTARTBLOCK && bmap->br_startblock != DELAYSTARTBLOCK; } /* Record a bmap intent. */ static int __xfs_bmap_add( struct xfs_mount *mp, struct xfs_defer_ops *dfops, enum xfs_bmap_intent_type type, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *bmap) { int error; struct xfs_bmap_intent *bi; trace_xfs_bmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock), type, XFS_FSB_TO_AGBNO(mp, bmap->br_startblock), ip->i_ino, whichfork, bmap->br_startoff, bmap->br_blockcount, bmap->br_state); bi = kmem_alloc(sizeof(struct xfs_bmap_intent), KM_SLEEP | KM_NOFS); INIT_LIST_HEAD(&bi->bi_list); bi->bi_type = type; bi->bi_owner = ip; bi->bi_whichfork = whichfork; bi->bi_bmap = *bmap; error = xfs_defer_join(dfops, bi->bi_owner); if (error) { kmem_free(bi); return error; } xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list); return 0; } /* Map an extent into a file. */ int xfs_bmap_map_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, struct xfs_bmbt_irec *PREV) { if (!xfs_bmap_is_update_needed(PREV)) return 0; return __xfs_bmap_add(mp, dfops, XFS_BMAP_MAP, ip, XFS_DATA_FORK, PREV); } /* Unmap an extent out of a file. */ int xfs_bmap_unmap_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, struct xfs_bmbt_irec *PREV) { if (!xfs_bmap_is_update_needed(PREV)) return 0; return __xfs_bmap_add(mp, dfops, XFS_BMAP_UNMAP, ip, XFS_DATA_FORK, PREV); } /* * Process one of the deferred bmap operations. We pass back the * btree cursor to maintain our lock on the bmapbt between calls. */ int xfs_bmap_finish_one( struct xfs_trans *tp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, enum xfs_bmap_intent_type type, int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state) { struct xfs_bmbt_irec bmap; int nimaps = 1; xfs_fsblock_t firstfsb; int flags = XFS_BMAPI_REMAP; int done; int error = 0; bmap.br_startblock = startblock; bmap.br_startoff = startoff; bmap.br_blockcount = blockcount; bmap.br_state = state; trace_xfs_bmap_deferred(tp->t_mountp, XFS_FSB_TO_AGNO(tp->t_mountp, startblock), type, XFS_FSB_TO_AGBNO(tp->t_mountp, startblock), ip->i_ino, whichfork, startoff, blockcount, state); if (whichfork != XFS_DATA_FORK && whichfork != XFS_ATTR_FORK) return -EFSCORRUPTED; if (whichfork == XFS_ATTR_FORK) flags |= XFS_BMAPI_ATTRFORK; if (XFS_TEST_ERROR(false, tp->t_mountp, XFS_ERRTAG_BMAP_FINISH_ONE, XFS_RANDOM_BMAP_FINISH_ONE)) return -EIO; switch (type) { case XFS_BMAP_MAP: firstfsb = bmap.br_startblock; error = xfs_bmapi_write(tp, ip, bmap.br_startoff, bmap.br_blockcount, flags, &firstfsb, bmap.br_blockcount, &bmap, &nimaps, dfops); break; case XFS_BMAP_UNMAP: error = xfs_bunmapi(tp, ip, bmap.br_startoff, bmap.br_blockcount, flags, 1, &firstfsb, dfops, &done); ASSERT(done); break; default: ASSERT(0); error = -EFSCORRUPTED; } return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_bmap.h0000644000000000000000000002346713063067171015745 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_BMAP_H__ #define __XFS_BMAP_H__ struct getbmap; struct xfs_bmbt_irec; struct xfs_ifork; struct xfs_inode; struct xfs_mount; struct xfs_trans; extern kmem_zone_t *xfs_bmap_free_item_zone; /* * Argument structure for xfs_bmap_alloc. */ struct xfs_bmalloca { xfs_fsblock_t *firstblock; /* i/o first block allocated */ struct xfs_defer_ops *dfops; /* bmap freelist */ struct xfs_trans *tp; /* transaction pointer */ struct xfs_inode *ip; /* incore inode pointer */ struct xfs_bmbt_irec prev; /* extent before the new one */ struct xfs_bmbt_irec got; /* extent after, or delayed */ xfs_fileoff_t offset; /* offset in file filling in */ xfs_extlen_t length; /* i/o length asked/allocated */ xfs_fsblock_t blkno; /* starting block of new extent */ struct xfs_btree_cur *cur; /* btree cursor */ xfs_extnum_t idx; /* current extent index */ int nallocs;/* number of extents alloc'd */ int logflags;/* flags for transaction logging */ xfs_extlen_t total; /* total blocks needed for xaction */ xfs_extlen_t minlen; /* minimum allocation size (blocks) */ xfs_extlen_t minleft; /* amount must be left after alloc */ bool eof; /* set if allocating past last extent */ bool wasdel; /* replacing a delayed allocation */ bool aeof; /* allocated space at eof */ bool conv; /* overwriting unwritten extents */ int datatype;/* data type being allocated */ int flags; }; /* * List of extents to be free "later". * The list is kept sorted on xbf_startblock. */ struct xfs_extent_free_item { xfs_fsblock_t xefi_startblock;/* starting fs block number */ xfs_extlen_t xefi_blockcount;/* number of blocks in extent */ struct list_head xefi_list; struct xfs_owner_info xefi_oinfo; /* extent owner */ }; #define XFS_BMAP_MAX_NMAP 4 /* * Flags for xfs_bmapi_* */ #define XFS_BMAPI_ENTIRE 0x001 /* return entire extent, not trimmed */ #define XFS_BMAPI_METADATA 0x002 /* mapping metadata not user data */ #define XFS_BMAPI_ATTRFORK 0x004 /* use attribute fork not data */ #define XFS_BMAPI_PREALLOC 0x008 /* preallocation op: unwritten space */ #define XFS_BMAPI_IGSTATE 0x010 /* Ignore state - */ /* combine contig. space */ #define XFS_BMAPI_CONTIG 0x020 /* must allocate only one extent */ /* * unwritten extent conversion - this needs write cache flushing and no additional * allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts * from written to unwritten, otherwise convert from unwritten to written. */ #define XFS_BMAPI_CONVERT 0x040 /* * allocate zeroed extents - this requires all newly allocated user data extents * to be initialised to zero. It will be ignored if XFS_BMAPI_METADATA is set. * Use in conjunction with XFS_BMAPI_CONVERT to convert unwritten extents found * during the allocation range to zeroed written extents. */ #define XFS_BMAPI_ZERO 0x080 /* * Map the inode offset to the block given in ap->firstblock. Primarily * used for reflink. The range must be in a hole, and this flag cannot be * turned on with PREALLOC or CONVERT, and cannot be used on the attr fork. * * For bunmapi, this flag unmaps the range without adjusting quota, reducing * refcount, or freeing the blocks. */ #define XFS_BMAPI_REMAP 0x100 /* Map something in the CoW fork. */ #define XFS_BMAPI_COWFORK 0x200 #define XFS_BMAPI_FLAGS \ { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ { XFS_BMAPI_METADATA, "METADATA" }, \ { XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \ { XFS_BMAPI_PREALLOC, "PREALLOC" }, \ { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ { XFS_BMAPI_CONTIG, "CONTIG" }, \ { XFS_BMAPI_CONVERT, "CONVERT" }, \ { XFS_BMAPI_ZERO, "ZERO" }, \ { XFS_BMAPI_REMAP, "REMAP" }, \ { XFS_BMAPI_COWFORK, "COWFORK" } static inline int xfs_bmapi_aflag(int w) { return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : (w == XFS_COW_FORK ? XFS_BMAPI_COWFORK : 0)); } static inline int xfs_bmapi_whichfork(int bmapi_flags) { if (bmapi_flags & XFS_BMAPI_COWFORK) return XFS_COW_FORK; else if (bmapi_flags & XFS_BMAPI_ATTRFORK) return XFS_ATTR_FORK; return XFS_DATA_FORK; } /* * Special values for xfs_bmbt_irec_t br_startblock field. */ #define DELAYSTARTBLOCK ((xfs_fsblock_t)-1LL) #define HOLESTARTBLOCK ((xfs_fsblock_t)-2LL) /* * Flags for xfs_bmap_add_extent*. */ #define BMAP_LEFT_CONTIG (1 << 0) #define BMAP_RIGHT_CONTIG (1 << 1) #define BMAP_LEFT_FILLING (1 << 2) #define BMAP_RIGHT_FILLING (1 << 3) #define BMAP_LEFT_DELAY (1 << 4) #define BMAP_RIGHT_DELAY (1 << 5) #define BMAP_LEFT_VALID (1 << 6) #define BMAP_RIGHT_VALID (1 << 7) #define BMAP_ATTRFORK (1 << 8) #define BMAP_COWFORK (1 << 9) #define XFS_BMAP_EXT_FLAGS \ { BMAP_LEFT_CONTIG, "LC" }, \ { BMAP_RIGHT_CONTIG, "RC" }, \ { BMAP_LEFT_FILLING, "LF" }, \ { BMAP_RIGHT_FILLING, "RF" }, \ { BMAP_ATTRFORK, "ATTR" }, \ { BMAP_COWFORK, "COW" } /* * This macro is used to determine how many extents will be shifted * in one write transaction. We could require two splits, * an extent move on the first and an extent merge on the second, * So it is proper that one extent is shifted inside write transaction * at a time. */ #define XFS_BMAP_MAX_SHIFT_EXTENTS 1 enum shift_direction { SHIFT_LEFT = 0, SHIFT_RIGHT, }; #ifdef DEBUG void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int whichfork, unsigned long caller_ip); #define XFS_BMAP_TRACE_EXLIST(ip,c,w) \ xfs_bmap_trace_exlist(ip,c,w, _THIS_IP_) #else #define XFS_BMAP_TRACE_EXLIST(ip,c,w) #endif void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno, xfs_filblks_t len); int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t bno, xfs_filblks_t len, struct xfs_owner_info *oinfo); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); int xfs_bmap_last_before(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *last_block, int whichfork); int xfs_bmap_last_offset(struct xfs_inode *ip, xfs_fileoff_t *unused, int whichfork); int xfs_bmap_one_block(struct xfs_inode *ip, int whichfork); int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip, int whichfork); int xfs_bmapi_read(struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, struct xfs_bmbt_irec *mval, int *nmap, int flags); int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_fsblock_t *firstblock, xfs_extlen_t total, struct xfs_bmbt_irec *mval, int *nmap, struct xfs_defer_ops *dfops); int __xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t *rlen, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, struct xfs_defer_ops *dfops); int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, struct xfs_defer_ops *dfops, int *done); int xfs_bmap_del_extent_delay(struct xfs_inode *ip, int whichfork, xfs_extnum_t *idx, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del); void xfs_bmap_del_extent_cow(struct xfs_inode *ip, xfs_extnum_t *idx, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del); int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, xfs_extnum_t num); uint xfs_default_attroffset(struct xfs_inode *ip); int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, struct xfs_defer_ops *dfops, enum shift_direction direction, int num_exts); int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); struct xfs_bmbt_rec_host * xfs_bmap_search_extents(struct xfs_inode *ip, xfs_fileoff_t bno, int fork, int *eofp, xfs_extnum_t *lastxp, struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp); int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork, xfs_fileoff_t aoff, xfs_filblks_t len, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *prev, xfs_extnum_t *lastx, int eof); struct xfs_bmbt_rec_host * xfs_bmap_search_extents(struct xfs_inode *ip, xfs_fileoff_t bno, int fork, int *eofp, xfs_extnum_t *lastxp, struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp); enum xfs_bmap_intent_type { XFS_BMAP_MAP = 1, XFS_BMAP_UNMAP, }; struct xfs_bmap_intent { struct list_head bi_list; enum xfs_bmap_intent_type bi_type; struct xfs_inode *bi_owner; int bi_whichfork; struct xfs_bmbt_irec bi_bmap; }; int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, enum xfs_bmap_intent_type type, int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state); int xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, struct xfs_bmbt_irec *imap); int xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, struct xfs_bmbt_irec *imap); #endif /* __XFS_BMAP_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_bmap_btree.c0000644000000000000000000005570213063067171017116 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_alloc.h" #include "xfs_btree.h" #include "xfs_bmap_btree.h" #include "xfs_bmap.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_rmap.h" /* * Determine the extent state. */ /* ARGSUSED */ STATIC xfs_exntst_t xfs_extent_state( xfs_filblks_t blks, int extent_flag) { if (extent_flag) { ASSERT(blks != 0); /* saved for DMIG */ return XFS_EXT_UNWRITTEN; } return XFS_EXT_NORM; } /* * Convert on-disk form of btree root to in-memory form. */ void xfs_bmdr_to_bmbt( struct xfs_inode *ip, xfs_bmdr_block_t *dblock, int dblocklen, struct xfs_btree_block *rblock, int rblocklen) { struct xfs_mount *mp = ip->i_mount; int dmxr; xfs_bmbt_key_t *fkp; __be64 *fpp; xfs_bmbt_key_t *tkp; __be64 *tpp; if (xfs_sb_version_hascrc(&mp->m_sb)) xfs_btree_init_block_int(mp, rblock, XFS_BUF_DADDR_NULL, XFS_BMAP_CRC_MAGIC, 0, 0, ip->i_ino, XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS); else xfs_btree_init_block_int(mp, rblock, XFS_BUF_DADDR_NULL, XFS_BMAP_MAGIC, 0, 0, ip->i_ino, XFS_BTREE_LONG_PTRS); rblock->bb_level = dblock->bb_level; ASSERT(be16_to_cpu(rblock->bb_level) > 0); rblock->bb_numrecs = dblock->bb_numrecs; dmxr = xfs_bmdr_maxrecs(dblocklen, 0); fkp = XFS_BMDR_KEY_ADDR(dblock, 1); tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); dmxr = be16_to_cpu(dblock->bb_numrecs); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr); } /* * Convert a compressed bmap extent record to an uncompressed form. * This code must be in sync with the routines xfs_bmbt_get_startoff, * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. */ STATIC void __xfs_bmbt_get_all( __uint64_t l0, __uint64_t l1, xfs_bmbt_irec_t *s) { int ext_flag; xfs_exntst_t st; ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN)); s->br_startoff = ((xfs_fileoff_t)l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; s->br_startblock = (((xfs_fsblock_t)l0 & xfs_mask64lo(9)) << 43) | (((xfs_fsblock_t)l1) >> 21); s->br_blockcount = (xfs_filblks_t)(l1 & xfs_mask64lo(21)); /* This is xfs_extent_state() in-line */ if (ext_flag) { ASSERT(s->br_blockcount != 0); /* saved for DMIG */ st = XFS_EXT_UNWRITTEN; } else st = XFS_EXT_NORM; s->br_state = st; } void xfs_bmbt_get_all( xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s) { __xfs_bmbt_get_all(r->l0, r->l1, s); } /* * Extract the blockcount field from an in memory bmap extent record. */ xfs_filblks_t xfs_bmbt_get_blockcount( xfs_bmbt_rec_host_t *r) { return (xfs_filblks_t)(r->l1 & xfs_mask64lo(21)); } /* * Extract the startblock field from an in memory bmap extent record. */ xfs_fsblock_t xfs_bmbt_get_startblock( xfs_bmbt_rec_host_t *r) { return (((xfs_fsblock_t)r->l0 & xfs_mask64lo(9)) << 43) | (((xfs_fsblock_t)r->l1) >> 21); } /* * Extract the startoff field from an in memory bmap extent record. */ xfs_fileoff_t xfs_bmbt_get_startoff( xfs_bmbt_rec_host_t *r) { return ((xfs_fileoff_t)r->l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; } xfs_exntst_t xfs_bmbt_get_state( xfs_bmbt_rec_host_t *r) { int ext_flag; ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN)); return xfs_extent_state(xfs_bmbt_get_blockcount(r), ext_flag); } /* * Extract the blockcount field from an on disk bmap extent record. */ xfs_filblks_t xfs_bmbt_disk_get_blockcount( xfs_bmbt_rec_t *r) { return (xfs_filblks_t)(be64_to_cpu(r->l1) & xfs_mask64lo(21)); } /* * Extract the startoff field from a disk format bmap extent record. */ xfs_fileoff_t xfs_bmbt_disk_get_startoff( xfs_bmbt_rec_t *r) { return ((xfs_fileoff_t)be64_to_cpu(r->l0) & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; } /* * Set all the fields in a bmap extent record from the arguments. */ void xfs_bmbt_set_allf( xfs_bmbt_rec_host_t *r, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state) { int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); ASSERT((startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)) == 0); ASSERT((blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); ASSERT((startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)) == 0); r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | ((xfs_bmbt_rec_base_t)startoff << 9) | ((xfs_bmbt_rec_base_t)startblock >> 43); r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | ((xfs_bmbt_rec_base_t)blockcount & (xfs_bmbt_rec_base_t)xfs_mask64lo(21)); } /* * Set all the fields in a bmap extent record from the uncompressed form. */ void xfs_bmbt_set_all( xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s) { xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock, s->br_blockcount, s->br_state); } /* * Set all the fields in a disk format bmap extent record from the arguments. */ void xfs_bmbt_disk_set_allf( xfs_bmbt_rec_t *r, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state) { int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); ASSERT((startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)) == 0); ASSERT((blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); ASSERT((startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)) == 0); r->l0 = cpu_to_be64( ((xfs_bmbt_rec_base_t)extent_flag << 63) | ((xfs_bmbt_rec_base_t)startoff << 9) | ((xfs_bmbt_rec_base_t)startblock >> 43)); r->l1 = cpu_to_be64( ((xfs_bmbt_rec_base_t)startblock << 21) | ((xfs_bmbt_rec_base_t)blockcount & (xfs_bmbt_rec_base_t)xfs_mask64lo(21))); } /* * Set all the fields in a bmap extent record from the uncompressed form. */ STATIC void xfs_bmbt_disk_set_all( xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s) { xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock, s->br_blockcount, s->br_state); } /* * Set the blockcount field in a bmap extent record. */ void xfs_bmbt_set_blockcount( xfs_bmbt_rec_host_t *r, xfs_filblks_t v) { ASSERT((v & xfs_mask64hi(43)) == 0); r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)xfs_mask64hi(43)) | (xfs_bmbt_rec_base_t)(v & xfs_mask64lo(21)); } /* * Set the startblock field in a bmap extent record. */ void xfs_bmbt_set_startblock( xfs_bmbt_rec_host_t *r, xfs_fsblock_t v) { ASSERT((v & xfs_mask64hi(12)) == 0); r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)xfs_mask64hi(55)) | (xfs_bmbt_rec_base_t)(v >> 43); r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)xfs_mask64lo(21)) | (xfs_bmbt_rec_base_t)(v << 21); } /* * Set the startoff field in a bmap extent record. */ void xfs_bmbt_set_startoff( xfs_bmbt_rec_host_t *r, xfs_fileoff_t v) { ASSERT((v & xfs_mask64hi(9)) == 0); r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) xfs_mask64hi(1)) | ((xfs_bmbt_rec_base_t)v << 9) | (r->l0 & (xfs_bmbt_rec_base_t)xfs_mask64lo(9)); } /* * Set the extent state field in a bmap extent record. */ void xfs_bmbt_set_state( xfs_bmbt_rec_host_t *r, xfs_exntst_t v) { ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN); if (v == XFS_EXT_NORM) r->l0 &= xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN); else r->l0 |= xfs_mask64hi(BMBT_EXNTFLAG_BITLEN); } /* * Convert in-memory form of btree root to on-disk form. */ void xfs_bmbt_to_bmdr( struct xfs_mount *mp, struct xfs_btree_block *rblock, int rblocklen, xfs_bmdr_block_t *dblock, int dblocklen) { int dmxr; xfs_bmbt_key_t *fkp; __be64 *fpp; xfs_bmbt_key_t *tkp; __be64 *tpp; if (xfs_sb_version_hascrc(&mp->m_sb)) { ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC)); ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid)); ASSERT(rblock->bb_u.l.bb_blkno == cpu_to_be64(XFS_BUF_DADDR_NULL)); } else ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_MAGIC)); ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK)); ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK)); ASSERT(rblock->bb_level != 0); dblock->bb_level = rblock->bb_level; dblock->bb_numrecs = rblock->bb_numrecs; dmxr = xfs_bmdr_maxrecs(dblocklen, 0); fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); tkp = XFS_BMDR_KEY_ADDR(dblock, 1); fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); dmxr = be16_to_cpu(dblock->bb_numrecs); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr); } /* * Check extent records, which have just been read, for * any bit in the extent flag field. ASSERT on debug * kernels, as this condition should not occur. * Return an error condition (1) if any flags found, * otherwise return 0. */ int xfs_check_nostate_extents( xfs_ifork_t *ifp, xfs_extnum_t idx, xfs_extnum_t num) { for (; num > 0; num--, idx++) { xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx); if ((ep->l0 >> (64 - BMBT_EXNTFLAG_BITLEN)) != 0) { ASSERT(0); return 1; } } return 0; } STATIC struct xfs_btree_cur * xfs_bmbt_dup_cursor( struct xfs_btree_cur *cur) { struct xfs_btree_cur *new; new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_private.b.ip, cur->bc_private.b.whichfork); /* * Copy the firstblock, dfops, and flags values, * since init cursor doesn't get them. */ new->bc_private.b.firstblock = cur->bc_private.b.firstblock; new->bc_private.b.dfops = cur->bc_private.b.dfops; new->bc_private.b.flags = cur->bc_private.b.flags; return new; } STATIC void xfs_bmbt_update_cursor( struct xfs_btree_cur *src, struct xfs_btree_cur *dst) { ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) || (dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME)); ASSERT(dst->bc_private.b.dfops == src->bc_private.b.dfops); dst->bc_private.b.allocated += src->bc_private.b.allocated; dst->bc_private.b.firstblock = src->bc_private.b.firstblock; src->bc_private.b.allocated = 0; } STATIC int xfs_bmbt_alloc_block( struct xfs_btree_cur *cur, union xfs_btree_ptr *start, union xfs_btree_ptr *new, int *stat) { xfs_alloc_arg_t args; /* block allocation args */ int error; /* error return value */ memset(&args, 0, sizeof(args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; args.fsbno = cur->bc_private.b.firstblock; args.firstblock = args.fsbno; xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_private.b.ip->i_ino, cur->bc_private.b.whichfork); if (args.fsbno == NULLFSBLOCK) { args.fsbno = be64_to_cpu(start->l); try_another_ag: args.type = XFS_ALLOCTYPE_START_BNO; /* * Make sure there is sufficient room left in the AG to * complete a full tree split for an extent insert. If * we are converting the middle part of an extent then * we may need space for two tree splits. * * We are relying on the caller to make the correct block * reservation for this operation to succeed. If the * reservation amount is insufficient then we may fail a * block allocation here and corrupt the filesystem. */ args.minleft = args.tp->t_blk_res; } else if (cur->bc_private.b.dfops->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; } args.minlen = args.maxlen = args.prod = 1; args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; if (!args.wasdel && args.tp->t_blk_res == 0) { error = -ENOSPC; goto error0; } error = xfs_alloc_vextent(&args); if (error) goto error0; /* * During a CoW operation, the allocation and bmbt updates occur in * different transactions. The mapping code tries to put new bmbt * blocks near extents being mapped, but the only way to guarantee this * is if the alloc and the mapping happen in a single transaction that * has a block reservation. That isn't the case here, so if we run out * of space we'll try again with another AG. */ if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && args.fsbno == NULLFSBLOCK && args.type == XFS_ALLOCTYPE_NEAR_BNO) { cur->bc_private.b.dfops->dop_low = true; args.fsbno = cur->bc_private.b.firstblock; goto try_another_ag; } if (args.fsbno == NULLFSBLOCK && args.minleft) { /* * Could not find an AG with enough free space to satisfy * a full btree split. Try again without minleft and if * successful activate the lowspace algorithm. */ args.fsbno = 0; args.type = XFS_ALLOCTYPE_FIRST_AG; args.minleft = 0; error = xfs_alloc_vextent(&args); if (error) goto error0; cur->bc_private.b.dfops->dop_low = true; } if (args.fsbno == NULLFSBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } ASSERT(args.len == 1); cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; cur->bc_private.b.ip->i_d.di_nblocks++; xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); xfs_trans_mod_dquot_byino(args.tp, cur->bc_private.b.ip, XFS_TRANS_DQ_BCOUNT, 1L); new->l = cpu_to_be64(args.fsbno); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } STATIC int xfs_bmbt_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { struct xfs_mount *mp = cur->bc_mp; struct xfs_inode *ip = cur->bc_private.b.ip; struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); struct xfs_owner_info oinfo; xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork); xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); return 0; } STATIC int xfs_bmbt_get_minrecs( struct xfs_btree_cur *cur, int level) { if (level == cur->bc_nlevels - 1) { struct xfs_ifork *ifp; ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); return xfs_bmbt_maxrecs(cur->bc_mp, ifp->if_broot_bytes, level == 0) / 2; } return cur->bc_mp->m_bmap_dmnr[level != 0]; } int xfs_bmbt_get_maxrecs( struct xfs_btree_cur *cur, int level) { if (level == cur->bc_nlevels - 1) { struct xfs_ifork *ifp; ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); return xfs_bmbt_maxrecs(cur->bc_mp, ifp->if_broot_bytes, level == 0); } return cur->bc_mp->m_bmap_dmxr[level != 0]; } /* * Get the maximum records we could store in the on-disk format. * * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but * for the root node this checks the available space in the dinode fork * so that we can resize the in-memory buffer to match it. After a * resize to the maximum size this function returns the same value * as xfs_bmbt_get_maxrecs for the root node, too. */ STATIC int xfs_bmbt_get_dmaxrecs( struct xfs_btree_cur *cur, int level) { if (level != cur->bc_nlevels - 1) return cur->bc_mp->m_bmap_dmxr[level != 0]; return xfs_bmdr_maxrecs(cur->bc_private.b.forksize, level == 0); } STATIC void xfs_bmbt_init_key_from_rec( union xfs_btree_key *key, union xfs_btree_rec *rec) { key->bmbt.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt)); } STATIC void xfs_bmbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) { xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b); } STATIC void xfs_bmbt_init_ptr_from_cur( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { ptr->l = 0; } STATIC __int64_t xfs_bmbt_key_diff( struct xfs_btree_cur *cur, union xfs_btree_key *key) { return (__int64_t)be64_to_cpu(key->bmbt.br_startoff) - cur->bc_rec.b.br_startoff; } static bool xfs_bmbt_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); unsigned int level; switch (block->bb_magic) { case cpu_to_be32(XFS_BMAP_CRC_MAGIC): if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(block->bb_u.l.bb_blkno) != bp->b_bn) return false; /* * XXX: need a better way of verifying the owner here. Right now * just make sure there has been one set. */ if (be64_to_cpu(block->bb_u.l.bb_owner) == 0) return false; /* fall through */ case cpu_to_be32(XFS_BMAP_MAGIC): break; default: return false; } /* * numrecs and level verification. * * We don't know what fork we belong to, so just verify that the level * is less than the maximum of the two. Later checks will be more * precise. */ level = be16_to_cpu(block->bb_level); if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1])) return false; if (be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0]) return false; /* sibling pointer verification */ if (!block->bb_u.l.bb_leftsib || (block->bb_u.l.bb_leftsib != cpu_to_be64(NULLFSBLOCK) && !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_leftsib)))) return false; if (!block->bb_u.l.bb_rightsib || (block->bb_u.l.bb_rightsib != cpu_to_be64(NULLFSBLOCK) && !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_rightsib)))) return false; return true; } static void xfs_bmbt_read_verify( struct xfs_buf *bp) { if (!xfs_btree_lblock_verify_crc(bp)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_bmbt_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_verifier_error(bp); } } static void xfs_bmbt_write_verify( struct xfs_buf *bp) { if (!xfs_bmbt_verify(bp)) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } xfs_btree_lblock_calc_crc(bp); } const struct xfs_buf_ops xfs_bmbt_buf_ops = { .name = "xfs_bmbt", .verify_read = xfs_bmbt_read_verify, .verify_write = xfs_bmbt_write_verify, }; #if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_bmbt_keys_inorder( struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2) { return be64_to_cpu(k1->bmbt.br_startoff) < be64_to_cpu(k2->bmbt.br_startoff); } STATIC int xfs_bmbt_recs_inorder( struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2) { return xfs_bmbt_disk_get_startoff(&r1->bmbt) + xfs_bmbt_disk_get_blockcount(&r1->bmbt) <= xfs_bmbt_disk_get_startoff(&r2->bmbt); } #endif /* DEBUG */ static const struct xfs_btree_ops xfs_bmbt_ops = { .rec_len = sizeof(xfs_bmbt_rec_t), .key_len = sizeof(xfs_bmbt_key_t), .dup_cursor = xfs_bmbt_dup_cursor, .update_cursor = xfs_bmbt_update_cursor, .alloc_block = xfs_bmbt_alloc_block, .free_block = xfs_bmbt_free_block, .get_maxrecs = xfs_bmbt_get_maxrecs, .get_minrecs = xfs_bmbt_get_minrecs, .get_dmaxrecs = xfs_bmbt_get_dmaxrecs, .init_key_from_rec = xfs_bmbt_init_key_from_rec, .init_rec_from_cur = xfs_bmbt_init_rec_from_cur, .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, .key_diff = xfs_bmbt_key_diff, .buf_ops = &xfs_bmbt_buf_ops, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_bmbt_keys_inorder, .recs_inorder = xfs_bmbt_recs_inorder, #endif }; /* * Allocate a new bmap btree cursor. */ struct xfs_btree_cur * /* new bmap btree cursor */ xfs_bmbt_init_cursor( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ struct xfs_inode *ip, /* inode owning the btree */ int whichfork) /* data or attr fork */ { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_btree_cur *cur; ASSERT(whichfork != XFS_COW_FORK); cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); cur->bc_tp = tp; cur->bc_mp = mp; cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1; cur->bc_btnum = XFS_BTNUM_BMAP; cur->bc_blocklog = mp->m_sb.sb_blocklog; cur->bc_ops = &xfs_bmbt_ops; cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE; if (xfs_sb_version_hascrc(&mp->m_sb)) cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork); cur->bc_private.b.ip = ip; cur->bc_private.b.firstblock = NULLFSBLOCK; cur->bc_private.b.dfops = NULL; cur->bc_private.b.allocated = 0; cur->bc_private.b.flags = 0; cur->bc_private.b.whichfork = whichfork; return cur; } /* * Calculate number of records in a bmap btree block. */ int xfs_bmbt_maxrecs( struct xfs_mount *mp, int blocklen, int leaf) { blocklen -= XFS_BMBT_BLOCK_LEN(mp); if (leaf) return blocklen / sizeof(xfs_bmbt_rec_t); return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)); } /* * Calculate number of records in a bmap btree inode root. */ int xfs_bmdr_maxrecs( int blocklen, int leaf) { blocklen -= sizeof(xfs_bmdr_block_t); if (leaf) return blocklen / sizeof(xfs_bmdr_rec_t); return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t)); } /* * Change the owner of a btree format fork fo the inode passed in. Change it to * the owner of that is passed in so that we can change owners before or after * we switch forks between inodes. The operation that the caller is doing will * determine whether is needs to change owner before or after the switch. * * For demand paged transactional modification, the fork switch should be done * after reading in all the blocks, modifying them and pinning them in the * transaction. For modification when the buffers are already pinned in memory, * the fork switch can be done before changing the owner as we won't need to * validate the owner until the btree buffers are unpinned and writes can occur * again. * * For recovery based ownership change, there is no transactional context and * so a buffer list must be supplied so that we can record the buffers that we * modified for the caller to issue IO on. */ int xfs_bmbt_change_owner( struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, xfs_ino_t new_owner, struct list_head *buffer_list) { struct xfs_btree_cur *cur; int error; ASSERT(tp || buffer_list); ASSERT(!(tp && buffer_list)); if (whichfork == XFS_DATA_FORK) ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_BTREE); else ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE); cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork); if (!cur) return -ENOMEM; error = xfs_btree_change_owner(cur, new_owner, buffer_list); xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_bmap_btree.h0000644000000000000000000001200713063067171017112 0ustar /* * Copyright (c) 2000,2002-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_BMAP_BTREE_H__ #define __XFS_BMAP_BTREE_H__ struct xfs_btree_cur; struct xfs_btree_block; struct xfs_mount; struct xfs_inode; struct xfs_trans; /* * Extent state and extent format macros. */ #define XFS_EXTFMT_INODE(x) \ (xfs_sb_version_hasextflgbit(&((x)->i_mount->m_sb)) ? \ XFS_EXTFMT_HASSTATE : XFS_EXTFMT_NOSTATE) #define ISUNWRITTEN(x) ((x)->br_state == XFS_EXT_UNWRITTEN) /* * Btree block header size depends on a superblock flag. */ #define XFS_BMBT_BLOCK_LEN(mp) \ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ XFS_BTREE_LBLOCK_CRC_LEN : XFS_BTREE_LBLOCK_LEN) #define XFS_BMBT_REC_ADDR(mp, block, index) \ ((xfs_bmbt_rec_t *) \ ((char *)(block) + \ XFS_BMBT_BLOCK_LEN(mp) + \ ((index) - 1) * sizeof(xfs_bmbt_rec_t))) #define XFS_BMBT_KEY_ADDR(mp, block, index) \ ((xfs_bmbt_key_t *) \ ((char *)(block) + \ XFS_BMBT_BLOCK_LEN(mp) + \ ((index) - 1) * sizeof(xfs_bmbt_key_t))) #define XFS_BMBT_PTR_ADDR(mp, block, index, maxrecs) \ ((xfs_bmbt_ptr_t *) \ ((char *)(block) + \ XFS_BMBT_BLOCK_LEN(mp) + \ (maxrecs) * sizeof(xfs_bmbt_key_t) + \ ((index) - 1) * sizeof(xfs_bmbt_ptr_t))) #define XFS_BMDR_REC_ADDR(block, index) \ ((xfs_bmdr_rec_t *) \ ((char *)(block) + \ sizeof(struct xfs_bmdr_block) + \ ((index) - 1) * sizeof(xfs_bmdr_rec_t))) #define XFS_BMDR_KEY_ADDR(block, index) \ ((xfs_bmdr_key_t *) \ ((char *)(block) + \ sizeof(struct xfs_bmdr_block) + \ ((index) - 1) * sizeof(xfs_bmdr_key_t))) #define XFS_BMDR_PTR_ADDR(block, index, maxrecs) \ ((xfs_bmdr_ptr_t *) \ ((char *)(block) + \ sizeof(struct xfs_bmdr_block) + \ (maxrecs) * sizeof(xfs_bmdr_key_t) + \ ((index) - 1) * sizeof(xfs_bmdr_ptr_t))) /* * These are to be used when we know the size of the block and * we don't have a cursor. */ #define XFS_BMAP_BROOT_PTR_ADDR(mp, bb, i, sz) \ XFS_BMBT_PTR_ADDR(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0)) #define XFS_BMAP_BROOT_SPACE_CALC(mp, nrecs) \ (int)(XFS_BMBT_BLOCK_LEN(mp) + \ ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) #define XFS_BMAP_BROOT_SPACE(mp, bb) \ (XFS_BMAP_BROOT_SPACE_CALC(mp, be16_to_cpu((bb)->bb_numrecs))) #define XFS_BMDR_SPACE_CALC(nrecs) \ (int)(sizeof(xfs_bmdr_block_t) + \ ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) #define XFS_BMAP_BMDR_SPACE(bb) \ (XFS_BMDR_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs))) /* * Maximum number of bmap btree levels. */ #define XFS_BM_MAXLEVELS(mp,w) ((mp)->m_bm_maxlevels[(w)]) /* * Prototypes for xfs_bmap.c to call. */ extern void xfs_bmdr_to_bmbt(struct xfs_inode *, xfs_bmdr_block_t *, int, struct xfs_btree_block *, int); extern void xfs_bmbt_get_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s); extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_host_t *r); extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_host_t *r); extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_host_t *r); extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_host_t *r); extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r); extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r); extern void xfs_bmbt_set_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s); extern void xfs_bmbt_set_allf(xfs_bmbt_rec_host_t *r, xfs_fileoff_t o, xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v); extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_host_t *r, xfs_filblks_t v); extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_host_t *r, xfs_fsblock_t v); extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_host_t *r, xfs_fileoff_t v); extern void xfs_bmbt_set_state(xfs_bmbt_rec_host_t *r, xfs_exntst_t v); extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o, xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v); extern void xfs_bmbt_to_bmdr(struct xfs_mount *, struct xfs_btree_block *, int, xfs_bmdr_block_t *, int); extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level); extern int xfs_bmdr_maxrecs(int blocklen, int leaf); extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf); extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, xfs_ino_t new_owner, struct list_head *buffer_list); extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, struct xfs_trans *, struct xfs_inode *, int); #endif /* __XFS_BMAP_BTREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_btree.c0000644000000000000000000037603613063067171016125 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_btree.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_alloc.h" /* * Cursor allocation zone. */ kmem_zone_t *xfs_btree_cur_zone; /* * Btree magic numbers. */ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, XFS_FIBT_MAGIC, 0 }, { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC, XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC, XFS_REFC_CRC_MAGIC } }; #define xfs_btree_magic(cur) \ xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] STATIC int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_lblock( struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_btree_block *block, /* btree long form block pointer */ int level, /* level of the btree block */ struct xfs_buf *bp) /* buffer for block, if any */ { int lblock_ok = 1; /* block passes checks */ struct xfs_mount *mp; /* file system mount point */ mp = cur->bc_mp; if (xfs_sb_version_hascrc(&mp->m_sb)) { lblock_ok = lblock_ok && uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid) && block->bb_u.l.bb_blkno == cpu_to_be64( bp ? bp->b_bn : XFS_BUF_DADDR_NULL); } lblock_ok = lblock_ok && be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) && be16_to_cpu(block->bb_level) == level && be16_to_cpu(block->bb_numrecs) <= cur->bc_ops->get_maxrecs(cur, level) && block->bb_u.l.bb_leftsib && (block->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK) || XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_leftsib))) && block->bb_u.l.bb_rightsib && (block->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK) || XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_rightsib))); if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK, XFS_RANDOM_BTREE_CHECK_LBLOCK))) { if (bp) trace_xfs_btree_corrupt(bp, _RET_IP_); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } return 0; } STATIC int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_sblock( struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_btree_block *block, /* btree short form block pointer */ int level, /* level of the btree block */ struct xfs_buf *bp) /* buffer containing block */ { struct xfs_mount *mp; /* file system mount point */ struct xfs_buf *agbp; /* buffer for ag. freespace struct */ struct xfs_agf *agf; /* ag. freespace structure */ xfs_agblock_t agflen; /* native ag. freespace length */ int sblock_ok = 1; /* block passes checks */ mp = cur->bc_mp; agbp = cur->bc_private.a.agbp; agf = XFS_BUF_TO_AGF(agbp); agflen = be32_to_cpu(agf->agf_length); if (xfs_sb_version_hascrc(&mp->m_sb)) { sblock_ok = sblock_ok && uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid) && block->bb_u.s.bb_blkno == cpu_to_be64( bp ? bp->b_bn : XFS_BUF_DADDR_NULL); } sblock_ok = sblock_ok && be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) && be16_to_cpu(block->bb_level) == level && be16_to_cpu(block->bb_numrecs) <= cur->bc_ops->get_maxrecs(cur, level) && (block->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK) || be32_to_cpu(block->bb_u.s.bb_leftsib) < agflen) && block->bb_u.s.bb_leftsib && (block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK) || be32_to_cpu(block->bb_u.s.bb_rightsib) < agflen) && block->bb_u.s.bb_rightsib; if (unlikely(XFS_TEST_ERROR(!sblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_SBLOCK, XFS_RANDOM_BTREE_CHECK_SBLOCK))) { if (bp) trace_xfs_btree_corrupt(bp, _RET_IP_); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } return 0; } /* * Debug routine: check that block header is ok. */ int xfs_btree_check_block( struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_btree_block *block, /* generic btree block pointer */ int level, /* level of the btree block */ struct xfs_buf *bp) /* buffer containing block, if any */ { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) return xfs_btree_check_lblock(cur, block, level, bp); else return xfs_btree_check_sblock(cur, block, level, bp); } /* * Check that (long) pointer is ok. */ int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_lptr( struct xfs_btree_cur *cur, /* btree cursor */ xfs_fsblock_t bno, /* btree block disk address */ int level) /* btree block level */ { XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, level > 0 && bno != NULLFSBLOCK && XFS_FSB_SANITY_CHECK(cur->bc_mp, bno)); return 0; } #ifdef DEBUG /* * Check that (short) pointer is ok. */ STATIC int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_sptr( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t bno, /* btree block disk address */ int level) /* btree block level */ { xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, level > 0 && bno != NULLAGBLOCK && bno != 0 && bno < agblocks); return 0; } /* * Check that block ptr is ok. */ STATIC int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_ptr( struct xfs_btree_cur *cur, /* btree cursor */ union xfs_btree_ptr *ptr, /* btree block disk address */ int index, /* offset from ptr to check */ int level) /* btree block level */ { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { return xfs_btree_check_lptr(cur, be64_to_cpu((&ptr->l)[index]), level); } else { return xfs_btree_check_sptr(cur, be32_to_cpu((&ptr->s)[index]), level); } } #endif /* * Calculate CRC on the whole btree block and stuff it into the * long-form btree header. * * Prior to calculting the CRC, pull the LSN out of the buffer log item and put * it into the buffer so recovery knows what the last modification was that made * it to disk. */ void xfs_btree_lblock_calc_crc( struct xfs_buf *bp) { struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_buf_log_item *bip = bp->b_fspriv; if (!xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) return; if (bip) block->bb_u.l.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF); } bool xfs_btree_lblock_verify_crc( struct xfs_buf *bp) { struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) { if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.l.bb_lsn))) return false; return xfs_buf_verify_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF); } return true; } /* * Calculate CRC on the whole btree block and stuff it into the * short-form btree header. * * Prior to calculting the CRC, pull the LSN out of the buffer log item and put * it into the buffer so recovery knows what the last modification was that made * it to disk. */ void xfs_btree_sblock_calc_crc( struct xfs_buf *bp) { struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_buf_log_item *bip = bp->b_fspriv; if (!xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) return; if (bip) block->bb_u.s.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF); } bool xfs_btree_sblock_verify_crc( struct xfs_buf *bp) { struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) { if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.s.bb_lsn))) return false; return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF); } return true; } static int xfs_btree_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { int error; error = cur->bc_ops->free_block(cur, bp); if (!error) { xfs_trans_binval(cur->bc_tp, bp); XFS_BTREE_STATS_INC(cur, free); } return error; } /* * Delete the btree cursor. */ void xfs_btree_del_cursor( xfs_btree_cur_t *cur, /* btree cursor */ int error) /* del because of error */ { int i; /* btree level */ /* * Clear the buffer pointers, and release the buffers. * If we're doing this in the face of an error, we * need to make sure to inspect all of the entries * in the bc_bufs array for buffers to be unlocked. * This is because some of the btree code works from * level n down to 0, and if we get an error along * the way we won't have initialized all the entries * down to 0. */ for (i = 0; i < cur->bc_nlevels; i++) { if (cur->bc_bufs[i]) xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); else if (!error) break; } /* * Can't free a bmap cursor without having dealt with the * allocated indirect blocks' accounting. */ ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP || cur->bc_private.b.allocated == 0); /* * Free the cursor. */ kmem_zone_free(xfs_btree_cur_zone, cur); } /* * Duplicate the btree cursor. * Allocate a new one, copy the record, re-get the buffers. */ int /* error */ xfs_btree_dup_cursor( xfs_btree_cur_t *cur, /* input cursor */ xfs_btree_cur_t **ncur) /* output cursor */ { xfs_buf_t *bp; /* btree block's buffer pointer */ int error; /* error return value */ int i; /* level number of btree block */ xfs_mount_t *mp; /* mount structure for filesystem */ xfs_btree_cur_t *new; /* new cursor value */ xfs_trans_t *tp; /* transaction pointer, can be NULL */ tp = cur->bc_tp; mp = cur->bc_mp; /* * Allocate a new cursor like the old one. */ new = cur->bc_ops->dup_cursor(cur); /* * Copy the record currently in the cursor. */ new->bc_rec = cur->bc_rec; /* * For each level current, re-get the buffer and copy the ptr value. */ for (i = 0; i < new->bc_nlevels; i++) { new->bc_ptrs[i] = cur->bc_ptrs[i]; new->bc_ra[i] = cur->bc_ra[i]; bp = cur->bc_bufs[i]; if (bp) { error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp, cur->bc_ops->buf_ops); if (error) { xfs_btree_del_cursor(new, error); *ncur = NULL; return error; } } new->bc_bufs[i] = bp; } *ncur = new; return 0; } /* * XFS btree block layout and addressing: * * There are two types of blocks in the btree: leaf and non-leaf blocks. * * The leaf record start with a header then followed by records containing * the values. A non-leaf block also starts with the same header, and * then first contains lookup keys followed by an equal number of pointers * to the btree blocks at the previous level. * * +--------+-------+-------+-------+-------+-------+-------+ * Leaf: | header | rec 1 | rec 2 | rec 3 | rec 4 | rec 5 | rec N | * +--------+-------+-------+-------+-------+-------+-------+ * * +--------+-------+-------+-------+-------+-------+-------+ * Non-Leaf: | header | key 1 | key 2 | key N | ptr 1 | ptr 2 | ptr N | * +--------+-------+-------+-------+-------+-------+-------+ * * The header is called struct xfs_btree_block for reasons better left unknown * and comes in different versions for short (32bit) and long (64bit) block * pointers. The record and key structures are defined by the btree instances * and opaque to the btree core. The block pointers are simple disk endian * integers, available in a short (32bit) and long (64bit) variant. * * The helpers below calculate the offset of a given record, key or pointer * into a btree block (xfs_btree_*_offset) or return a pointer to the given * record, key or pointer (xfs_btree_*_addr). Note that all addressing * inside the btree block is done using indices starting at one, not zero! * * If XFS_BTREE_OVERLAPPING is set, then this btree supports keys containing * overlapping intervals. In such a tree, records are still sorted lowest to * highest and indexed by the smallest key value that refers to the record. * However, nodes are different: each pointer has two associated keys -- one * indexing the lowest key available in the block(s) below (the same behavior * as the key in a regular btree) and another indexing the highest key * available in the block(s) below. Because records are /not/ sorted by the * highest key, all leaf block updates require us to compute the highest key * that matches any record in the leaf and to recursively update the high keys * in the nodes going further up in the tree, if necessary. Nodes look like * this: * * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ * Non-Leaf: | header | lo1 | hi1 | lo2 | hi2 | ... | ptr 1 | ptr 2 | ... | * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ * * To perform an interval query on an overlapped tree, perform the usual * depth-first search and use the low and high keys to decide if we can skip * that particular node. If a leaf node is reached, return the records that * intersect the interval. Note that an interval query may return numerous * entries. For a non-overlapped tree, simply search for the record associated * with the lowest key and iterate forward until a non-matching record is * found. Section 14.3 ("Interval Trees") of _Introduction to Algorithms_ by * Cormen, Leiserson, Rivest, and Stein (2nd or 3rd ed. only) discuss this in * more detail. * * Why do we care about overlapping intervals? Let's say you have a bunch of * reverse mapping records on a reflink filesystem: * * 1: +- file A startblock B offset C length D -----------+ * 2: +- file E startblock F offset G length H --------------+ * 3: +- file I startblock F offset J length K --+ * 4: +- file L... --+ * * Now say we want to map block (B+D) into file A at offset (C+D). Ideally, * we'd simply increment the length of record 1. But how do we find the record * that ends at (B+D-1) (i.e. record 1)? A LE lookup of (B+D-1) would return * record 3 because the keys are ordered first by startblock. An interval * query would return records 1 and 2 because they both overlap (B+D-1), and * from that we can pick out record 1 as the appropriate left neighbor. * * In the non-overlapped case you can do a LE lookup and decrement the cursor * because a record's interval must end before the next record. */ /* * Return size of the btree block header for this btree instance. */ static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur) { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) return XFS_BTREE_LBLOCK_CRC_LEN; return XFS_BTREE_LBLOCK_LEN; } if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) return XFS_BTREE_SBLOCK_CRC_LEN; return XFS_BTREE_SBLOCK_LEN; } /* * Return size of btree block pointers for this btree instance. */ static inline size_t xfs_btree_ptr_len(struct xfs_btree_cur *cur) { return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? sizeof(__be64) : sizeof(__be32); } /* * Calculate offset of the n-th record in a btree block. */ STATIC size_t xfs_btree_rec_offset( struct xfs_btree_cur *cur, int n) { return xfs_btree_block_len(cur) + (n - 1) * cur->bc_ops->rec_len; } /* * Calculate offset of the n-th key in a btree block. */ STATIC size_t xfs_btree_key_offset( struct xfs_btree_cur *cur, int n) { return xfs_btree_block_len(cur) + (n - 1) * cur->bc_ops->key_len; } /* * Calculate offset of the n-th high key in a btree block. */ STATIC size_t xfs_btree_high_key_offset( struct xfs_btree_cur *cur, int n) { return xfs_btree_block_len(cur) + (n - 1) * cur->bc_ops->key_len + (cur->bc_ops->key_len / 2); } /* * Calculate offset of the n-th block pointer in a btree block. */ STATIC size_t xfs_btree_ptr_offset( struct xfs_btree_cur *cur, int n, int level) { return xfs_btree_block_len(cur) + cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len + (n - 1) * xfs_btree_ptr_len(cur); } /* * Return a pointer to the n-th record in the btree block. */ STATIC union xfs_btree_rec * xfs_btree_rec_addr( struct xfs_btree_cur *cur, int n, struct xfs_btree_block *block) { return (union xfs_btree_rec *) ((char *)block + xfs_btree_rec_offset(cur, n)); } /* * Return a pointer to the n-th key in the btree block. */ STATIC union xfs_btree_key * xfs_btree_key_addr( struct xfs_btree_cur *cur, int n, struct xfs_btree_block *block) { return (union xfs_btree_key *) ((char *)block + xfs_btree_key_offset(cur, n)); } /* * Return a pointer to the n-th high key in the btree block. */ STATIC union xfs_btree_key * xfs_btree_high_key_addr( struct xfs_btree_cur *cur, int n, struct xfs_btree_block *block) { return (union xfs_btree_key *) ((char *)block + xfs_btree_high_key_offset(cur, n)); } /* * Return a pointer to the n-th block pointer in the btree block. */ STATIC union xfs_btree_ptr * xfs_btree_ptr_addr( struct xfs_btree_cur *cur, int n, struct xfs_btree_block *block) { int level = xfs_btree_get_level(block); ASSERT(block->bb_level != 0); return (union xfs_btree_ptr *) ((char *)block + xfs_btree_ptr_offset(cur, n, level)); } /* * Get the root block which is stored in the inode. * * For now this btree implementation assumes the btree root is always * stored in the if_broot field of an inode fork. */ STATIC struct xfs_btree_block * xfs_btree_get_iroot( struct xfs_btree_cur *cur) { struct xfs_ifork *ifp; ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); return (struct xfs_btree_block *)ifp->if_broot; } /* * Retrieve the block pointer from the cursor at the given level. * This may be an inode btree root or from a buffer. */ STATIC struct xfs_btree_block * /* generic btree block pointer */ xfs_btree_get_block( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level in btree */ struct xfs_buf **bpp) /* buffer containing the block */ { if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && (level == cur->bc_nlevels - 1)) { *bpp = NULL; return xfs_btree_get_iroot(cur); } *bpp = cur->bc_bufs[level]; return XFS_BUF_TO_BLOCK(*bpp); } /* * Get a buffer for the block, return it with no data read. * Long-form addressing. */ xfs_buf_t * /* buffer for fsbno */ xfs_btree_get_bufl( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_fsblock_t fsbno, /* file system block number */ uint lock) /* lock flags for get_buf */ { xfs_daddr_t d; /* real disk block address */ ASSERT(fsbno != NULLFSBLOCK); d = XFS_FSB_TO_DADDR(mp, fsbno); return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); } /* * Get a buffer for the block, return it with no data read. * Short-form addressing. */ xfs_buf_t * /* buffer for agno/agbno */ xfs_btree_get_bufs( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t agbno, /* allocation group block number */ uint lock) /* lock flags for get_buf */ { xfs_daddr_t d; /* real disk block address */ ASSERT(agno != NULLAGNUMBER); ASSERT(agbno != NULLAGBLOCK); d = XFS_AGB_TO_DADDR(mp, agno, agbno); return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); } /* * Check for the cursor referring to the last block at the given level. */ int /* 1=is last block, 0=not last block */ xfs_btree_islastblock( xfs_btree_cur_t *cur, /* btree cursor */ int level) /* level to check */ { struct xfs_btree_block *block; /* generic btree block pointer */ xfs_buf_t *bp; /* buffer containing block */ block = xfs_btree_get_block(cur, level, &bp); xfs_btree_check_block(cur, block, level, bp); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) return block->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK); else return block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK); } /* * Change the cursor to point to the first record at the given level. * Other levels are unaffected. */ STATIC int /* success=1, failure=0 */ xfs_btree_firstrec( xfs_btree_cur_t *cur, /* btree cursor */ int level) /* level to change */ { struct xfs_btree_block *block; /* generic btree block pointer */ xfs_buf_t *bp; /* buffer containing block */ /* * Get the block pointer for this level. */ block = xfs_btree_get_block(cur, level, &bp); xfs_btree_check_block(cur, block, level, bp); /* * It's empty, there is no such record. */ if (!block->bb_numrecs) return 0; /* * Set the ptr value to 1, that's the first record/key. */ cur->bc_ptrs[level] = 1; return 1; } /* * Change the cursor to point to the last record in the current block * at the given level. Other levels are unaffected. */ STATIC int /* success=1, failure=0 */ xfs_btree_lastrec( xfs_btree_cur_t *cur, /* btree cursor */ int level) /* level to change */ { struct xfs_btree_block *block; /* generic btree block pointer */ xfs_buf_t *bp; /* buffer containing block */ /* * Get the block pointer for this level. */ block = xfs_btree_get_block(cur, level, &bp); xfs_btree_check_block(cur, block, level, bp); /* * It's empty, there is no such record. */ if (!block->bb_numrecs) return 0; /* * Set the ptr value to numrecs, that's the last record/key. */ cur->bc_ptrs[level] = be16_to_cpu(block->bb_numrecs); return 1; } /* * Compute first and last byte offsets for the fields given. * Interprets the offsets table, which contains struct field offsets. */ void xfs_btree_offsets( __int64_t fields, /* bitmask of fields */ const short *offsets, /* table of field offsets */ int nbits, /* number of bits to inspect */ int *first, /* output: first byte offset */ int *last) /* output: last byte offset */ { int i; /* current bit number */ __int64_t imask; /* mask for current bit number */ ASSERT(fields != 0); /* * Find the lowest bit, so the first byte offset. */ for (i = 0, imask = 1LL; ; i++, imask <<= 1) { if (imask & fields) { *first = offsets[i]; break; } } /* * Find the highest bit, so the last byte offset. */ for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) { if (imask & fields) { *last = offsets[i + 1] - 1; break; } } } /* * Get a buffer for the block, return it read in. * Long-form addressing. */ int xfs_btree_read_bufl( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t fsbno, /* file system block number */ uint lock, /* lock flags for read_buf */ struct xfs_buf **bpp, /* buffer for fsbno */ int refval, /* ref count value for buffer */ const struct xfs_buf_ops *ops) { struct xfs_buf *bp; /* return value */ xfs_daddr_t d; /* real disk block address */ int error; ASSERT(fsbno != NULLFSBLOCK); d = XFS_FSB_TO_DADDR(mp, fsbno); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, mp->m_bsize, lock, &bp, ops); if (error) return error; if (bp) xfs_buf_set_ref(bp, refval); *bpp = bp; return 0; } /* * Read-ahead the block, don't wait for it, don't return a buffer. * Long-form addressing. */ /* ARGSUSED */ void xfs_btree_reada_bufl( struct xfs_mount *mp, /* file system mount point */ xfs_fsblock_t fsbno, /* file system block number */ xfs_extlen_t count, /* count of filesystem blocks */ const struct xfs_buf_ops *ops) { xfs_daddr_t d; ASSERT(fsbno != NULLFSBLOCK); d = XFS_FSB_TO_DADDR(mp, fsbno); xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, ops); } /* * Read-ahead the block, don't wait for it, don't return a buffer. * Short-form addressing. */ /* ARGSUSED */ void xfs_btree_reada_bufs( struct xfs_mount *mp, /* file system mount point */ xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t agbno, /* allocation group block number */ xfs_extlen_t count, /* count of filesystem blocks */ const struct xfs_buf_ops *ops) { xfs_daddr_t d; ASSERT(agno != NULLAGNUMBER); ASSERT(agbno != NULLAGBLOCK); d = XFS_AGB_TO_DADDR(mp, agno, agbno); xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, ops); } STATIC int xfs_btree_readahead_lblock( struct xfs_btree_cur *cur, int lr, struct xfs_btree_block *block) { int rval = 0; xfs_fsblock_t left = be64_to_cpu(block->bb_u.l.bb_leftsib); xfs_fsblock_t right = be64_to_cpu(block->bb_u.l.bb_rightsib); if ((lr & XFS_BTCUR_LEFTRA) && left != NULLFSBLOCK) { xfs_btree_reada_bufl(cur->bc_mp, left, 1, cur->bc_ops->buf_ops); rval++; } if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLFSBLOCK) { xfs_btree_reada_bufl(cur->bc_mp, right, 1, cur->bc_ops->buf_ops); rval++; } return rval; } STATIC int xfs_btree_readahead_sblock( struct xfs_btree_cur *cur, int lr, struct xfs_btree_block *block) { int rval = 0; xfs_agblock_t left = be32_to_cpu(block->bb_u.s.bb_leftsib); xfs_agblock_t right = be32_to_cpu(block->bb_u.s.bb_rightsib); if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) { xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, left, 1, cur->bc_ops->buf_ops); rval++; } if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) { xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, right, 1, cur->bc_ops->buf_ops); rval++; } return rval; } /* * Read-ahead btree blocks, at the given level. * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA. */ STATIC int xfs_btree_readahead( struct xfs_btree_cur *cur, /* btree cursor */ int lev, /* level in btree */ int lr) /* left/right bits */ { struct xfs_btree_block *block; /* * No readahead needed if we are at the root level and the * btree root is stored in the inode. */ if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && (lev == cur->bc_nlevels - 1)) return 0; if ((cur->bc_ra[lev] | lr) == cur->bc_ra[lev]) return 0; cur->bc_ra[lev] |= lr; block = XFS_BUF_TO_BLOCK(cur->bc_bufs[lev]); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) return xfs_btree_readahead_lblock(cur, lr, block); return xfs_btree_readahead_sblock(cur, lr, block); } STATIC xfs_daddr_t xfs_btree_ptr_to_daddr( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { ASSERT(ptr->l != cpu_to_be64(NULLFSBLOCK)); return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l)); } else { ASSERT(cur->bc_private.a.agno != NULLAGNUMBER); ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK)); return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno, be32_to_cpu(ptr->s)); } } /* * Readahead @count btree blocks at the given @ptr location. * * We don't need to care about long or short form btrees here as we have a * method of converting the ptr directly to a daddr available to us. */ STATIC void xfs_btree_readahead_ptr( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr, xfs_extlen_t count) { xfs_buf_readahead(cur->bc_mp->m_ddev_targp, xfs_btree_ptr_to_daddr(cur, ptr), cur->bc_mp->m_bsize * count, cur->bc_ops->buf_ops); } /* * Set the buffer for level "lev" in the cursor to bp, releasing * any previous buffer. */ STATIC void xfs_btree_setbuf( xfs_btree_cur_t *cur, /* btree cursor */ int lev, /* level in btree */ xfs_buf_t *bp) /* new buffer to set */ { struct xfs_btree_block *b; /* btree block */ if (cur->bc_bufs[lev]) xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[lev]); cur->bc_bufs[lev] = bp; cur->bc_ra[lev] = 0; b = XFS_BUF_TO_BLOCK(bp); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { if (b->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK)) cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; if (b->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK)) cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; } else { if (b->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK)) cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; if (b->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK)) cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; } } STATIC int xfs_btree_ptr_is_null( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) return ptr->l == cpu_to_be64(NULLFSBLOCK); else return ptr->s == cpu_to_be32(NULLAGBLOCK); } STATIC void xfs_btree_set_ptr_null( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) ptr->l = cpu_to_be64(NULLFSBLOCK); else ptr->s = cpu_to_be32(NULLAGBLOCK); } /* * Get/set/init sibling pointers */ STATIC void xfs_btree_get_sibling( struct xfs_btree_cur *cur, struct xfs_btree_block *block, union xfs_btree_ptr *ptr, int lr) { ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { if (lr == XFS_BB_RIGHTSIB) ptr->l = block->bb_u.l.bb_rightsib; else ptr->l = block->bb_u.l.bb_leftsib; } else { if (lr == XFS_BB_RIGHTSIB) ptr->s = block->bb_u.s.bb_rightsib; else ptr->s = block->bb_u.s.bb_leftsib; } } STATIC void xfs_btree_set_sibling( struct xfs_btree_cur *cur, struct xfs_btree_block *block, union xfs_btree_ptr *ptr, int lr) { ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { if (lr == XFS_BB_RIGHTSIB) block->bb_u.l.bb_rightsib = ptr->l; else block->bb_u.l.bb_leftsib = ptr->l; } else { if (lr == XFS_BB_RIGHTSIB) block->bb_u.s.bb_rightsib = ptr->s; else block->bb_u.s.bb_leftsib = ptr->s; } } void xfs_btree_init_block_int( struct xfs_mount *mp, struct xfs_btree_block *buf, xfs_daddr_t blkno, __u32 magic, __u16 level, __u16 numrecs, __u64 owner, unsigned int flags) { buf->bb_magic = cpu_to_be32(magic); buf->bb_level = cpu_to_be16(level); buf->bb_numrecs = cpu_to_be16(numrecs); if (flags & XFS_BTREE_LONG_PTRS) { buf->bb_u.l.bb_leftsib = cpu_to_be64(NULLFSBLOCK); buf->bb_u.l.bb_rightsib = cpu_to_be64(NULLFSBLOCK); if (flags & XFS_BTREE_CRC_BLOCKS) { buf->bb_u.l.bb_blkno = cpu_to_be64(blkno); buf->bb_u.l.bb_owner = cpu_to_be64(owner); uuid_copy(&buf->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid); buf->bb_u.l.bb_pad = 0; buf->bb_u.l.bb_lsn = 0; } } else { /* owner is a 32 bit value on short blocks */ __u32 __owner = (__u32)owner; buf->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK); buf->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK); if (flags & XFS_BTREE_CRC_BLOCKS) { buf->bb_u.s.bb_blkno = cpu_to_be64(blkno); buf->bb_u.s.bb_owner = cpu_to_be32(__owner); uuid_copy(&buf->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid); buf->bb_u.s.bb_lsn = 0; } } } void xfs_btree_init_block( struct xfs_mount *mp, struct xfs_buf *bp, __u32 magic, __u16 level, __u16 numrecs, __u64 owner, unsigned int flags) { xfs_btree_init_block_int(mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn, magic, level, numrecs, owner, flags); } STATIC void xfs_btree_init_block_cur( struct xfs_btree_cur *cur, struct xfs_buf *bp, int level, int numrecs) { __u64 owner; /* * we can pull the owner from the cursor right now as the different * owners align directly with the pointer size of the btree. This may * change in future, but is safe for current users of the generic btree * code. */ if (cur->bc_flags & XFS_BTREE_LONG_PTRS) owner = cur->bc_private.b.ip->i_ino; else owner = cur->bc_private.a.agno; xfs_btree_init_block_int(cur->bc_mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn, xfs_btree_magic(cur), level, numrecs, owner, cur->bc_flags); } /* * Return true if ptr is the last record in the btree and * we need to track updates to this record. The decision * will be further refined in the update_lastrec method. */ STATIC int xfs_btree_is_lastrec( struct xfs_btree_cur *cur, struct xfs_btree_block *block, int level) { union xfs_btree_ptr ptr; if (level > 0) return 0; if (!(cur->bc_flags & XFS_BTREE_LASTREC_UPDATE)) return 0; xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); if (!xfs_btree_ptr_is_null(cur, &ptr)) return 0; return 1; } STATIC void xfs_btree_buf_to_ptr( struct xfs_btree_cur *cur, struct xfs_buf *bp, union xfs_btree_ptr *ptr) { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) ptr->l = cpu_to_be64(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp))); else { ptr->s = cpu_to_be32(xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp))); } } STATIC void xfs_btree_set_refs( struct xfs_btree_cur *cur, struct xfs_buf *bp) { switch (cur->bc_btnum) { case XFS_BTNUM_BNO: case XFS_BTNUM_CNT: xfs_buf_set_ref(bp, XFS_ALLOC_BTREE_REF); break; case XFS_BTNUM_INO: case XFS_BTNUM_FINO: xfs_buf_set_ref(bp, XFS_INO_BTREE_REF); break; case XFS_BTNUM_BMAP: xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF); break; case XFS_BTNUM_RMAP: xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF); break; case XFS_BTNUM_REFC: xfs_buf_set_ref(bp, XFS_REFC_BTREE_REF); break; default: ASSERT(0); } } STATIC int xfs_btree_get_buf_block( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr, int flags, struct xfs_btree_block **block, struct xfs_buf **bpp) { struct xfs_mount *mp = cur->bc_mp; xfs_daddr_t d; /* need to sort out how callers deal with failures first */ ASSERT(!(flags & XBF_TRYLOCK)); d = xfs_btree_ptr_to_daddr(cur, ptr); *bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d, mp->m_bsize, flags); if (!*bpp) return -ENOMEM; (*bpp)->b_ops = cur->bc_ops->buf_ops; *block = XFS_BUF_TO_BLOCK(*bpp); return 0; } /* * Read in the buffer at the given ptr and return the buffer and * the block pointer within the buffer. */ STATIC int xfs_btree_read_buf_block( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr, int flags, struct xfs_btree_block **block, struct xfs_buf **bpp) { struct xfs_mount *mp = cur->bc_mp; xfs_daddr_t d; int error; /* need to sort out how callers deal with failures first */ ASSERT(!(flags & XBF_TRYLOCK)); d = xfs_btree_ptr_to_daddr(cur, ptr); error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d, mp->m_bsize, flags, bpp, cur->bc_ops->buf_ops); if (error) return error; xfs_btree_set_refs(cur, *bpp); *block = XFS_BUF_TO_BLOCK(*bpp); return 0; } /* * Copy keys from one btree block to another. */ STATIC void xfs_btree_copy_keys( struct xfs_btree_cur *cur, union xfs_btree_key *dst_key, union xfs_btree_key *src_key, int numkeys) { ASSERT(numkeys >= 0); memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len); } /* * Copy records from one btree block to another. */ STATIC void xfs_btree_copy_recs( struct xfs_btree_cur *cur, union xfs_btree_rec *dst_rec, union xfs_btree_rec *src_rec, int numrecs) { ASSERT(numrecs >= 0); memcpy(dst_rec, src_rec, numrecs * cur->bc_ops->rec_len); } /* * Copy block pointers from one btree block to another. */ STATIC void xfs_btree_copy_ptrs( struct xfs_btree_cur *cur, union xfs_btree_ptr *dst_ptr, union xfs_btree_ptr *src_ptr, int numptrs) { ASSERT(numptrs >= 0); memcpy(dst_ptr, src_ptr, numptrs * xfs_btree_ptr_len(cur)); } /* * Shift keys one index left/right inside a single btree block. */ STATIC void xfs_btree_shift_keys( struct xfs_btree_cur *cur, union xfs_btree_key *key, int dir, int numkeys) { char *dst_key; ASSERT(numkeys >= 0); ASSERT(dir == 1 || dir == -1); dst_key = (char *)key + (dir * cur->bc_ops->key_len); memmove(dst_key, key, numkeys * cur->bc_ops->key_len); } /* * Shift records one index left/right inside a single btree block. */ STATIC void xfs_btree_shift_recs( struct xfs_btree_cur *cur, union xfs_btree_rec *rec, int dir, int numrecs) { char *dst_rec; ASSERT(numrecs >= 0); ASSERT(dir == 1 || dir == -1); dst_rec = (char *)rec + (dir * cur->bc_ops->rec_len); memmove(dst_rec, rec, numrecs * cur->bc_ops->rec_len); } /* * Shift block pointers one index left/right inside a single btree block. */ STATIC void xfs_btree_shift_ptrs( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr, int dir, int numptrs) { char *dst_ptr; ASSERT(numptrs >= 0); ASSERT(dir == 1 || dir == -1); dst_ptr = (char *)ptr + (dir * xfs_btree_ptr_len(cur)); memmove(dst_ptr, ptr, numptrs * xfs_btree_ptr_len(cur)); } /* * Log key values from the btree block. */ STATIC void xfs_btree_log_keys( struct xfs_btree_cur *cur, struct xfs_buf *bp, int first, int last) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); if (bp) { xfs_trans_buf_set_type(cur->bc_tp, bp, XFS_BLFT_BTREE_BUF); xfs_trans_log_buf(cur->bc_tp, bp, xfs_btree_key_offset(cur, first), xfs_btree_key_offset(cur, last + 1) - 1); } else { xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, xfs_ilog_fbroot(cur->bc_private.b.whichfork)); } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); } /* * Log record values from the btree block. */ void xfs_btree_log_recs( struct xfs_btree_cur *cur, struct xfs_buf *bp, int first, int last) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); xfs_trans_buf_set_type(cur->bc_tp, bp, XFS_BLFT_BTREE_BUF); xfs_trans_log_buf(cur->bc_tp, bp, xfs_btree_rec_offset(cur, first), xfs_btree_rec_offset(cur, last + 1) - 1); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); } /* * Log block pointer fields from a btree block (nonleaf). */ STATIC void xfs_btree_log_ptrs( struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_buf *bp, /* buffer containing btree block */ int first, /* index of first pointer to log */ int last) /* index of last pointer to log */ { XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); if (bp) { struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); int level = xfs_btree_get_level(block); xfs_trans_buf_set_type(cur->bc_tp, bp, XFS_BLFT_BTREE_BUF); xfs_trans_log_buf(cur->bc_tp, bp, xfs_btree_ptr_offset(cur, first, level), xfs_btree_ptr_offset(cur, last + 1, level) - 1); } else { xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, xfs_ilog_fbroot(cur->bc_private.b.whichfork)); } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); } /* * Log fields from a btree block header. */ void xfs_btree_log_block( struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_buf *bp, /* buffer containing btree block */ int fields) /* mask of fields: XFS_BB_... */ { int first; /* first byte offset logged */ int last; /* last byte offset logged */ static const short soffsets[] = { /* table of offsets (short) */ offsetof(struct xfs_btree_block, bb_magic), offsetof(struct xfs_btree_block, bb_level), offsetof(struct xfs_btree_block, bb_numrecs), offsetof(struct xfs_btree_block, bb_u.s.bb_leftsib), offsetof(struct xfs_btree_block, bb_u.s.bb_rightsib), offsetof(struct xfs_btree_block, bb_u.s.bb_blkno), offsetof(struct xfs_btree_block, bb_u.s.bb_lsn), offsetof(struct xfs_btree_block, bb_u.s.bb_uuid), offsetof(struct xfs_btree_block, bb_u.s.bb_owner), offsetof(struct xfs_btree_block, bb_u.s.bb_crc), XFS_BTREE_SBLOCK_CRC_LEN }; static const short loffsets[] = { /* table of offsets (long) */ offsetof(struct xfs_btree_block, bb_magic), offsetof(struct xfs_btree_block, bb_level), offsetof(struct xfs_btree_block, bb_numrecs), offsetof(struct xfs_btree_block, bb_u.l.bb_leftsib), offsetof(struct xfs_btree_block, bb_u.l.bb_rightsib), offsetof(struct xfs_btree_block, bb_u.l.bb_blkno), offsetof(struct xfs_btree_block, bb_u.l.bb_lsn), offsetof(struct xfs_btree_block, bb_u.l.bb_uuid), offsetof(struct xfs_btree_block, bb_u.l.bb_owner), offsetof(struct xfs_btree_block, bb_u.l.bb_crc), offsetof(struct xfs_btree_block, bb_u.l.bb_pad), XFS_BTREE_LBLOCK_CRC_LEN }; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGBI(cur, bp, fields); if (bp) { int nbits; if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) { /* * We don't log the CRC when updating a btree * block but instead recreate it during log * recovery. As the log buffers have checksums * of their own this is safe and avoids logging a crc * update in a lot of places. */ if (fields == XFS_BB_ALL_BITS) fields = XFS_BB_ALL_BITS_CRC; nbits = XFS_BB_NUM_BITS_CRC; } else { nbits = XFS_BB_NUM_BITS; } xfs_btree_offsets(fields, (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? loffsets : soffsets, nbits, &first, &last); xfs_trans_buf_set_type(cur->bc_tp, bp, XFS_BLFT_BTREE_BUF); xfs_trans_log_buf(cur->bc_tp, bp, first, last); } else { xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, xfs_ilog_fbroot(cur->bc_private.b.whichfork)); } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); } /* * Increment cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */ int /* error */ xfs_btree_increment( struct xfs_btree_cur *cur, int level, int *stat) /* success/failure */ { struct xfs_btree_block *block; union xfs_btree_ptr ptr; struct xfs_buf *bp; int error; /* error return value */ int lev; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGI(cur, level); ASSERT(level < cur->bc_nlevels); /* Read-ahead to the right at this level. */ xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); /* Get a pointer to the btree block. */ block = xfs_btree_get_block(cur, level, &bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) goto error0; #endif /* We're done if we remain in the block after the increment. */ if (++cur->bc_ptrs[level] <= xfs_btree_get_numrecs(block)) goto out1; /* Fail if we just went off the right edge of the tree. */ xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); if (xfs_btree_ptr_is_null(cur, &ptr)) goto out0; XFS_BTREE_STATS_INC(cur, increment); /* * March up the tree incrementing pointers. * Stop when we don't go off the right edge of a block. */ for (lev = level + 1; lev < cur->bc_nlevels; lev++) { block = xfs_btree_get_block(cur, lev, &bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, lev, bp); if (error) goto error0; #endif if (++cur->bc_ptrs[lev] <= xfs_btree_get_numrecs(block)) break; /* Read-ahead the right block for the next loop. */ xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); } /* * If we went off the root then we are either seriously * confused or have the tree root in an inode. */ if (lev == cur->bc_nlevels) { if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) goto out0; ASSERT(0); error = -EFSCORRUPTED; goto error0; } ASSERT(lev < cur->bc_nlevels); /* * Now walk back down the tree, fixing up the cursor's buffer * pointers and key numbers. */ for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) { union xfs_btree_ptr *ptrp; ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); --lev; error = xfs_btree_read_buf_block(cur, ptrp, 0, &block, &bp); if (error) goto error0; xfs_btree_setbuf(cur, lev, bp); cur->bc_ptrs[lev] = 1; } out1: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; out0: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } /* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */ int /* error */ xfs_btree_decrement( struct xfs_btree_cur *cur, int level, int *stat) /* success/failure */ { struct xfs_btree_block *block; xfs_buf_t *bp; int error; /* error return value */ int lev; union xfs_btree_ptr ptr; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGI(cur, level); ASSERT(level < cur->bc_nlevels); /* Read-ahead to the left at this level. */ xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); /* We're done if we remain in the block after the decrement. */ if (--cur->bc_ptrs[level] > 0) goto out1; /* Get a pointer to the btree block. */ block = xfs_btree_get_block(cur, level, &bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) goto error0; #endif /* Fail if we just went off the left edge of the tree. */ xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_LEFTSIB); if (xfs_btree_ptr_is_null(cur, &ptr)) goto out0; XFS_BTREE_STATS_INC(cur, decrement); /* * March up the tree decrementing pointers. * Stop when we don't go off the left edge of a block. */ for (lev = level + 1; lev < cur->bc_nlevels; lev++) { if (--cur->bc_ptrs[lev] > 0) break; /* Read-ahead the left block for the next loop. */ xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); } /* * If we went off the root then we are seriously confused. * or the root of the tree is in an inode. */ if (lev == cur->bc_nlevels) { if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) goto out0; ASSERT(0); error = -EFSCORRUPTED; goto error0; } ASSERT(lev < cur->bc_nlevels); /* * Now walk back down the tree, fixing up the cursor's buffer * pointers and key numbers. */ for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) { union xfs_btree_ptr *ptrp; ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); --lev; error = xfs_btree_read_buf_block(cur, ptrp, 0, &block, &bp); if (error) goto error0; xfs_btree_setbuf(cur, lev, bp); cur->bc_ptrs[lev] = xfs_btree_get_numrecs(block); } out1: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; out0: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } STATIC int xfs_btree_lookup_get_block( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level in the btree */ union xfs_btree_ptr *pp, /* ptr to btree block */ struct xfs_btree_block **blkp) /* return btree block */ { struct xfs_buf *bp; /* buffer pointer for btree block */ int error = 0; /* special case the root block if in an inode */ if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && (level == cur->bc_nlevels - 1)) { *blkp = xfs_btree_get_iroot(cur); return 0; } /* * If the old buffer at this level for the disk address we are * looking for re-use it. * * Otherwise throw it away and get a new one. */ bp = cur->bc_bufs[level]; if (bp && XFS_BUF_ADDR(bp) == xfs_btree_ptr_to_daddr(cur, pp)) { *blkp = XFS_BUF_TO_BLOCK(bp); return 0; } error = xfs_btree_read_buf_block(cur, pp, 0, blkp, &bp); if (error) return error; xfs_btree_setbuf(cur, level, bp); return 0; } /* * Get current search key. For level 0 we don't actually have a key * structure so we make one up from the record. For all other levels * we just return the right key. */ STATIC union xfs_btree_key * xfs_lookup_get_search_key( struct xfs_btree_cur *cur, int level, int keyno, struct xfs_btree_block *block, union xfs_btree_key *kp) { if (level == 0) { cur->bc_ops->init_key_from_rec(kp, xfs_btree_rec_addr(cur, keyno, block)); return kp; } return xfs_btree_key_addr(cur, keyno, block); } /* * Lookup the record. The cursor is made to point to it, based on dir. * stat is set to 0 if can't find any such record, 1 for success. */ int /* error */ xfs_btree_lookup( struct xfs_btree_cur *cur, /* btree cursor */ xfs_lookup_t dir, /* <=, ==, or >= */ int *stat) /* success/failure */ { struct xfs_btree_block *block; /* current btree block */ __int64_t diff; /* difference for the current key */ int error; /* error return value */ int keyno; /* current key number */ int level; /* level in the btree */ union xfs_btree_ptr *pp; /* ptr to btree block */ union xfs_btree_ptr ptr; /* ptr to btree block */ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGI(cur, dir); XFS_BTREE_STATS_INC(cur, lookup); /* No such thing as a zero-level tree. */ if (cur->bc_nlevels == 0) return -EFSCORRUPTED; block = NULL; keyno = 0; /* initialise start pointer from cursor */ cur->bc_ops->init_ptr_from_cur(cur, &ptr); pp = &ptr; /* * Iterate over each level in the btree, starting at the root. * For each level above the leaves, find the key we need, based * on the lookup record, then follow the corresponding block * pointer down to the next level. */ for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { /* Get the block we need to do the lookup on. */ error = xfs_btree_lookup_get_block(cur, level, pp, &block); if (error) goto error0; if (diff == 0) { /* * If we already had a key match at a higher level, we * know we need to use the first entry in this block. */ keyno = 1; } else { /* Otherwise search this block. Do a binary search. */ int high; /* high entry number */ int low; /* low entry number */ /* Set low and high entry numbers, 1-based. */ low = 1; high = xfs_btree_get_numrecs(block); if (!high) { /* Block is empty, must be an empty leaf. */ ASSERT(level == 0 && cur->bc_nlevels == 1); cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } /* Binary search the block. */ while (low <= high) { union xfs_btree_key key; union xfs_btree_key *kp; XFS_BTREE_STATS_INC(cur, compare); /* keyno is average of low and high. */ keyno = (low + high) >> 1; /* Get current search key */ kp = xfs_lookup_get_search_key(cur, level, keyno, block, &key); /* * Compute difference to get next direction: * - less than, move right * - greater than, move left * - equal, we're done */ diff = cur->bc_ops->key_diff(cur, kp); if (diff < 0) low = keyno + 1; else if (diff > 0) high = keyno - 1; else break; } } /* * If there are more levels, set up for the next level * by getting the block number and filling in the cursor. */ if (level > 0) { /* * If we moved left, need the previous key number, * unless there isn't one. */ if (diff > 0 && --keyno < 1) keyno = 1; pp = xfs_btree_ptr_addr(cur, keyno, block); #ifdef DEBUG error = xfs_btree_check_ptr(cur, pp, 0, level); if (error) goto error0; #endif cur->bc_ptrs[level] = keyno; } } /* Done with the search. See if we need to adjust the results. */ if (dir != XFS_LOOKUP_LE && diff < 0) { keyno++; /* * If ge search and we went off the end of the block, but it's * not the last block, we're in the wrong block. */ xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); if (dir == XFS_LOOKUP_GE && keyno > xfs_btree_get_numrecs(block) && !xfs_btree_ptr_is_null(cur, &ptr)) { int i; cur->bc_ptrs[0] = keyno; error = xfs_btree_increment(cur, 0, &i); if (error) goto error0; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; } } else if (dir == XFS_LOOKUP_LE && diff > 0) keyno--; cur->bc_ptrs[0] = keyno; /* Return if we succeeded or not. */ if (keyno == 0 || keyno > xfs_btree_get_numrecs(block)) *stat = 0; else if (dir != XFS_LOOKUP_EQ || diff == 0) *stat = 1; else *stat = 0; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } /* Find the high key storage area from a regular key. */ STATIC union xfs_btree_key * xfs_btree_high_key_from_key( struct xfs_btree_cur *cur, union xfs_btree_key *key) { ASSERT(cur->bc_flags & XFS_BTREE_OVERLAPPING); return (union xfs_btree_key *)((char *)key + (cur->bc_ops->key_len / 2)); } /* Determine the low (and high if overlapped) keys of a leaf block */ STATIC void xfs_btree_get_leaf_keys( struct xfs_btree_cur *cur, struct xfs_btree_block *block, union xfs_btree_key *key) { union xfs_btree_key max_hkey; union xfs_btree_key hkey; union xfs_btree_rec *rec; union xfs_btree_key *high; int n; rec = xfs_btree_rec_addr(cur, 1, block); cur->bc_ops->init_key_from_rec(key, rec); if (cur->bc_flags & XFS_BTREE_OVERLAPPING) { cur->bc_ops->init_high_key_from_rec(&max_hkey, rec); for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { rec = xfs_btree_rec_addr(cur, n, block); cur->bc_ops->init_high_key_from_rec(&hkey, rec); if (cur->bc_ops->diff_two_keys(cur, &hkey, &max_hkey) > 0) max_hkey = hkey; } high = xfs_btree_high_key_from_key(cur, key); memcpy(high, &max_hkey, cur->bc_ops->key_len / 2); } } /* Determine the low (and high if overlapped) keys of a node block */ STATIC void xfs_btree_get_node_keys( struct xfs_btree_cur *cur, struct xfs_btree_block *block, union xfs_btree_key *key) { union xfs_btree_key *hkey; union xfs_btree_key *max_hkey; union xfs_btree_key *high; int n; if (cur->bc_flags & XFS_BTREE_OVERLAPPING) { memcpy(key, xfs_btree_key_addr(cur, 1, block), cur->bc_ops->key_len / 2); max_hkey = xfs_btree_high_key_addr(cur, 1, block); for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { hkey = xfs_btree_high_key_addr(cur, n, block); if (cur->bc_ops->diff_two_keys(cur, hkey, max_hkey) > 0) max_hkey = hkey; } high = xfs_btree_high_key_from_key(cur, key); memcpy(high, max_hkey, cur->bc_ops->key_len / 2); } else { memcpy(key, xfs_btree_key_addr(cur, 1, block), cur->bc_ops->key_len); } } /* Derive the keys for any btree block. */ STATIC void xfs_btree_get_keys( struct xfs_btree_cur *cur, struct xfs_btree_block *block, union xfs_btree_key *key) { if (be16_to_cpu(block->bb_level) == 0) xfs_btree_get_leaf_keys(cur, block, key); else xfs_btree_get_node_keys(cur, block, key); } /* * Decide if we need to update the parent keys of a btree block. For * a standard btree this is only necessary if we're updating the first * record/key. For an overlapping btree, we must always update the * keys because the highest key can be in any of the records or keys * in the block. */ static inline bool xfs_btree_needs_key_update( struct xfs_btree_cur *cur, int ptr) { return (cur->bc_flags & XFS_BTREE_OVERLAPPING) || ptr == 1; } /* * Update the low and high parent keys of the given level, progressing * towards the root. If force_all is false, stop if the keys for a given * level do not need updating. */ STATIC int __xfs_btree_updkeys( struct xfs_btree_cur *cur, int level, struct xfs_btree_block *block, struct xfs_buf *bp0, bool force_all) { union xfs_btree_key key; /* keys from current level */ union xfs_btree_key *lkey; /* keys from the next level up */ union xfs_btree_key *hkey; union xfs_btree_key *nlkey; /* keys from the next level up */ union xfs_btree_key *nhkey; struct xfs_buf *bp; int ptr; ASSERT(cur->bc_flags & XFS_BTREE_OVERLAPPING); /* Exit if there aren't any parent levels to update. */ if (level + 1 >= cur->bc_nlevels) return 0; trace_xfs_btree_updkeys(cur, level, bp0); lkey = &key; hkey = xfs_btree_high_key_from_key(cur, lkey); xfs_btree_get_keys(cur, block, lkey); for (level++; level < cur->bc_nlevels; level++) { #ifdef DEBUG int error; #endif block = xfs_btree_get_block(cur, level, &bp); trace_xfs_btree_updkeys(cur, level, bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } #endif ptr = cur->bc_ptrs[level]; nlkey = xfs_btree_key_addr(cur, ptr, block); nhkey = xfs_btree_high_key_addr(cur, ptr, block); if (!force_all && !(cur->bc_ops->diff_two_keys(cur, nlkey, lkey) != 0 || cur->bc_ops->diff_two_keys(cur, nhkey, hkey) != 0)) break; xfs_btree_copy_keys(cur, nlkey, lkey, 1); xfs_btree_log_keys(cur, bp, ptr, ptr); if (level + 1 >= cur->bc_nlevels) break; xfs_btree_get_node_keys(cur, block, lkey); } return 0; } /* Update all the keys from some level in cursor back to the root. */ STATIC int xfs_btree_updkeys_force( struct xfs_btree_cur *cur, int level) { struct xfs_buf *bp; struct xfs_btree_block *block; block = xfs_btree_get_block(cur, level, &bp); return __xfs_btree_updkeys(cur, level, block, bp, true); } /* * Update the parent keys of the given level, progressing towards the root. */ STATIC int xfs_btree_update_keys( struct xfs_btree_cur *cur, int level) { struct xfs_btree_block *block; struct xfs_buf *bp; union xfs_btree_key *kp; union xfs_btree_key key; int ptr; ASSERT(level >= 0); block = xfs_btree_get_block(cur, level, &bp); if (cur->bc_flags & XFS_BTREE_OVERLAPPING) return __xfs_btree_updkeys(cur, level, block, bp, false); XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGIK(cur, level, keyp); /* * Go up the tree from this level toward the root. * At each level, update the key value to the value input. * Stop when we reach a level where the cursor isn't pointing * at the first entry in the block. */ xfs_btree_get_keys(cur, block, &key); for (level++, ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { #ifdef DEBUG int error; #endif block = xfs_btree_get_block(cur, level, &bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } #endif ptr = cur->bc_ptrs[level]; kp = xfs_btree_key_addr(cur, ptr, block); xfs_btree_copy_keys(cur, kp, &key, 1); xfs_btree_log_keys(cur, bp, ptr, ptr); } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return 0; } /* * Update the record referred to by cur to the value in the * given record. This either works (return 0) or gets an * EFSCORRUPTED error. */ int xfs_btree_update( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) { struct xfs_btree_block *block; struct xfs_buf *bp; int error; int ptr; union xfs_btree_rec *rp; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGR(cur, rec); /* Pick up the current block. */ block = xfs_btree_get_block(cur, 0, &bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, 0, bp); if (error) goto error0; #endif /* Get the address of the rec to be updated. */ ptr = cur->bc_ptrs[0]; rp = xfs_btree_rec_addr(cur, ptr, block); /* Fill in the new contents and log them. */ xfs_btree_copy_recs(cur, rp, rec, 1); xfs_btree_log_recs(cur, bp, ptr, ptr); /* * If we are tracking the last record in the tree and * we are at the far right edge of the tree, update it. */ if (xfs_btree_is_lastrec(cur, block, 0)) { cur->bc_ops->update_lastrec(cur, block, rec, ptr, LASTREC_UPDATE); } /* Pass new key value up to our parent. */ if (xfs_btree_needs_key_update(cur, ptr)) { error = xfs_btree_update_keys(cur, 0); if (error) goto error0; } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } /* * Move 1 record left from cur/level if possible. * Update cur to reflect the new path. */ STATIC int /* error */ xfs_btree_lshift( struct xfs_btree_cur *cur, int level, int *stat) /* success/failure */ { struct xfs_buf *lbp; /* left buffer pointer */ struct xfs_btree_block *left; /* left btree block */ int lrecs; /* left record count */ struct xfs_buf *rbp; /* right buffer pointer */ struct xfs_btree_block *right; /* right btree block */ struct xfs_btree_cur *tcur; /* temporary btree cursor */ int rrecs; /* right record count */ union xfs_btree_ptr lptr; /* left btree pointer */ union xfs_btree_key *rkp = NULL; /* right btree key */ union xfs_btree_ptr *rpp = NULL; /* right address pointer */ union xfs_btree_rec *rrp = NULL; /* right record pointer */ int error; /* error return value */ int i; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGI(cur, level); if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && level == cur->bc_nlevels - 1) goto out0; /* Set up variables for this block as "right". */ right = xfs_btree_get_block(cur, level, &rbp); #ifdef DEBUG error = xfs_btree_check_block(cur, right, level, rbp); if (error) goto error0; #endif /* If we've got no left sibling then we can't shift an entry left. */ xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); if (xfs_btree_ptr_is_null(cur, &lptr)) goto out0; /* * If the cursor entry is the one that would be moved, don't * do it... it's too complicated. */ if (cur->bc_ptrs[level] <= 1) goto out0; /* Set up the left neighbor as "left". */ error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp); if (error) goto error0; /* If it's full, it can't take another entry. */ lrecs = xfs_btree_get_numrecs(left); if (lrecs == cur->bc_ops->get_maxrecs(cur, level)) goto out0; rrecs = xfs_btree_get_numrecs(right); /* * We add one entry to the left side and remove one for the right side. * Account for it here, the changes will be updated on disk and logged * later. */ lrecs++; rrecs--; XFS_BTREE_STATS_INC(cur, lshift); XFS_BTREE_STATS_ADD(cur, moves, 1); /* * If non-leaf, copy a key and a ptr to the left block. * Log the changes to the left block. */ if (level > 0) { /* It's a non-leaf. Move keys and pointers. */ union xfs_btree_key *lkp; /* left btree key */ union xfs_btree_ptr *lpp; /* left address pointer */ lkp = xfs_btree_key_addr(cur, lrecs, left); rkp = xfs_btree_key_addr(cur, 1, right); lpp = xfs_btree_ptr_addr(cur, lrecs, left); rpp = xfs_btree_ptr_addr(cur, 1, right); #ifdef DEBUG error = xfs_btree_check_ptr(cur, rpp, 0, level); if (error) goto error0; #endif xfs_btree_copy_keys(cur, lkp, rkp, 1); xfs_btree_copy_ptrs(cur, lpp, rpp, 1); xfs_btree_log_keys(cur, lbp, lrecs, lrecs); xfs_btree_log_ptrs(cur, lbp, lrecs, lrecs); ASSERT(cur->bc_ops->keys_inorder(cur, xfs_btree_key_addr(cur, lrecs - 1, left), lkp)); } else { /* It's a leaf. Move records. */ union xfs_btree_rec *lrp; /* left record pointer */ lrp = xfs_btree_rec_addr(cur, lrecs, left); rrp = xfs_btree_rec_addr(cur, 1, right); xfs_btree_copy_recs(cur, lrp, rrp, 1); xfs_btree_log_recs(cur, lbp, lrecs, lrecs); ASSERT(cur->bc_ops->recs_inorder(cur, xfs_btree_rec_addr(cur, lrecs - 1, left), lrp)); } xfs_btree_set_numrecs(left, lrecs); xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS); xfs_btree_set_numrecs(right, rrecs); xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS); /* * Slide the contents of right down one entry. */ XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1); if (level > 0) { /* It's a nonleaf. operate on keys and ptrs */ #ifdef DEBUG int i; /* loop index */ for (i = 0; i < rrecs; i++) { error = xfs_btree_check_ptr(cur, rpp, i + 1, level); if (error) goto error0; } #endif xfs_btree_shift_keys(cur, xfs_btree_key_addr(cur, 2, right), -1, rrecs); xfs_btree_shift_ptrs(cur, xfs_btree_ptr_addr(cur, 2, right), -1, rrecs); xfs_btree_log_keys(cur, rbp, 1, rrecs); xfs_btree_log_ptrs(cur, rbp, 1, rrecs); } else { /* It's a leaf. operate on records */ xfs_btree_shift_recs(cur, xfs_btree_rec_addr(cur, 2, right), -1, rrecs); xfs_btree_log_recs(cur, rbp, 1, rrecs); } /* * Using a temporary cursor, update the parent key values of the * block on the left. */ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) { error = xfs_btree_dup_cursor(cur, &tcur); if (error) goto error0; i = xfs_btree_firstrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0); error = xfs_btree_decrement(tcur, level, &i); if (error) goto error1; /* Update the parent high keys of the left block, if needed. */ error = xfs_btree_update_keys(tcur, level); if (error) goto error1; xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); } /* Update the parent keys of the right block. */ error = xfs_btree_update_keys(cur, level); if (error) goto error0; /* Slide the cursor value left one. */ cur->bc_ptrs[level]--; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; out0: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; error1: XFS_BTREE_TRACE_CURSOR(tcur, XBT_ERROR); xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); return error; } /* * Move 1 record right from cur/level if possible. * Update cur to reflect the new path. */ STATIC int /* error */ xfs_btree_rshift( struct xfs_btree_cur *cur, int level, int *stat) /* success/failure */ { struct xfs_buf *lbp; /* left buffer pointer */ struct xfs_btree_block *left; /* left btree block */ struct xfs_buf *rbp; /* right buffer pointer */ struct xfs_btree_block *right; /* right btree block */ struct xfs_btree_cur *tcur; /* temporary btree cursor */ union xfs_btree_ptr rptr; /* right block pointer */ union xfs_btree_key *rkp; /* right btree key */ int rrecs; /* right record count */ int lrecs; /* left record count */ int error; /* error return value */ int i; /* loop counter */ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGI(cur, level); if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && (level == cur->bc_nlevels - 1)) goto out0; /* Set up variables for this block as "left". */ left = xfs_btree_get_block(cur, level, &lbp); #ifdef DEBUG error = xfs_btree_check_block(cur, left, level, lbp); if (error) goto error0; #endif /* If we've got no right sibling then we can't shift an entry right. */ xfs_btree_get_sibling(cur, left, &rptr, XFS_BB_RIGHTSIB); if (xfs_btree_ptr_is_null(cur, &rptr)) goto out0; /* * If the cursor entry is the one that would be moved, don't * do it... it's too complicated. */ lrecs = xfs_btree_get_numrecs(left); if (cur->bc_ptrs[level] >= lrecs) goto out0; /* Set up the right neighbor as "right". */ error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp); if (error) goto error0; /* If it's full, it can't take another entry. */ rrecs = xfs_btree_get_numrecs(right); if (rrecs == cur->bc_ops->get_maxrecs(cur, level)) goto out0; XFS_BTREE_STATS_INC(cur, rshift); XFS_BTREE_STATS_ADD(cur, moves, rrecs); /* * Make a hole at the start of the right neighbor block, then * copy the last left block entry to the hole. */ if (level > 0) { /* It's a nonleaf. make a hole in the keys and ptrs */ union xfs_btree_key *lkp; union xfs_btree_ptr *lpp; union xfs_btree_ptr *rpp; lkp = xfs_btree_key_addr(cur, lrecs, left); lpp = xfs_btree_ptr_addr(cur, lrecs, left); rkp = xfs_btree_key_addr(cur, 1, right); rpp = xfs_btree_ptr_addr(cur, 1, right); #ifdef DEBUG for (i = rrecs - 1; i >= 0; i--) { error = xfs_btree_check_ptr(cur, rpp, i, level); if (error) goto error0; } #endif xfs_btree_shift_keys(cur, rkp, 1, rrecs); xfs_btree_shift_ptrs(cur, rpp, 1, rrecs); #ifdef DEBUG error = xfs_btree_check_ptr(cur, lpp, 0, level); if (error) goto error0; #endif /* Now put the new data in, and log it. */ xfs_btree_copy_keys(cur, rkp, lkp, 1); xfs_btree_copy_ptrs(cur, rpp, lpp, 1); xfs_btree_log_keys(cur, rbp, 1, rrecs + 1); xfs_btree_log_ptrs(cur, rbp, 1, rrecs + 1); ASSERT(cur->bc_ops->keys_inorder(cur, rkp, xfs_btree_key_addr(cur, 2, right))); } else { /* It's a leaf. make a hole in the records */ union xfs_btree_rec *lrp; union xfs_btree_rec *rrp; lrp = xfs_btree_rec_addr(cur, lrecs, left); rrp = xfs_btree_rec_addr(cur, 1, right); xfs_btree_shift_recs(cur, rrp, 1, rrecs); /* Now put the new data in, and log it. */ xfs_btree_copy_recs(cur, rrp, lrp, 1); xfs_btree_log_recs(cur, rbp, 1, rrecs + 1); } /* * Decrement and log left's numrecs, bump and log right's numrecs. */ xfs_btree_set_numrecs(left, --lrecs); xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS); xfs_btree_set_numrecs(right, ++rrecs); xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS); /* * Using a temporary cursor, update the parent key values of the * block on the right. */ error = xfs_btree_dup_cursor(cur, &tcur); if (error) goto error0; i = xfs_btree_lastrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0); error = xfs_btree_increment(tcur, level, &i); if (error) goto error1; /* Update the parent high keys of the left block, if needed. */ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) { error = xfs_btree_update_keys(cur, level); if (error) goto error1; } /* Update the parent keys of the right block. */ error = xfs_btree_update_keys(tcur, level); if (error) goto error1; xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; out0: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; error1: XFS_BTREE_TRACE_CURSOR(tcur, XBT_ERROR); xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); return error; } /* * Split cur/level block in half. * Return new block number and the key to its first * record (to be inserted into parent). */ STATIC int /* error */ __xfs_btree_split( struct xfs_btree_cur *cur, int level, union xfs_btree_ptr *ptrp, union xfs_btree_key *key, struct xfs_btree_cur **curp, int *stat) /* success/failure */ { union xfs_btree_ptr lptr; /* left sibling block ptr */ struct xfs_buf *lbp; /* left buffer pointer */ struct xfs_btree_block *left; /* left btree block */ union xfs_btree_ptr rptr; /* right sibling block ptr */ struct xfs_buf *rbp; /* right buffer pointer */ struct xfs_btree_block *right; /* right btree block */ union xfs_btree_ptr rrptr; /* right-right sibling ptr */ struct xfs_buf *rrbp; /* right-right buffer pointer */ struct xfs_btree_block *rrblock; /* right-right btree block */ int lrecs; int rrecs; int src_index; int error; /* error return value */ #ifdef DEBUG int i; #endif XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGIPK(cur, level, *ptrp, key); XFS_BTREE_STATS_INC(cur, split); /* Set up left block (current one). */ left = xfs_btree_get_block(cur, level, &lbp); #ifdef DEBUG error = xfs_btree_check_block(cur, left, level, lbp); if (error) goto error0; #endif xfs_btree_buf_to_ptr(cur, lbp, &lptr); /* Allocate the new block. If we can't do it, we're toast. Give up. */ error = cur->bc_ops->alloc_block(cur, &lptr, &rptr, stat); if (error) goto error0; if (*stat == 0) goto out0; XFS_BTREE_STATS_INC(cur, alloc); /* Set up the new block as "right". */ error = xfs_btree_get_buf_block(cur, &rptr, 0, &right, &rbp); if (error) goto error0; /* Fill in the btree header for the new right block. */ xfs_btree_init_block_cur(cur, rbp, xfs_btree_get_level(left), 0); /* * Split the entries between the old and the new block evenly. * Make sure that if there's an odd number of entries now, that * each new block will have the same number of entries. */ lrecs = xfs_btree_get_numrecs(left); rrecs = lrecs / 2; if ((lrecs & 1) && cur->bc_ptrs[level] <= rrecs + 1) rrecs++; src_index = (lrecs - rrecs + 1); XFS_BTREE_STATS_ADD(cur, moves, rrecs); /* Adjust numrecs for the later get_*_keys() calls. */ lrecs -= rrecs; xfs_btree_set_numrecs(left, lrecs); xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs); /* * Copy btree block entries from the left block over to the * new block, the right. Update the right block and log the * changes. */ if (level > 0) { /* It's a non-leaf. Move keys and pointers. */ union xfs_btree_key *lkp; /* left btree key */ union xfs_btree_ptr *lpp; /* left address pointer */ union xfs_btree_key *rkp; /* right btree key */ union xfs_btree_ptr *rpp; /* right address pointer */ lkp = xfs_btree_key_addr(cur, src_index, left); lpp = xfs_btree_ptr_addr(cur, src_index, left); rkp = xfs_btree_key_addr(cur, 1, right); rpp = xfs_btree_ptr_addr(cur, 1, right); #ifdef DEBUG for (i = src_index; i < rrecs; i++) { error = xfs_btree_check_ptr(cur, lpp, i, level); if (error) goto error0; } #endif /* Copy the keys & pointers to the new block. */ xfs_btree_copy_keys(cur, rkp, lkp, rrecs); xfs_btree_copy_ptrs(cur, rpp, lpp, rrecs); xfs_btree_log_keys(cur, rbp, 1, rrecs); xfs_btree_log_ptrs(cur, rbp, 1, rrecs); /* Stash the keys of the new block for later insertion. */ xfs_btree_get_node_keys(cur, right, key); } else { /* It's a leaf. Move records. */ union xfs_btree_rec *lrp; /* left record pointer */ union xfs_btree_rec *rrp; /* right record pointer */ lrp = xfs_btree_rec_addr(cur, src_index, left); rrp = xfs_btree_rec_addr(cur, 1, right); /* Copy records to the new block. */ xfs_btree_copy_recs(cur, rrp, lrp, rrecs); xfs_btree_log_recs(cur, rbp, 1, rrecs); /* Stash the keys of the new block for later insertion. */ xfs_btree_get_leaf_keys(cur, right, key); } /* * Find the left block number by looking in the buffer. * Adjust sibling pointers. */ xfs_btree_get_sibling(cur, left, &rrptr, XFS_BB_RIGHTSIB); xfs_btree_set_sibling(cur, right, &rrptr, XFS_BB_RIGHTSIB); xfs_btree_set_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); xfs_btree_set_sibling(cur, left, &rptr, XFS_BB_RIGHTSIB); xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS); xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); /* * If there's a block to the new block's right, make that block * point back to right instead of to left. */ if (!xfs_btree_ptr_is_null(cur, &rrptr)) { error = xfs_btree_read_buf_block(cur, &rrptr, 0, &rrblock, &rrbp); if (error) goto error0; xfs_btree_set_sibling(cur, rrblock, &rptr, XFS_BB_LEFTSIB); xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB); } /* Update the parent high keys of the left block, if needed. */ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) { error = xfs_btree_update_keys(cur, level); if (error) goto error0; } /* * If the cursor is really in the right block, move it there. * If it's just pointing past the last entry in left, then we'll * insert there, so don't change anything in that case. */ if (cur->bc_ptrs[level] > lrecs + 1) { xfs_btree_setbuf(cur, level, rbp); cur->bc_ptrs[level] -= lrecs; } /* * If there are more levels, we'll need another cursor which refers * the right block, no matter where this cursor was. */ if (level + 1 < cur->bc_nlevels) { error = xfs_btree_dup_cursor(cur, curp); if (error) goto error0; (*curp)->bc_ptrs[level + 1]++; } *ptrp = rptr; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; out0: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } #ifdef __KERNEL__ struct xfs_btree_split_args { struct xfs_btree_cur *cur; int level; union xfs_btree_ptr *ptrp; union xfs_btree_key *key; struct xfs_btree_cur **curp; int *stat; /* success/failure */ int result; bool kswapd; /* allocation in kswapd context */ struct completion *done; struct work_struct work; }; /* * Stack switching interfaces for allocation */ static void xfs_btree_split_worker( struct work_struct *work) { struct xfs_btree_split_args *args = container_of(work, struct xfs_btree_split_args, work); unsigned long pflags; unsigned long new_pflags = PF_FSTRANS; /* * we are in a transaction context here, but may also be doing work * in kswapd context, and hence we may need to inherit that state * temporarily to ensure that we don't block waiting for memory reclaim * in any way. */ if (args->kswapd) new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD; current_set_flags_nested(&pflags, new_pflags); args->result = __xfs_btree_split(args->cur, args->level, args->ptrp, args->key, args->curp, args->stat); complete(args->done); current_restore_flags_nested(&pflags, new_pflags); } /* * BMBT split requests often come in with little stack to work on. Push * them off to a worker thread so there is lots of stack to use. For the other * btree types, just call directly to avoid the context switch overhead here. */ STATIC int /* error */ xfs_btree_split( struct xfs_btree_cur *cur, int level, union xfs_btree_ptr *ptrp, union xfs_btree_key *key, struct xfs_btree_cur **curp, int *stat) /* success/failure */ { struct xfs_btree_split_args args; DECLARE_COMPLETION_ONSTACK(done); if (cur->bc_btnum != XFS_BTNUM_BMAP) return __xfs_btree_split(cur, level, ptrp, key, curp, stat); args.cur = cur; args.level = level; args.ptrp = ptrp; args.key = key; args.curp = curp; args.stat = stat; args.done = &done; args.kswapd = current_is_kswapd(); INIT_WORK_ONSTACK(&args.work, xfs_btree_split_worker); queue_work(xfs_alloc_wq, &args.work); wait_for_completion(&done); destroy_work_on_stack(&args.work); return args.result; } #else /* !KERNEL */ #define xfs_btree_split __xfs_btree_split #endif /* * Copy the old inode root contents into a real block and make the * broot point to it. */ int /* error */ xfs_btree_new_iroot( struct xfs_btree_cur *cur, /* btree cursor */ int *logflags, /* logging flags for inode */ int *stat) /* return status - 0 fail */ { struct xfs_buf *cbp; /* buffer for cblock */ struct xfs_btree_block *block; /* btree block */ struct xfs_btree_block *cblock; /* child btree block */ union xfs_btree_key *ckp; /* child key pointer */ union xfs_btree_ptr *cpp; /* child ptr pointer */ union xfs_btree_key *kp; /* pointer to btree key */ union xfs_btree_ptr *pp; /* pointer to block addr */ union xfs_btree_ptr nptr; /* new block addr */ int level; /* btree level */ int error; /* error return code */ #ifdef DEBUG int i; /* loop counter */ #endif XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_STATS_INC(cur, newroot); ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); level = cur->bc_nlevels - 1; block = xfs_btree_get_iroot(cur); pp = xfs_btree_ptr_addr(cur, 1, block); /* Allocate the new block. If we can't do it, we're toast. Give up. */ error = cur->bc_ops->alloc_block(cur, pp, &nptr, stat); if (error) goto error0; if (*stat == 0) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return 0; } XFS_BTREE_STATS_INC(cur, alloc); /* Copy the root into a real block. */ error = xfs_btree_get_buf_block(cur, &nptr, 0, &cblock, &cbp); if (error) goto error0; /* * we can't just memcpy() the root in for CRC enabled btree blocks. * In that case have to also ensure the blkno remains correct */ memcpy(cblock, block, xfs_btree_block_len(cur)); if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) cblock->bb_u.l.bb_blkno = cpu_to_be64(cbp->b_bn); else cblock->bb_u.s.bb_blkno = cpu_to_be64(cbp->b_bn); } be16_add_cpu(&block->bb_level, 1); xfs_btree_set_numrecs(block, 1); cur->bc_nlevels++; cur->bc_ptrs[level + 1] = 1; kp = xfs_btree_key_addr(cur, 1, block); ckp = xfs_btree_key_addr(cur, 1, cblock); xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock)); cpp = xfs_btree_ptr_addr(cur, 1, cblock); #ifdef DEBUG for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { error = xfs_btree_check_ptr(cur, pp, i, level); if (error) goto error0; } #endif xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock)); #ifdef DEBUG error = xfs_btree_check_ptr(cur, &nptr, 0, level); if (error) goto error0; #endif xfs_btree_copy_ptrs(cur, pp, &nptr, 1); xfs_iroot_realloc(cur->bc_private.b.ip, 1 - xfs_btree_get_numrecs(cblock), cur->bc_private.b.whichfork); xfs_btree_setbuf(cur, level, cbp); /* * Do all this logging at the end so that * the root is at the right level. */ xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS); xfs_btree_log_keys(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs)); xfs_btree_log_ptrs(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs)); *logflags |= XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_private.b.whichfork); *stat = 1; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } /* * Allocate a new root block, fill it in. */ STATIC int /* error */ xfs_btree_new_root( struct xfs_btree_cur *cur, /* btree cursor */ int *stat) /* success/failure */ { struct xfs_btree_block *block; /* one half of the old root block */ struct xfs_buf *bp; /* buffer containing block */ int error; /* error return value */ struct xfs_buf *lbp; /* left buffer pointer */ struct xfs_btree_block *left; /* left btree block */ struct xfs_buf *nbp; /* new (root) buffer */ struct xfs_btree_block *new; /* new (root) btree block */ int nptr; /* new value for key index, 1 or 2 */ struct xfs_buf *rbp; /* right buffer pointer */ struct xfs_btree_block *right; /* right btree block */ union xfs_btree_ptr rptr; union xfs_btree_ptr lptr; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_STATS_INC(cur, newroot); /* initialise our start point from the cursor */ cur->bc_ops->init_ptr_from_cur(cur, &rptr); /* Allocate the new block. If we can't do it, we're toast. Give up. */ error = cur->bc_ops->alloc_block(cur, &rptr, &lptr, stat); if (error) goto error0; if (*stat == 0) goto out0; XFS_BTREE_STATS_INC(cur, alloc); /* Set up the new block. */ error = xfs_btree_get_buf_block(cur, &lptr, 0, &new, &nbp); if (error) goto error0; /* Set the root in the holding structure increasing the level by 1. */ cur->bc_ops->set_root(cur, &lptr, 1); /* * At the previous root level there are now two blocks: the old root, * and the new block generated when it was split. We don't know which * one the cursor is pointing at, so we set up variables "left" and * "right" for each case. */ block = xfs_btree_get_block(cur, cur->bc_nlevels - 1, &bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, cur->bc_nlevels - 1, bp); if (error) goto error0; #endif xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); if (!xfs_btree_ptr_is_null(cur, &rptr)) { /* Our block is left, pick up the right block. */ lbp = bp; xfs_btree_buf_to_ptr(cur, lbp, &lptr); left = block; error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp); if (error) goto error0; bp = rbp; nptr = 1; } else { /* Our block is right, pick up the left block. */ rbp = bp; xfs_btree_buf_to_ptr(cur, rbp, &rptr); right = block; xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp); if (error) goto error0; bp = lbp; nptr = 2; } /* Fill in the new block's btree header and log it. */ xfs_btree_init_block_cur(cur, nbp, cur->bc_nlevels, 2); xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS); ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) && !xfs_btree_ptr_is_null(cur, &rptr)); /* Fill in the key data in the new root. */ if (xfs_btree_get_level(left) > 0) { /* * Get the keys for the left block's keys and put them directly * in the parent block. Do the same for the right block. */ xfs_btree_get_node_keys(cur, left, xfs_btree_key_addr(cur, 1, new)); xfs_btree_get_node_keys(cur, right, xfs_btree_key_addr(cur, 2, new)); } else { /* * Get the keys for the left block's records and put them * directly in the parent block. Do the same for the right * block. */ xfs_btree_get_leaf_keys(cur, left, xfs_btree_key_addr(cur, 1, new)); xfs_btree_get_leaf_keys(cur, right, xfs_btree_key_addr(cur, 2, new)); } xfs_btree_log_keys(cur, nbp, 1, 2); /* Fill in the pointer data in the new root. */ xfs_btree_copy_ptrs(cur, xfs_btree_ptr_addr(cur, 1, new), &lptr, 1); xfs_btree_copy_ptrs(cur, xfs_btree_ptr_addr(cur, 2, new), &rptr, 1); xfs_btree_log_ptrs(cur, nbp, 1, 2); /* Fix up the cursor. */ xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); cur->bc_ptrs[cur->bc_nlevels] = nptr; cur->bc_nlevels++; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; out0: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } STATIC int xfs_btree_make_block_unfull( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* btree level */ int numrecs,/* # of recs in block */ int *oindex,/* old tree index */ int *index, /* new tree index */ union xfs_btree_ptr *nptr, /* new btree ptr */ struct xfs_btree_cur **ncur, /* new btree cursor */ union xfs_btree_key *key, /* key of new block */ int *stat) { int error = 0; if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && level == cur->bc_nlevels - 1) { struct xfs_inode *ip = cur->bc_private.b.ip; if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) { /* A root block that can be made bigger. */ xfs_iroot_realloc(ip, 1, cur->bc_private.b.whichfork); *stat = 1; } else { /* A root block that needs replacing */ int logflags = 0; error = xfs_btree_new_iroot(cur, &logflags, stat); if (error || *stat == 0) return error; xfs_trans_log_inode(cur->bc_tp, ip, logflags); } return 0; } /* First, try shifting an entry to the right neighbor. */ error = xfs_btree_rshift(cur, level, stat); if (error || *stat) return error; /* Next, try shifting an entry to the left neighbor. */ error = xfs_btree_lshift(cur, level, stat); if (error) return error; if (*stat) { *oindex = *index = cur->bc_ptrs[level]; return 0; } /* * Next, try splitting the current block in half. * * If this works we have to re-set our variables because we * could be in a different block now. */ error = xfs_btree_split(cur, level, nptr, key, ncur, stat); if (error || *stat == 0) return error; *index = cur->bc_ptrs[level]; return 0; } /* * Insert one record/level. Return information to the caller * allowing the next level up to proceed if necessary. */ STATIC int xfs_btree_insrec( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level to insert record at */ union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ union xfs_btree_rec *rec, /* record to insert */ union xfs_btree_key *key, /* i/o: block key for ptrp */ struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ int *stat) /* success/failure */ { struct xfs_btree_block *block; /* btree block */ struct xfs_buf *bp; /* buffer for block */ union xfs_btree_ptr nptr; /* new block ptr */ struct xfs_btree_cur *ncur; /* new btree cursor */ union xfs_btree_key nkey; /* new block key */ union xfs_btree_key *lkey; int optr; /* old key/record index */ int ptr; /* key/record index */ int numrecs;/* number of records */ int error; /* error return value */ #ifdef DEBUG int i; #endif xfs_daddr_t old_bn; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, &rec); ncur = NULL; lkey = &nkey; /* * If we have an external root pointer, and we've made it to the * root level, allocate a new root block and we're done. */ if (!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && (level >= cur->bc_nlevels)) { error = xfs_btree_new_root(cur, stat); xfs_btree_set_ptr_null(cur, ptrp); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return error; } /* If we're off the left edge, return failure. */ ptr = cur->bc_ptrs[level]; if (ptr == 0) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } optr = ptr; XFS_BTREE_STATS_INC(cur, insrec); /* Get pointers to the btree buffer and block. */ block = xfs_btree_get_block(cur, level, &bp); old_bn = bp ? bp->b_bn : XFS_BUF_DADDR_NULL; numrecs = xfs_btree_get_numrecs(block); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) goto error0; /* Check that the new entry is being inserted in the right place. */ if (ptr <= numrecs) { if (level == 0) { ASSERT(cur->bc_ops->recs_inorder(cur, rec, xfs_btree_rec_addr(cur, ptr, block))); } else { ASSERT(cur->bc_ops->keys_inorder(cur, key, xfs_btree_key_addr(cur, ptr, block))); } } #endif /* * If the block is full, we can't insert the new entry until we * make the block un-full. */ xfs_btree_set_ptr_null(cur, &nptr); if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) { error = xfs_btree_make_block_unfull(cur, level, numrecs, &optr, &ptr, &nptr, &ncur, lkey, stat); if (error || *stat == 0) goto error0; } /* * The current block may have changed if the block was * previously full and we have just made space in it. */ block = xfs_btree_get_block(cur, level, &bp); numrecs = xfs_btree_get_numrecs(block); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) return error; #endif /* * At this point we know there's room for our new entry in the block * we're pointing at. */ XFS_BTREE_STATS_ADD(cur, moves, numrecs - ptr + 1); if (level > 0) { /* It's a nonleaf. make a hole in the keys and ptrs */ union xfs_btree_key *kp; union xfs_btree_ptr *pp; kp = xfs_btree_key_addr(cur, ptr, block); pp = xfs_btree_ptr_addr(cur, ptr, block); #ifdef DEBUG for (i = numrecs - ptr; i >= 0; i--) { error = xfs_btree_check_ptr(cur, pp, i, level); if (error) return error; } #endif xfs_btree_shift_keys(cur, kp, 1, numrecs - ptr + 1); xfs_btree_shift_ptrs(cur, pp, 1, numrecs - ptr + 1); #ifdef DEBUG error = xfs_btree_check_ptr(cur, ptrp, 0, level); if (error) goto error0; #endif /* Now put the new data in, bump numrecs and log it. */ xfs_btree_copy_keys(cur, kp, key, 1); xfs_btree_copy_ptrs(cur, pp, ptrp, 1); numrecs++; xfs_btree_set_numrecs(block, numrecs); xfs_btree_log_ptrs(cur, bp, ptr, numrecs); xfs_btree_log_keys(cur, bp, ptr, numrecs); #ifdef DEBUG if (ptr < numrecs) { ASSERT(cur->bc_ops->keys_inorder(cur, kp, xfs_btree_key_addr(cur, ptr + 1, block))); } #endif } else { /* It's a leaf. make a hole in the records */ union xfs_btree_rec *rp; rp = xfs_btree_rec_addr(cur, ptr, block); xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1); /* Now put the new data in, bump numrecs and log it. */ xfs_btree_copy_recs(cur, rp, rec, 1); xfs_btree_set_numrecs(block, ++numrecs); xfs_btree_log_recs(cur, bp, ptr, numrecs); #ifdef DEBUG if (ptr < numrecs) { ASSERT(cur->bc_ops->recs_inorder(cur, rp, xfs_btree_rec_addr(cur, ptr + 1, block))); } #endif } /* Log the new number of records in the btree header. */ xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); /* * If we just inserted into a new tree block, we have to * recalculate nkey here because nkey is out of date. * * Otherwise we're just updating an existing block (having shoved * some records into the new tree block), so use the regular key * update mechanism. */ if (bp && bp->b_bn != old_bn) { xfs_btree_get_keys(cur, block, lkey); } else if (xfs_btree_needs_key_update(cur, optr)) { error = xfs_btree_update_keys(cur, level); if (error) goto error0; } /* * If we are tracking the last record in the tree and * we are at the far right edge of the tree, update it. */ if (xfs_btree_is_lastrec(cur, block, level)) { cur->bc_ops->update_lastrec(cur, block, rec, ptr, LASTREC_INSREC); } /* * Return the new block number, if any. * If there is one, give back a record value and a cursor too. */ *ptrp = nptr; if (!xfs_btree_ptr_is_null(cur, &nptr)) { xfs_btree_copy_keys(cur, key, lkey, 1); *curp = ncur; } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } /* * Insert the record at the point referenced by cur. * * A multi-level split of the tree on insert will invalidate the original * cursor. All callers of this function should assume that the cursor is * no longer valid and revalidate it. */ int xfs_btree_insert( struct xfs_btree_cur *cur, int *stat) { int error; /* error return value */ int i; /* result value, 0 for failure */ int level; /* current level number in btree */ union xfs_btree_ptr nptr; /* new block number (split result) */ struct xfs_btree_cur *ncur; /* new cursor (split result) */ struct xfs_btree_cur *pcur; /* previous level's cursor */ union xfs_btree_key bkey; /* key of block to insert */ union xfs_btree_key *key; union xfs_btree_rec rec; /* record to insert */ level = 0; ncur = NULL; pcur = cur; key = &bkey; xfs_btree_set_ptr_null(cur, &nptr); /* Make a key out of the record data to be inserted, and save it. */ cur->bc_ops->init_rec_from_cur(cur, &rec); cur->bc_ops->init_key_from_rec(key, &rec); /* * Loop going up the tree, starting at the leaf level. * Stop when we don't get a split block, that must mean that * the insert is finished with this level. */ do { /* * Insert nrec/nptr into this level of the tree. * Note if we fail, nptr will be null. */ error = xfs_btree_insrec(pcur, level, &nptr, &rec, key, &ncur, &i); if (error) { if (pcur != cur) xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); goto error0; } XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); level++; /* * See if the cursor we just used is trash. * Can't trash the caller's cursor, but otherwise we should * if ncur is a new cursor or we're about to be done. */ if (pcur != cur && (ncur || xfs_btree_ptr_is_null(cur, &nptr))) { /* Save the state from the cursor before we trash it */ if (cur->bc_ops->update_cursor) cur->bc_ops->update_cursor(pcur, cur); cur->bc_nlevels = pcur->bc_nlevels; xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); } /* If we got a new cursor, switch to it. */ if (ncur) { pcur = ncur; ncur = NULL; } } while (!xfs_btree_ptr_is_null(cur, &nptr)); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = i; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } /* * Try to merge a non-leaf block back into the inode root. * * Note: the killroot names comes from the fact that we're effectively * killing the old root block. But because we can't just delete the * inode we have to copy the single block it was pointing to into the * inode. */ STATIC int xfs_btree_kill_iroot( struct xfs_btree_cur *cur) { int whichfork = cur->bc_private.b.whichfork; struct xfs_inode *ip = cur->bc_private.b.ip; struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_btree_block *block; struct xfs_btree_block *cblock; union xfs_btree_key *kp; union xfs_btree_key *ckp; union xfs_btree_ptr *pp; union xfs_btree_ptr *cpp; struct xfs_buf *cbp; int level; int index; int numrecs; int error; #ifdef DEBUG union xfs_btree_ptr ptr; int i; #endif XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); ASSERT(cur->bc_nlevels > 1); /* * Don't deal with the root block needs to be a leaf case. * We're just going to turn the thing back into extents anyway. */ level = cur->bc_nlevels - 1; if (level == 1) goto out0; /* * Give up if the root has multiple children. */ block = xfs_btree_get_iroot(cur); if (xfs_btree_get_numrecs(block) != 1) goto out0; cblock = xfs_btree_get_block(cur, level - 1, &cbp); numrecs = xfs_btree_get_numrecs(cblock); /* * Only do this if the next level will fit. * Then the data must be copied up to the inode, * instead of freeing the root you free the next level. */ if (numrecs > cur->bc_ops->get_dmaxrecs(cur, level)) goto out0; XFS_BTREE_STATS_INC(cur, killroot); #ifdef DEBUG xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_LEFTSIB); ASSERT(xfs_btree_ptr_is_null(cur, &ptr)); xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); ASSERT(xfs_btree_ptr_is_null(cur, &ptr)); #endif index = numrecs - cur->bc_ops->get_maxrecs(cur, level); if (index) { xfs_iroot_realloc(cur->bc_private.b.ip, index, cur->bc_private.b.whichfork); block = ifp->if_broot; } be16_add_cpu(&block->bb_numrecs, index); ASSERT(block->bb_numrecs == cblock->bb_numrecs); kp = xfs_btree_key_addr(cur, 1, block); ckp = xfs_btree_key_addr(cur, 1, cblock); xfs_btree_copy_keys(cur, kp, ckp, numrecs); pp = xfs_btree_ptr_addr(cur, 1, block); cpp = xfs_btree_ptr_addr(cur, 1, cblock); #ifdef DEBUG for (i = 0; i < numrecs; i++) { error = xfs_btree_check_ptr(cur, cpp, i, level - 1); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } } #endif xfs_btree_copy_ptrs(cur, pp, cpp, numrecs); error = xfs_btree_free_block(cur, cbp); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } cur->bc_bufs[level - 1] = NULL; be16_add_cpu(&block->bb_level, -1); xfs_trans_log_inode(cur->bc_tp, ip, XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_private.b.whichfork)); cur->bc_nlevels--; out0: XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return 0; } /* * Kill the current root node, and replace it with it's only child node. */ STATIC int xfs_btree_kill_root( struct xfs_btree_cur *cur, struct xfs_buf *bp, int level, union xfs_btree_ptr *newroot) { int error; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_STATS_INC(cur, killroot); /* * Update the root pointer, decreasing the level by 1 and then * free the old root. */ cur->bc_ops->set_root(cur, newroot, -1); error = xfs_btree_free_block(cur, bp); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } cur->bc_bufs[level] = NULL; cur->bc_ra[level] = 0; cur->bc_nlevels--; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); return 0; } STATIC int xfs_btree_dec_cursor( struct xfs_btree_cur *cur, int level, int *stat) { int error; int i; if (level > 0) { error = xfs_btree_decrement(cur, level, &i); if (error) return error; } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; } /* * Single level of the btree record deletion routine. * Delete record pointed to by cur/level. * Remove the record from its block then rebalance the tree. * Return 0 for error, 1 for done, 2 to go on to the next level. */ STATIC int /* error */ xfs_btree_delrec( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level removing record from */ int *stat) /* fail/done/go-on */ { struct xfs_btree_block *block; /* btree block */ union xfs_btree_ptr cptr; /* current block ptr */ struct xfs_buf *bp; /* buffer for block */ int error; /* error return value */ int i; /* loop counter */ union xfs_btree_ptr lptr; /* left sibling block ptr */ struct xfs_buf *lbp; /* left buffer pointer */ struct xfs_btree_block *left; /* left btree block */ int lrecs = 0; /* left record count */ int ptr; /* key/record index */ union xfs_btree_ptr rptr; /* right sibling block ptr */ struct xfs_buf *rbp; /* right buffer pointer */ struct xfs_btree_block *right; /* right btree block */ struct xfs_btree_block *rrblock; /* right-right btree block */ struct xfs_buf *rrbp; /* right-right buffer pointer */ int rrecs = 0; /* right record count */ struct xfs_btree_cur *tcur; /* temporary btree cursor */ int numrecs; /* temporary numrec count */ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGI(cur, level); tcur = NULL; /* Get the index of the entry being deleted, check for nothing there. */ ptr = cur->bc_ptrs[level]; if (ptr == 0) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } /* Get the buffer & block containing the record or key/ptr. */ block = xfs_btree_get_block(cur, level, &bp); numrecs = xfs_btree_get_numrecs(block); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) goto error0; #endif /* Fail if we're off the end of the block. */ if (ptr > numrecs) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } XFS_BTREE_STATS_INC(cur, delrec); XFS_BTREE_STATS_ADD(cur, moves, numrecs - ptr); /* Excise the entries being deleted. */ if (level > 0) { /* It's a nonleaf. operate on keys and ptrs */ union xfs_btree_key *lkp; union xfs_btree_ptr *lpp; lkp = xfs_btree_key_addr(cur, ptr + 1, block); lpp = xfs_btree_ptr_addr(cur, ptr + 1, block); #ifdef DEBUG for (i = 0; i < numrecs - ptr; i++) { error = xfs_btree_check_ptr(cur, lpp, i, level); if (error) goto error0; } #endif if (ptr < numrecs) { xfs_btree_shift_keys(cur, lkp, -1, numrecs - ptr); xfs_btree_shift_ptrs(cur, lpp, -1, numrecs - ptr); xfs_btree_log_keys(cur, bp, ptr, numrecs - 1); xfs_btree_log_ptrs(cur, bp, ptr, numrecs - 1); } } else { /* It's a leaf. operate on records */ if (ptr < numrecs) { xfs_btree_shift_recs(cur, xfs_btree_rec_addr(cur, ptr + 1, block), -1, numrecs - ptr); xfs_btree_log_recs(cur, bp, ptr, numrecs - 1); } } /* * Decrement and log the number of entries in the block. */ xfs_btree_set_numrecs(block, --numrecs); xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); /* * If we are tracking the last record in the tree and * we are at the far right edge of the tree, update it. */ if (xfs_btree_is_lastrec(cur, block, level)) { cur->bc_ops->update_lastrec(cur, block, NULL, ptr, LASTREC_DELREC); } /* * We're at the root level. First, shrink the root block in-memory. * Try to get rid of the next level down. If we can't then there's * nothing left to do. */ if (level == cur->bc_nlevels - 1) { if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) { xfs_iroot_realloc(cur->bc_private.b.ip, -1, cur->bc_private.b.whichfork); error = xfs_btree_kill_iroot(cur); if (error) goto error0; error = xfs_btree_dec_cursor(cur, level, stat); if (error) goto error0; *stat = 1; return 0; } /* * If this is the root level, and there's only one entry left, * and it's NOT the leaf level, then we can get rid of this * level. */ if (numrecs == 1 && level > 0) { union xfs_btree_ptr *pp; /* * pp is still set to the first pointer in the block. * Make it the new root of the btree. */ pp = xfs_btree_ptr_addr(cur, 1, block); error = xfs_btree_kill_root(cur, bp, level, pp); if (error) goto error0; } else if (level > 0) { error = xfs_btree_dec_cursor(cur, level, stat); if (error) goto error0; } *stat = 1; return 0; } /* * If we deleted the leftmost entry in the block, update the * key values above us in the tree. */ if (xfs_btree_needs_key_update(cur, ptr)) { error = xfs_btree_update_keys(cur, level); if (error) goto error0; } /* * If the number of records remaining in the block is at least * the minimum, we're done. */ if (numrecs >= cur->bc_ops->get_minrecs(cur, level)) { error = xfs_btree_dec_cursor(cur, level, stat); if (error) goto error0; return 0; } /* * Otherwise, we have to move some records around to keep the * tree balanced. Look at the left and right sibling blocks to * see if we can re-balance by moving only one record. */ xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); xfs_btree_get_sibling(cur, block, &lptr, XFS_BB_LEFTSIB); if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) { /* * One child of root, need to get a chance to copy its contents * into the root and delete it. Can't go up to next level, * there's nothing to delete there. */ if (xfs_btree_ptr_is_null(cur, &rptr) && xfs_btree_ptr_is_null(cur, &lptr) && level == cur->bc_nlevels - 2) { error = xfs_btree_kill_iroot(cur); if (!error) error = xfs_btree_dec_cursor(cur, level, stat); if (error) goto error0; return 0; } } ASSERT(!xfs_btree_ptr_is_null(cur, &rptr) || !xfs_btree_ptr_is_null(cur, &lptr)); /* * Duplicate the cursor so our btree manipulations here won't * disrupt the next level up. */ error = xfs_btree_dup_cursor(cur, &tcur); if (error) goto error0; /* * If there's a right sibling, see if it's ok to shift an entry * out of it. */ if (!xfs_btree_ptr_is_null(cur, &rptr)) { /* * Move the temp cursor to the last entry in the next block. * Actually any entry but the first would suffice. */ i = xfs_btree_lastrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); error = xfs_btree_increment(tcur, level, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); i = xfs_btree_lastrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); /* Grab a pointer to the block. */ right = xfs_btree_get_block(tcur, level, &rbp); #ifdef DEBUG error = xfs_btree_check_block(tcur, right, level, rbp); if (error) goto error0; #endif /* Grab the current block number, for future use. */ xfs_btree_get_sibling(tcur, right, &cptr, XFS_BB_LEFTSIB); /* * If right block is full enough so that removing one entry * won't make it too empty, and left-shifting an entry out * of right to us works, we're done. */ if (xfs_btree_get_numrecs(right) - 1 >= cur->bc_ops->get_minrecs(tcur, level)) { error = xfs_btree_lshift(tcur, level, &i); if (error) goto error0; if (i) { ASSERT(xfs_btree_get_numrecs(block) >= cur->bc_ops->get_minrecs(tcur, level)); xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); tcur = NULL; error = xfs_btree_dec_cursor(cur, level, stat); if (error) goto error0; return 0; } } /* * Otherwise, grab the number of records in right for * future reference, and fix up the temp cursor to point * to our block again (last record). */ rrecs = xfs_btree_get_numrecs(right); if (!xfs_btree_ptr_is_null(cur, &lptr)) { i = xfs_btree_firstrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); error = xfs_btree_decrement(tcur, level, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); } } /* * If there's a left sibling, see if it's ok to shift an entry * out of it. */ if (!xfs_btree_ptr_is_null(cur, &lptr)) { /* * Move the temp cursor to the first entry in the * previous block. */ i = xfs_btree_firstrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); error = xfs_btree_decrement(tcur, level, &i); if (error) goto error0; i = xfs_btree_firstrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); /* Grab a pointer to the block. */ left = xfs_btree_get_block(tcur, level, &lbp); #ifdef DEBUG error = xfs_btree_check_block(cur, left, level, lbp); if (error) goto error0; #endif /* Grab the current block number, for future use. */ xfs_btree_get_sibling(tcur, left, &cptr, XFS_BB_RIGHTSIB); /* * If left block is full enough so that removing one entry * won't make it too empty, and right-shifting an entry out * of left to us works, we're done. */ if (xfs_btree_get_numrecs(left) - 1 >= cur->bc_ops->get_minrecs(tcur, level)) { error = xfs_btree_rshift(tcur, level, &i); if (error) goto error0; if (i) { ASSERT(xfs_btree_get_numrecs(block) >= cur->bc_ops->get_minrecs(tcur, level)); xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); tcur = NULL; if (level == 0) cur->bc_ptrs[0]++; XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; } } /* * Otherwise, grab the number of records in right for * future reference. */ lrecs = xfs_btree_get_numrecs(left); } /* Delete the temp cursor, we're done with it. */ xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); tcur = NULL; /* If here, we need to do a join to keep the tree balanced. */ ASSERT(!xfs_btree_ptr_is_null(cur, &cptr)); if (!xfs_btree_ptr_is_null(cur, &lptr) && lrecs + xfs_btree_get_numrecs(block) <= cur->bc_ops->get_maxrecs(cur, level)) { /* * Set "right" to be the starting block, * "left" to be the left neighbor. */ rptr = cptr; right = block; rbp = bp; error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp); if (error) goto error0; /* * If that won't work, see if we can join with the right neighbor block. */ } else if (!xfs_btree_ptr_is_null(cur, &rptr) && rrecs + xfs_btree_get_numrecs(block) <= cur->bc_ops->get_maxrecs(cur, level)) { /* * Set "left" to be the starting block, * "right" to be the right neighbor. */ lptr = cptr; left = block; lbp = bp; error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp); if (error) goto error0; /* * Otherwise, we can't fix the imbalance. * Just return. This is probably a logic error, but it's not fatal. */ } else { error = xfs_btree_dec_cursor(cur, level, stat); if (error) goto error0; return 0; } rrecs = xfs_btree_get_numrecs(right); lrecs = xfs_btree_get_numrecs(left); /* * We're now going to join "left" and "right" by moving all the stuff * in "right" to "left" and deleting "right". */ XFS_BTREE_STATS_ADD(cur, moves, rrecs); if (level > 0) { /* It's a non-leaf. Move keys and pointers. */ union xfs_btree_key *lkp; /* left btree key */ union xfs_btree_ptr *lpp; /* left address pointer */ union xfs_btree_key *rkp; /* right btree key */ union xfs_btree_ptr *rpp; /* right address pointer */ lkp = xfs_btree_key_addr(cur, lrecs + 1, left); lpp = xfs_btree_ptr_addr(cur, lrecs + 1, left); rkp = xfs_btree_key_addr(cur, 1, right); rpp = xfs_btree_ptr_addr(cur, 1, right); #ifdef DEBUG for (i = 1; i < rrecs; i++) { error = xfs_btree_check_ptr(cur, rpp, i, level); if (error) goto error0; } #endif xfs_btree_copy_keys(cur, lkp, rkp, rrecs); xfs_btree_copy_ptrs(cur, lpp, rpp, rrecs); xfs_btree_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs); xfs_btree_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs); } else { /* It's a leaf. Move records. */ union xfs_btree_rec *lrp; /* left record pointer */ union xfs_btree_rec *rrp; /* right record pointer */ lrp = xfs_btree_rec_addr(cur, lrecs + 1, left); rrp = xfs_btree_rec_addr(cur, 1, right); xfs_btree_copy_recs(cur, lrp, rrp, rrecs); xfs_btree_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs); } XFS_BTREE_STATS_INC(cur, join); /* * Fix up the number of records and right block pointer in the * surviving block, and log it. */ xfs_btree_set_numrecs(left, lrecs + rrecs); xfs_btree_get_sibling(cur, right, &cptr, XFS_BB_RIGHTSIB), xfs_btree_set_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB); xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); /* If there is a right sibling, point it to the remaining block. */ xfs_btree_get_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB); if (!xfs_btree_ptr_is_null(cur, &cptr)) { error = xfs_btree_read_buf_block(cur, &cptr, 0, &rrblock, &rrbp); if (error) goto error0; xfs_btree_set_sibling(cur, rrblock, &lptr, XFS_BB_LEFTSIB); xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB); } /* Free the deleted block. */ error = xfs_btree_free_block(cur, rbp); if (error) goto error0; /* * If we joined with the left neighbor, set the buffer in the * cursor to the left block, and fix up the index. */ if (bp != lbp) { cur->bc_bufs[level] = lbp; cur->bc_ptrs[level] += lrecs; cur->bc_ra[level] = 0; } /* * If we joined with the right neighbor and there's a level above * us, increment the cursor at that level. */ else if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) || (level + 1 < cur->bc_nlevels)) { error = xfs_btree_increment(cur, level + 1, &i); if (error) goto error0; } /* * Readjust the ptr at this level if it's not a leaf, since it's * still pointing at the deletion point, which makes the cursor * inconsistent. If this makes the ptr 0, the caller fixes it up. * We can't use decrement because it would change the next level up. */ if (level > 0) cur->bc_ptrs[level]--; /* * We combined blocks, so we have to update the parent keys if the * btree supports overlapped intervals. However, bc_ptrs[level + 1] * points to the old block so that the caller knows which record to * delete. Therefore, the caller must be savvy enough to call updkeys * for us if we return stat == 2. The other exit points from this * function don't require deletions further up the tree, so they can * call updkeys directly. */ XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); /* Return value means the next level up has something to do. */ *stat = 2; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); if (tcur) xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); return error; } /* * Delete the record pointed to by cur. * The cursor refers to the place where the record was (could be inserted) * when the operation returns. */ int /* error */ xfs_btree_delete( struct xfs_btree_cur *cur, int *stat) /* success/failure */ { int error; /* error return value */ int level; int i; bool joined = false; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); /* * Go up the tree, starting at leaf level. * * If 2 is returned then a join was done; go to the next level. * Otherwise we are done. */ for (level = 0, i = 2; i == 2; level++) { error = xfs_btree_delrec(cur, level, &i); if (error) goto error0; if (i == 2) joined = true; } /* * If we combined blocks as part of deleting the record, delrec won't * have updated the parent high keys so we have to do that here. */ if (joined && (cur->bc_flags & XFS_BTREE_OVERLAPPING)) { error = xfs_btree_updkeys_force(cur, 0); if (error) goto error0; } if (i == 0) { for (level = 1; level < cur->bc_nlevels; level++) { if (cur->bc_ptrs[level] == 0) { error = xfs_btree_decrement(cur, level, &i); if (error) goto error0; break; } } } XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = i; return 0; error0: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } /* * Get the data from the pointed-to record. */ int /* error */ xfs_btree_get_rec( struct xfs_btree_cur *cur, /* btree cursor */ union xfs_btree_rec **recp, /* output: btree record */ int *stat) /* output: success/failure */ { struct xfs_btree_block *block; /* btree block */ struct xfs_buf *bp; /* buffer pointer */ int ptr; /* record number */ #ifdef DEBUG int error; /* error return value */ #endif ptr = cur->bc_ptrs[0]; block = xfs_btree_get_block(cur, 0, &bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, 0, bp); if (error) return error; #endif /* * Off the right end or left end, return failure. */ if (ptr > xfs_btree_get_numrecs(block) || ptr <= 0) { *stat = 0; return 0; } /* * Point to the record and extract its data. */ *recp = xfs_btree_rec_addr(cur, ptr, block); *stat = 1; return 0; } /* Visit a block in a btree. */ STATIC int xfs_btree_visit_block( struct xfs_btree_cur *cur, int level, xfs_btree_visit_blocks_fn fn, void *data) { struct xfs_btree_block *block; struct xfs_buf *bp; union xfs_btree_ptr rptr; int error; /* do right sibling readahead */ xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); block = xfs_btree_get_block(cur, level, &bp); /* process the block */ error = fn(cur, level, data); if (error) return error; /* now read rh sibling block for next iteration */ xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); if (xfs_btree_ptr_is_null(cur, &rptr)) return -ENOENT; return xfs_btree_lookup_get_block(cur, level, &rptr, &block); } /* Visit every block in a btree. */ int xfs_btree_visit_blocks( struct xfs_btree_cur *cur, xfs_btree_visit_blocks_fn fn, void *data) { union xfs_btree_ptr lptr; int level; struct xfs_btree_block *block = NULL; int error = 0; cur->bc_ops->init_ptr_from_cur(cur, &lptr); /* for each level */ for (level = cur->bc_nlevels - 1; level >= 0; level--) { /* grab the left hand block */ error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); if (error) return error; /* readahead the left most block for the next level down */ if (level > 0) { union xfs_btree_ptr *ptr; ptr = xfs_btree_ptr_addr(cur, 1, block); xfs_btree_readahead_ptr(cur, ptr, 1); /* save for the next iteration of the loop */ lptr = *ptr; } /* for each buffer in the level */ do { error = xfs_btree_visit_block(cur, level, fn, data); } while (!error); if (error != -ENOENT) return error; } return 0; } /* * Change the owner of a btree. * * The mechanism we use here is ordered buffer logging. Because we don't know * how many buffers were are going to need to modify, we don't really want to * have to make transaction reservations for the worst case of every buffer in a * full size btree as that may be more space that we can fit in the log.... * * We do the btree walk in the most optimal manner possible - we have sibling * pointers so we can just walk all the blocks on each level from left to right * in a single pass, and then move to the next level and do the same. We can * also do readahead on the sibling pointers to get IO moving more quickly, * though for slow disks this is unlikely to make much difference to performance * as the amount of CPU work we have to do before moving to the next block is * relatively small. * * For each btree block that we load, modify the owner appropriately, set the * buffer as an ordered buffer and log it appropriately. We need to ensure that * we mark the region we change dirty so that if the buffer is relogged in * a subsequent transaction the changes we make here as an ordered buffer are * correctly relogged in that transaction. If we are in recovery context, then * just queue the modified buffer as delayed write buffer so the transaction * recovery completion writes the changes to disk. */ struct xfs_btree_block_change_owner_info { __uint64_t new_owner; struct list_head *buffer_list; }; static int xfs_btree_block_change_owner( struct xfs_btree_cur *cur, int level, void *data) { struct xfs_btree_block_change_owner_info *bbcoi = data; struct xfs_btree_block *block; struct xfs_buf *bp; /* modify the owner */ block = xfs_btree_get_block(cur, level, &bp); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) block->bb_u.l.bb_owner = cpu_to_be64(bbcoi->new_owner); else block->bb_u.s.bb_owner = cpu_to_be32(bbcoi->new_owner); /* * If the block is a root block hosted in an inode, we might not have a * buffer pointer here and we shouldn't attempt to log the change as the * information is already held in the inode and discarded when the root * block is formatted into the on-disk inode fork. We still change it, * though, so everything is consistent in memory. */ if (bp) { if (cur->bc_tp) { xfs_trans_ordered_buf(cur->bc_tp, bp); xfs_btree_log_block(cur, bp, XFS_BB_OWNER); } else { xfs_buf_delwri_queue(bp, bbcoi->buffer_list); } } else { ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); ASSERT(level == cur->bc_nlevels - 1); } return 0; } int xfs_btree_change_owner( struct xfs_btree_cur *cur, __uint64_t new_owner, struct list_head *buffer_list) { struct xfs_btree_block_change_owner_info bbcoi; bbcoi.new_owner = new_owner; bbcoi.buffer_list = buffer_list; return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner, &bbcoi); } /** * xfs_btree_sblock_v5hdr_verify() -- verify the v5 fields of a short-format * btree block * * @bp: buffer containing the btree block * @max_recs: pointer to the m_*_mxr max records field in the xfs mount * @pag_max_level: pointer to the per-ag max level field */ bool xfs_btree_sblock_v5hdr_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_perag *pag = bp->b_pag; if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) return false; if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) return false; if (pag && be32_to_cpu(block->bb_u.s.bb_owner) != pag->pag_agno) return false; return true; } /** * xfs_btree_sblock_verify() -- verify a short-format btree block * * @bp: buffer containing the btree block * @max_recs: maximum records allowed in this btree node */ bool xfs_btree_sblock_verify( struct xfs_buf *bp, unsigned int max_recs) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); /* numrecs verification */ if (be16_to_cpu(block->bb_numrecs) > max_recs) return false; /* sibling pointer verification */ if (!block->bb_u.s.bb_leftsib || (be32_to_cpu(block->bb_u.s.bb_leftsib) >= mp->m_sb.sb_agblocks && block->bb_u.s.bb_leftsib != cpu_to_be32(NULLAGBLOCK))) return false; if (!block->bb_u.s.bb_rightsib || (be32_to_cpu(block->bb_u.s.bb_rightsib) >= mp->m_sb.sb_agblocks && block->bb_u.s.bb_rightsib != cpu_to_be32(NULLAGBLOCK))) return false; return true; } /* * Calculate the number of btree levels needed to store a given number of * records in a short-format btree. */ uint xfs_btree_compute_maxlevels( struct xfs_mount *mp, uint *limits, unsigned long len) { uint level; unsigned long maxblocks; maxblocks = (len + limits[0] - 1) / limits[0]; for (level = 1; maxblocks > 1; level++) maxblocks = (maxblocks + limits[1] - 1) / limits[1]; return level; } /* * Query a regular btree for all records overlapping a given interval. * Start with a LE lookup of the key of low_rec and return all records * until we find a record with a key greater than the key of high_rec. */ STATIC int xfs_btree_simple_query_range( struct xfs_btree_cur *cur, union xfs_btree_key *low_key, union xfs_btree_key *high_key, xfs_btree_query_range_fn fn, void *priv) { union xfs_btree_rec *recp; union xfs_btree_key rec_key; __int64_t diff; int stat; bool firstrec = true; int error; ASSERT(cur->bc_ops->init_high_key_from_rec); ASSERT(cur->bc_ops->diff_two_keys); /* * Find the leftmost record. The btree cursor must be set * to the low record used to generate low_key. */ stat = 0; error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat); if (error) goto out; /* Nothing? See if there's anything to the right. */ if (!stat) { error = xfs_btree_increment(cur, 0, &stat); if (error) goto out; } while (stat) { /* Find the record. */ error = xfs_btree_get_rec(cur, &recp, &stat); if (error || !stat) break; /* Skip if high_key(rec) < low_key. */ if (firstrec) { cur->bc_ops->init_high_key_from_rec(&rec_key, recp); firstrec = false; diff = cur->bc_ops->diff_two_keys(cur, low_key, &rec_key); if (diff > 0) goto advloop; } /* Stop if high_key < low_key(rec). */ cur->bc_ops->init_key_from_rec(&rec_key, recp); diff = cur->bc_ops->diff_two_keys(cur, &rec_key, high_key); if (diff > 0) break; /* Callback */ error = fn(cur, recp, priv); if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) break; advloop: /* Move on to the next record. */ error = xfs_btree_increment(cur, 0, &stat); if (error) break; } out: return error; } /* * Query an overlapped interval btree for all records overlapping a given * interval. This function roughly follows the algorithm given in * "Interval Trees" of _Introduction to Algorithms_, which is section * 14.3 in the 2nd and 3rd editions. * * First, generate keys for the low and high records passed in. * * For any leaf node, generate the high and low keys for the record. * If the record keys overlap with the query low/high keys, pass the * record to the function iterator. * * For any internal node, compare the low and high keys of each * pointer against the query low/high keys. If there's an overlap, * follow the pointer. * * As an optimization, we stop scanning a block when we find a low key * that is greater than the query's high key. */ STATIC int xfs_btree_overlapped_query_range( struct xfs_btree_cur *cur, union xfs_btree_key *low_key, union xfs_btree_key *high_key, xfs_btree_query_range_fn fn, void *priv) { union xfs_btree_ptr ptr; union xfs_btree_ptr *pp; union xfs_btree_key rec_key; union xfs_btree_key rec_hkey; union xfs_btree_key *lkp; union xfs_btree_key *hkp; union xfs_btree_rec *recp; struct xfs_btree_block *block; __int64_t ldiff; __int64_t hdiff; int level; struct xfs_buf *bp; int i; int error; /* Load the root of the btree. */ level = cur->bc_nlevels - 1; cur->bc_ops->init_ptr_from_cur(cur, &ptr); error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); if (error) return error; xfs_btree_get_block(cur, level, &bp); trace_xfs_btree_overlapped_query_range(cur, level, bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) goto out; #endif cur->bc_ptrs[level] = 1; while (level < cur->bc_nlevels) { block = xfs_btree_get_block(cur, level, &bp); /* End of node, pop back towards the root. */ if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { pop_up: if (level < cur->bc_nlevels - 1) cur->bc_ptrs[level + 1]++; level++; continue; } if (level == 0) { /* Handle a leaf node. */ recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); cur->bc_ops->init_high_key_from_rec(&rec_hkey, recp); ldiff = cur->bc_ops->diff_two_keys(cur, &rec_hkey, low_key); cur->bc_ops->init_key_from_rec(&rec_key, recp); hdiff = cur->bc_ops->diff_two_keys(cur, high_key, &rec_key); /* * If (record's high key >= query's low key) and * (query's high key >= record's low key), then * this record overlaps the query range; callback. */ if (ldiff >= 0 && hdiff >= 0) { error = fn(cur, recp, priv); if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) break; } else if (hdiff < 0) { /* Record is larger than high key; pop. */ goto pop_up; } cur->bc_ptrs[level]++; continue; } /* Handle an internal node. */ lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); ldiff = cur->bc_ops->diff_two_keys(cur, hkp, low_key); hdiff = cur->bc_ops->diff_two_keys(cur, high_key, lkp); /* * If (pointer's high key >= query's low key) and * (query's high key >= pointer's low key), then * this record overlaps the query range; follow pointer. */ if (ldiff >= 0 && hdiff >= 0) { level--; error = xfs_btree_lookup_get_block(cur, level, pp, &block); if (error) goto out; xfs_btree_get_block(cur, level, &bp); trace_xfs_btree_overlapped_query_range(cur, level, bp); #ifdef DEBUG error = xfs_btree_check_block(cur, block, level, bp); if (error) goto out; #endif cur->bc_ptrs[level] = 1; continue; } else if (hdiff < 0) { /* The low key is larger than the upper range; pop. */ goto pop_up; } cur->bc_ptrs[level]++; } out: /* * If we don't end this function with the cursor pointing at a record * block, a subsequent non-error cursor deletion will not release * node-level buffers, causing a buffer leak. This is quite possible * with a zero-results range query, so release the buffers if we * failed to return any results. */ if (cur->bc_bufs[0] == NULL) { for (i = 0; i < cur->bc_nlevels; i++) { if (cur->bc_bufs[i]) { xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); cur->bc_bufs[i] = NULL; cur->bc_ptrs[i] = 0; cur->bc_ra[i] = 0; } } } return error; } /* * Query a btree for all records overlapping a given interval of keys. The * supplied function will be called with each record found; return one of the * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a * negative error code. */ int xfs_btree_query_range( struct xfs_btree_cur *cur, union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, xfs_btree_query_range_fn fn, void *priv) { union xfs_btree_rec rec; union xfs_btree_key low_key; union xfs_btree_key high_key; /* Find the keys of both ends of the interval. */ cur->bc_rec = *high_rec; cur->bc_ops->init_rec_from_cur(cur, &rec); cur->bc_ops->init_key_from_rec(&high_key, &rec); cur->bc_rec = *low_rec; cur->bc_ops->init_rec_from_cur(cur, &rec); cur->bc_ops->init_key_from_rec(&low_key, &rec); /* Enforce low key < high key. */ if (cur->bc_ops->diff_two_keys(cur, &low_key, &high_key) > 0) return -EINVAL; if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING)) return xfs_btree_simple_query_range(cur, &low_key, &high_key, fn, priv); return xfs_btree_overlapped_query_range(cur, &low_key, &high_key, fn, priv); } /* * Calculate the number of blocks needed to store a given number of records * in a short-format (per-AG metadata) btree. */ xfs_extlen_t xfs_btree_calc_size( struct xfs_mount *mp, uint *limits, unsigned long long len) { int level; int maxrecs; xfs_extlen_t rval; maxrecs = limits[0]; for (level = 0, rval = 0; len > 1; level++) { len += maxrecs - 1; do_div(len, maxrecs); maxrecs = limits[1]; rval += len; } return rval; } static int xfs_btree_count_blocks_helper( struct xfs_btree_cur *cur, int level, void *data) { xfs_extlen_t *blocks = data; (*blocks)++; return 0; } /* Count the blocks in a btree and return the result in *blocks. */ int xfs_btree_count_blocks( struct xfs_btree_cur *cur, xfs_extlen_t *blocks) { *blocks = 0; return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper, blocks); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_btree.h0000644000000000000000000004200613063067171016115 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_BTREE_H__ #define __XFS_BTREE_H__ struct xfs_buf; struct xfs_defer_ops; struct xfs_inode; struct xfs_mount; struct xfs_trans; extern kmem_zone_t *xfs_btree_cur_zone; /* * Generic key, ptr and record wrapper structures. * * These are disk format structures, and are converted where necessary * by the btree specific code that needs to interpret them. */ union xfs_btree_ptr { __be32 s; /* short form ptr */ __be64 l; /* long form ptr */ }; /* * The in-core btree key. Overlapping btrees actually store two keys * per pointer, so we reserve enough memory to hold both. The __*bigkey * items should never be accessed directly. */ union xfs_btree_key { struct xfs_bmbt_key bmbt; xfs_bmdr_key_t bmbr; /* bmbt root block */ xfs_alloc_key_t alloc; struct xfs_inobt_key inobt; struct xfs_rmap_key rmap; struct xfs_rmap_key __rmap_bigkey[2]; struct xfs_refcount_key refc; }; union xfs_btree_rec { struct xfs_bmbt_rec bmbt; xfs_bmdr_rec_t bmbr; /* bmbt root block */ struct xfs_alloc_rec alloc; struct xfs_inobt_rec inobt; struct xfs_rmap_rec rmap; struct xfs_refcount_rec refc; }; /* * This nonsense is to make -wlint happy. */ #define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi) #define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi) #define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi) #define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi) #define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) #define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi) #define XFS_BTNUM_REFC ((xfs_btnum_t)XFS_BTNUM_REFCi) /* * For logging record fields. */ #define XFS_BB_MAGIC (1 << 0) #define XFS_BB_LEVEL (1 << 1) #define XFS_BB_NUMRECS (1 << 2) #define XFS_BB_LEFTSIB (1 << 3) #define XFS_BB_RIGHTSIB (1 << 4) #define XFS_BB_BLKNO (1 << 5) #define XFS_BB_LSN (1 << 6) #define XFS_BB_UUID (1 << 7) #define XFS_BB_OWNER (1 << 8) #define XFS_BB_NUM_BITS 5 #define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1) #define XFS_BB_NUM_BITS_CRC 9 #define XFS_BB_ALL_BITS_CRC ((1 << XFS_BB_NUM_BITS_CRC) - 1) /* * Generic stats interface */ #define __XFS_BTREE_STATS_INC(mp, type, stat) \ XFS_STATS_INC(mp, xs_ ## type ## _2_ ## stat) #define XFS_BTREE_STATS_INC(cur, stat) \ do { \ struct xfs_mount *__mp = cur->bc_mp; \ switch (cur->bc_btnum) { \ case XFS_BTNUM_BNO: __XFS_BTREE_STATS_INC(__mp, abtb, stat); break; \ case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(__mp, abtc, stat); break; \ case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ case XFS_BTNUM_REFC: __XFS_BTREE_STATS_INC(__mp, refcbt, stat); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) #define __XFS_BTREE_STATS_ADD(mp, type, stat, val) \ XFS_STATS_ADD(mp, xs_ ## type ## _2_ ## stat, val) #define XFS_BTREE_STATS_ADD(cur, stat, val) \ do { \ struct xfs_mount *__mp = cur->bc_mp; \ switch (cur->bc_btnum) { \ case XFS_BTNUM_BNO: \ __XFS_BTREE_STATS_ADD(__mp, abtb, stat, val); break; \ case XFS_BTNUM_CNT: \ __XFS_BTREE_STATS_ADD(__mp, abtc, stat, val); break; \ case XFS_BTNUM_BMAP: \ __XFS_BTREE_STATS_ADD(__mp, bmbt, stat, val); break; \ case XFS_BTNUM_INO: \ __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ case XFS_BTNUM_FINO: \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ case XFS_BTNUM_RMAP: \ __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ case XFS_BTNUM_REFC: \ __XFS_BTREE_STATS_ADD(__mp, refcbt, stat, val); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) #define XFS_BTREE_MAXLEVELS 9 /* max of all btrees */ struct xfs_btree_ops { /* size of the key and record structures */ size_t key_len; size_t rec_len; /* cursor operations */ struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); void (*update_cursor)(struct xfs_btree_cur *src, struct xfs_btree_cur *dst); /* update btree root pointer */ void (*set_root)(struct xfs_btree_cur *cur, union xfs_btree_ptr *nptr, int level_change); /* block allocation / freeing */ int (*alloc_block)(struct xfs_btree_cur *cur, union xfs_btree_ptr *start_bno, union xfs_btree_ptr *new_bno, int *stat); int (*free_block)(struct xfs_btree_cur *cur, struct xfs_buf *bp); /* update last record information */ void (*update_lastrec)(struct xfs_btree_cur *cur, struct xfs_btree_block *block, union xfs_btree_rec *rec, int ptr, int reason); /* records in block/level */ int (*get_minrecs)(struct xfs_btree_cur *cur, int level); int (*get_maxrecs)(struct xfs_btree_cur *cur, int level); /* records on disk. Matter for the root in inode case. */ int (*get_dmaxrecs)(struct xfs_btree_cur *cur, int level); /* init values of btree structures */ void (*init_key_from_rec)(union xfs_btree_key *key, union xfs_btree_rec *rec); void (*init_rec_from_cur)(struct xfs_btree_cur *cur, union xfs_btree_rec *rec); void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr); void (*init_high_key_from_rec)(union xfs_btree_key *key, union xfs_btree_rec *rec); /* difference between key value and cursor value */ __int64_t (*key_diff)(struct xfs_btree_cur *cur, union xfs_btree_key *key); /* * Difference between key2 and key1 -- positive if key1 > key2, * negative if key1 < key2, and zero if equal. */ __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur, union xfs_btree_key *key1, union xfs_btree_key *key2); const struct xfs_buf_ops *buf_ops; #if defined(DEBUG) || defined(XFS_WARN) /* check that k1 is lower than k2 */ int (*keys_inorder)(struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2); /* check that r1 is lower than r2 */ int (*recs_inorder)(struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2); #endif }; /* * Reasons for the update_lastrec method to be called. */ #define LASTREC_UPDATE 0 #define LASTREC_INSREC 1 #define LASTREC_DELREC 2 union xfs_btree_irec { struct xfs_alloc_rec_incore a; struct xfs_bmbt_irec b; struct xfs_inobt_rec_incore i; struct xfs_rmap_irec r; struct xfs_refcount_irec rc; }; /* Per-AG btree private information. */ union xfs_btree_cur_private { struct { unsigned long nr_ops; /* # record updates */ int shape_changes; /* # of extent splits */ } refc; }; /* * Btree cursor structure. * This collects all information needed by the btree code in one place. */ typedef struct xfs_btree_cur { struct xfs_trans *bc_tp; /* transaction we're in, if any */ struct xfs_mount *bc_mp; /* file system mount struct */ const struct xfs_btree_ops *bc_ops; uint bc_flags; /* btree features - below */ union xfs_btree_irec bc_rec; /* current insert/search record value */ struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ #define XFS_BTCUR_LEFTRA 1 /* left sibling has been read-ahead */ #define XFS_BTCUR_RIGHTRA 2 /* right sibling has been read-ahead */ __uint8_t bc_nlevels; /* number of levels in the tree */ __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ xfs_btnum_t bc_btnum; /* identifies which btree type */ union { struct { /* needed for BNO, CNT, INO */ struct xfs_buf *agbp; /* agf/agi buffer pointer */ struct xfs_defer_ops *dfops; /* deferred updates */ xfs_agnumber_t agno; /* ag number */ union xfs_btree_cur_private priv; } a; struct { /* needed for BMAP */ struct xfs_inode *ip; /* pointer to our inode */ struct xfs_defer_ops *dfops; /* deferred updates */ xfs_fsblock_t firstblock; /* 1st blk allocated */ int allocated; /* count of alloced */ short forksize; /* fork's inode space */ char whichfork; /* data or attr fork */ char flags; /* flags */ #define XFS_BTCUR_BPRV_WASDEL 1 /* was delayed */ } b; } bc_private; /* per-btree type data */ } xfs_btree_cur_t; /* cursor flags */ #define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */ #define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */ #define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */ #define XFS_BTREE_CRC_BLOCKS (1<<3) /* uses extended btree blocks */ #define XFS_BTREE_OVERLAPPING (1<<4) /* overlapping intervals */ #define XFS_BTREE_NOERROR 0 #define XFS_BTREE_ERROR 1 /* * Convert from buffer to btree block header. */ #define XFS_BUF_TO_BLOCK(bp) ((struct xfs_btree_block *)((bp)->b_addr)) /* * Check that block header is ok. */ int xfs_btree_check_block( struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_btree_block *block, /* generic btree block pointer */ int level, /* level of the btree block */ struct xfs_buf *bp); /* buffer containing block, if any */ /* * Check that (long) pointer is ok. */ int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_lptr( struct xfs_btree_cur *cur, /* btree cursor */ xfs_fsblock_t ptr, /* btree block disk address */ int level); /* btree block level */ /* * Delete the btree cursor. */ void xfs_btree_del_cursor( xfs_btree_cur_t *cur, /* btree cursor */ int error); /* del because of error */ /* * Duplicate the btree cursor. * Allocate a new one, copy the record, re-get the buffers. */ int /* error */ xfs_btree_dup_cursor( xfs_btree_cur_t *cur, /* input cursor */ xfs_btree_cur_t **ncur);/* output cursor */ /* * Get a buffer for the block, return it with no data read. * Long-form addressing. */ struct xfs_buf * /* buffer for fsbno */ xfs_btree_get_bufl( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t fsbno, /* file system block number */ uint lock); /* lock flags for get_buf */ /* * Get a buffer for the block, return it with no data read. * Short-form addressing. */ struct xfs_buf * /* buffer for agno/agbno */ xfs_btree_get_bufs( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t agbno, /* allocation group block number */ uint lock); /* lock flags for get_buf */ /* * Check for the cursor referring to the last block at the given level. */ int /* 1=is last block, 0=not last block */ xfs_btree_islastblock( xfs_btree_cur_t *cur, /* btree cursor */ int level); /* level to check */ /* * Compute first and last byte offsets for the fields given. * Interprets the offsets table, which contains struct field offsets. */ void xfs_btree_offsets( __int64_t fields, /* bitmask of fields */ const short *offsets,/* table of field offsets */ int nbits, /* number of bits to inspect */ int *first, /* output: first byte offset */ int *last); /* output: last byte offset */ /* * Get a buffer for the block, return it read in. * Long-form addressing. */ int /* error */ xfs_btree_read_bufl( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t fsbno, /* file system block number */ uint lock, /* lock flags for read_buf */ struct xfs_buf **bpp, /* buffer for fsbno */ int refval, /* ref count value for buffer */ const struct xfs_buf_ops *ops); /* * Read-ahead the block, don't wait for it, don't return a buffer. * Long-form addressing. */ void /* error */ xfs_btree_reada_bufl( struct xfs_mount *mp, /* file system mount point */ xfs_fsblock_t fsbno, /* file system block number */ xfs_extlen_t count, /* count of filesystem blocks */ const struct xfs_buf_ops *ops); /* * Read-ahead the block, don't wait for it, don't return a buffer. * Short-form addressing. */ void /* error */ xfs_btree_reada_bufs( struct xfs_mount *mp, /* file system mount point */ xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t agbno, /* allocation group block number */ xfs_extlen_t count, /* count of filesystem blocks */ const struct xfs_buf_ops *ops); /* * Initialise a new btree block header */ void xfs_btree_init_block( struct xfs_mount *mp, struct xfs_buf *bp, __u32 magic, __u16 level, __u16 numrecs, __u64 owner, unsigned int flags); void xfs_btree_init_block_int( struct xfs_mount *mp, struct xfs_btree_block *buf, xfs_daddr_t blkno, __u32 magic, __u16 level, __u16 numrecs, __u64 owner, unsigned int flags); /* * Common btree core entry points. */ int xfs_btree_increment(struct xfs_btree_cur *, int, int *); int xfs_btree_decrement(struct xfs_btree_cur *, int, int *); int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *); int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *); int xfs_btree_insert(struct xfs_btree_cur *, int *); int xfs_btree_delete(struct xfs_btree_cur *, int *); int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *); int xfs_btree_change_owner(struct xfs_btree_cur *cur, __uint64_t new_owner, struct list_head *buffer_list); /* * btree block CRC helpers */ void xfs_btree_lblock_calc_crc(struct xfs_buf *); bool xfs_btree_lblock_verify_crc(struct xfs_buf *); void xfs_btree_sblock_calc_crc(struct xfs_buf *); bool xfs_btree_sblock_verify_crc(struct xfs_buf *); /* * Internal btree helpers also used by xfs_bmap.c. */ void xfs_btree_log_block(struct xfs_btree_cur *, struct xfs_buf *, int); void xfs_btree_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int, int); /* * Helpers. */ static inline int xfs_btree_get_numrecs(struct xfs_btree_block *block) { return be16_to_cpu(block->bb_numrecs); } static inline void xfs_btree_set_numrecs(struct xfs_btree_block *block, __uint16_t numrecs) { block->bb_numrecs = cpu_to_be16(numrecs); } static inline int xfs_btree_get_level(struct xfs_btree_block *block) { return be16_to_cpu(block->bb_level); } /* * Min and max functions for extlen, agblock, fileoff, and filblks types. */ #define XFS_EXTLEN_MIN(a,b) min_t(xfs_extlen_t, (a), (b)) #define XFS_EXTLEN_MAX(a,b) max_t(xfs_extlen_t, (a), (b)) #define XFS_AGBLOCK_MIN(a,b) min_t(xfs_agblock_t, (a), (b)) #define XFS_AGBLOCK_MAX(a,b) max_t(xfs_agblock_t, (a), (b)) #define XFS_FILEOFF_MIN(a,b) min_t(xfs_fileoff_t, (a), (b)) #define XFS_FILEOFF_MAX(a,b) max_t(xfs_fileoff_t, (a), (b)) #define XFS_FILBLKS_MIN(a,b) min_t(xfs_filblks_t, (a), (b)) #define XFS_FILBLKS_MAX(a,b) max_t(xfs_filblks_t, (a), (b)) #define XFS_FSB_SANITY_CHECK(mp,fsb) \ (XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \ XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks) /* * Trace hooks. Currently not implemented as they need to be ported * over to the generic tracing functionality, which is some effort. * * i,j = integer (32 bit) * b = btree block buffer (xfs_buf_t) * p = btree ptr * r = btree record * k = btree key */ #define XFS_BTREE_TRACE_ARGBI(c, b, i) #define XFS_BTREE_TRACE_ARGBII(c, b, i, j) #define XFS_BTREE_TRACE_ARGI(c, i) #define XFS_BTREE_TRACE_ARGIPK(c, i, p, s) #define XFS_BTREE_TRACE_ARGIPR(c, i, p, r) #define XFS_BTREE_TRACE_ARGIK(c, i, k) #define XFS_BTREE_TRACE_ARGR(c, r) #define XFS_BTREE_TRACE_CURSOR(c, t) bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp); bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, unsigned long len); xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, unsigned long long len); /* return codes */ #define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */ #define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */ typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur, union xfs_btree_rec *rec, void *priv); int xfs_btree_query_range(struct xfs_btree_cur *cur, union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, xfs_btree_query_range_fn fn, void *priv); typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level, void *data); int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, xfs_btree_visit_blocks_fn fn, void *data); int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks); #endif /* __XFS_BTREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_cksum.h0000644000000000000000000000317013063067170016134 0ustar #ifndef _XFS_CKSUM_H #define _XFS_CKSUM_H 1 #define XFS_CRC_SEED (~(__uint32_t)0) /* * Calculate the intermediate checksum for a buffer that has the CRC field * inside it. The offset of the 32bit crc fields is passed as the * cksum_offset parameter. */ static inline __uint32_t xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset) { __uint32_t zero = 0; __uint32_t crc; /* Calculate CRC up to the checksum. */ crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset); /* Skip checksum field */ crc = crc32c(crc, &zero, sizeof(__u32)); /* Calculate the rest of the CRC. */ return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)], length - (cksum_offset + sizeof(__be32))); } /* * Convert the intermediate checksum to the final ondisk format. * * The CRC32c calculation uses LE format even on BE machines, but returns the * result in host endian format. Hence we need to byte swap it back to LE format * so that it is consistent on disk. */ static inline __le32 xfs_end_cksum(__uint32_t crc) { return ~cpu_to_le32(crc); } /* * Helper to generate the checksum for a buffer. */ static inline void xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset) { __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset); *(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc); } /* * Helper to verify the checksum for a buffer. */ static inline int xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset) { __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset); return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc); } #endif /* _XFS_CKSUM_H */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_da_btree.c0000644000000000000000000021402413063067171016555 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_attr_leaf.h" #include "xfs_trace.h" #include "xfs_cksum.h" /* * xfs_da_btree.c * * Routines to implement directories as Btrees of hashed names. */ /*======================================================================== * Function prototypes for the kernel. *========================================================================*/ /* * Routines used for growing the Btree. */ STATIC int xfs_da3_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *existing_root, xfs_da_state_blk_t *new_child); STATIC int xfs_da3_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *existing_blk, xfs_da_state_blk_t *split_blk, xfs_da_state_blk_t *blk_to_add, int treelevel, int *result); STATIC void xfs_da3_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *node_blk_1, xfs_da_state_blk_t *node_blk_2); STATIC void xfs_da3_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *old_node_blk, xfs_da_state_blk_t *new_node_blk); /* * Routines used for shrinking the Btree. */ STATIC int xfs_da3_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk); STATIC int xfs_da3_node_toosmall(xfs_da_state_t *state, int *retval); STATIC void xfs_da3_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk); STATIC void xfs_da3_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *src_node_blk, xfs_da_state_blk_t *dst_node_blk); /* * Utility routines. */ STATIC int xfs_da3_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, xfs_da_state_blk_t *save_blk); kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */ /* * Allocate a dir-state structure. * We don't put them on the stack since they're large. */ xfs_da_state_t * xfs_da_state_alloc(void) { return kmem_zone_zalloc(xfs_da_state_zone, KM_NOFS); } /* * Kill the altpath contents of a da-state structure. */ STATIC void xfs_da_state_kill_altpath(xfs_da_state_t *state) { int i; for (i = 0; i < state->altpath.active; i++) state->altpath.blk[i].bp = NULL; state->altpath.active = 0; } /* * Free a da-state structure. */ void xfs_da_state_free(xfs_da_state_t *state) { xfs_da_state_kill_altpath(state); #ifdef DEBUG memset((char *)state, 0, sizeof(*state)); #endif /* DEBUG */ kmem_zone_free(xfs_da_state_zone, state); } static bool xfs_da3_node_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_da_intnode *hdr = bp->b_addr; struct xfs_da3_icnode_hdr ichdr; const struct xfs_dir_ops *ops; ops = xfs_dir_get_ops(mp, NULL); ops->node_hdr_from_disk(&ichdr, hdr); if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_da3_node_hdr *hdr3 = bp->b_addr; if (ichdr.magic != XFS_DA3_NODE_MAGIC) return false; if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn))) return false; } else { if (ichdr.magic != XFS_DA_NODE_MAGIC) return false; } if (ichdr.level == 0) return false; if (ichdr.level > XFS_DA_NODE_MAXDEPTH) return false; if (ichdr.count == 0) return false; /* * we don't know if the node is for and attribute or directory tree, * so only fail if the count is outside both bounds */ if (ichdr.count > mp->m_dir_geo->node_ents && ichdr.count > mp->m_attr_geo->node_ents) return false; /* XXX: hash order check? */ return true; } static void xfs_da3_node_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_da3_node_hdr *hdr3 = bp->b_addr; if (!xfs_da3_node_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_DA3_NODE_CRC_OFF); } /* * leaf/node format detection on trees is sketchy, so a node read can be done on * leaf level blocks when detection identifies the tree as a node format tree * incorrectly. In this case, we need to swap the verifier to match the correct * format of the block being read. */ static void xfs_da3_node_read_verify( struct xfs_buf *bp) { struct xfs_da_blkinfo *info = bp->b_addr; switch (be16_to_cpu(info->magic)) { case XFS_DA3_NODE_MAGIC: if (!xfs_buf_verify_cksum(bp, XFS_DA3_NODE_CRC_OFF)) { xfs_buf_ioerror(bp, -EFSBADCRC); break; } /* fall through */ case XFS_DA_NODE_MAGIC: if (!xfs_da3_node_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); break; } return; case XFS_ATTR_LEAF_MAGIC: case XFS_ATTR3_LEAF_MAGIC: bp->b_ops = &xfs_attr3_leaf_buf_ops; bp->b_ops->verify_read(bp); return; case XFS_DIR2_LEAFN_MAGIC: case XFS_DIR3_LEAFN_MAGIC: bp->b_ops = &xfs_dir3_leafn_buf_ops; bp->b_ops->verify_read(bp); return; default: xfs_buf_ioerror(bp, -EFSCORRUPTED); break; } /* corrupt block */ xfs_verifier_error(bp); } const struct xfs_buf_ops xfs_da3_node_buf_ops = { .name = "xfs_da3_node", .verify_read = xfs_da3_node_read_verify, .verify_write = xfs_da3_node_write_verify, }; int xfs_da3_node_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp, int which_fork) { int err; err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, which_fork, &xfs_da3_node_buf_ops); if (!err && tp) { struct xfs_da_blkinfo *info = (*bpp)->b_addr; int type; switch (be16_to_cpu(info->magic)) { case XFS_DA_NODE_MAGIC: case XFS_DA3_NODE_MAGIC: type = XFS_BLFT_DA_NODE_BUF; break; case XFS_ATTR_LEAF_MAGIC: case XFS_ATTR3_LEAF_MAGIC: type = XFS_BLFT_ATTR_LEAF_BUF; break; case XFS_DIR2_LEAFN_MAGIC: case XFS_DIR3_LEAFN_MAGIC: type = XFS_BLFT_DIR_LEAFN_BUF; break; default: type = 0; ASSERT(0); break; } xfs_trans_buf_set_type(tp, *bpp, type); } return err; } /*======================================================================== * Routines used for growing the Btree. *========================================================================*/ /* * Create the initial contents of an intermediate node. */ int xfs_da3_node_create( struct xfs_da_args *args, xfs_dablk_t blkno, int level, struct xfs_buf **bpp, int whichfork) { struct xfs_da_intnode *node; struct xfs_trans *tp = args->trans; struct xfs_mount *mp = tp->t_mountp; struct xfs_da3_icnode_hdr ichdr = {0}; struct xfs_buf *bp; int error; struct xfs_inode *dp = args->dp; trace_xfs_da_node_create(args); ASSERT(level <= XFS_DA_NODE_MAXDEPTH); error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, whichfork); if (error) return error; bp->b_ops = &xfs_da3_node_buf_ops; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DA_NODE_BUF); node = bp->b_addr; if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_da3_node_hdr *hdr3 = bp->b_addr; memset(hdr3, 0, sizeof(struct xfs_da3_node_hdr)); ichdr.magic = XFS_DA3_NODE_MAGIC; hdr3->info.blkno = cpu_to_be64(bp->b_bn); hdr3->info.owner = cpu_to_be64(args->dp->i_ino); uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid); } else { ichdr.magic = XFS_DA_NODE_MAGIC; } ichdr.level = level; dp->d_ops->node_hdr_to_disk(node, &ichdr); xfs_trans_log_buf(tp, bp, XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); *bpp = bp; return 0; } /* * Split a leaf node, rebalance, then possibly split * intermediate nodes, rebalance, etc. */ int /* error */ xfs_da3_split( struct xfs_da_state *state) { struct xfs_da_state_blk *oldblk; struct xfs_da_state_blk *newblk; struct xfs_da_state_blk *addblk; struct xfs_da_intnode *node; int max; int action = 0; int error; int i; trace_xfs_da_split(state->args); /* * Walk back up the tree splitting/inserting/adjusting as necessary. * If we need to insert and there isn't room, split the node, then * decide which fragment to insert the new block from below into. * Note that we may split the root this way, but we need more fixup. */ max = state->path.active - 1; ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH)); ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC || state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC); addblk = &state->path.blk[max]; /* initial dummy value */ for (i = max; (i >= 0) && addblk; state->path.active--, i--) { oldblk = &state->path.blk[i]; newblk = &state->altpath.blk[i]; /* * If a leaf node then * Allocate a new leaf node, then rebalance across them. * else if an intermediate node then * We split on the last layer, must we split the node? */ switch (oldblk->magic) { case XFS_ATTR_LEAF_MAGIC: error = xfs_attr3_leaf_split(state, oldblk, newblk); if ((error != 0) && (error != -ENOSPC)) { return error; /* GROT: attr is inconsistent */ } if (!error) { addblk = newblk; break; } /* * Entry wouldn't fit, split the leaf again. The new * extrablk will be consumed by xfs_da3_node_split if * the node is split. */ state->extravalid = 1; if (state->inleaf) { state->extraafter = 0; /* before newblk */ trace_xfs_attr_leaf_split_before(state->args); error = xfs_attr3_leaf_split(state, oldblk, &state->extrablk); } else { state->extraafter = 1; /* after newblk */ trace_xfs_attr_leaf_split_after(state->args); error = xfs_attr3_leaf_split(state, newblk, &state->extrablk); } if (error) return error; /* GROT: attr inconsistent */ addblk = newblk; break; case XFS_DIR2_LEAFN_MAGIC: error = xfs_dir2_leafn_split(state, oldblk, newblk); if (error) return error; addblk = newblk; break; case XFS_DA_NODE_MAGIC: error = xfs_da3_node_split(state, oldblk, newblk, addblk, max - i, &action); addblk->bp = NULL; if (error) return error; /* GROT: dir is inconsistent */ /* * Record the newly split block for the next time thru? */ if (action) addblk = newblk; else addblk = NULL; break; } /* * Update the btree to show the new hashval for this child. */ xfs_da3_fixhashpath(state, &state->path); } if (!addblk) return 0; /* * xfs_da3_node_split() should have consumed any extra blocks we added * during a double leaf split in the attr fork. This is guaranteed as * we can't be here if the attr fork only has a single leaf block. */ ASSERT(state->extravalid == 0 || state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC); /* * Split the root node. */ ASSERT(state->path.active == 0); oldblk = &state->path.blk[0]; error = xfs_da3_root_split(state, oldblk, addblk); if (error) { addblk->bp = NULL; return error; /* GROT: dir is inconsistent */ } /* * Update pointers to the node which used to be block 0 and just got * bumped because of the addition of a new root node. Note that the * original block 0 could be at any position in the list of blocks in * the tree. * * Note: the magic numbers and sibling pointers are in the same physical * place for both v2 and v3 headers (by design). Hence it doesn't matter * which version of the xfs_da_intnode structure we use here as the * result will be the same using either structure. */ node = oldblk->bp->b_addr; if (node->hdr.info.forw) { ASSERT(be32_to_cpu(node->hdr.info.forw) == addblk->blkno); node = addblk->bp->b_addr; node->hdr.info.back = cpu_to_be32(oldblk->blkno); xfs_trans_log_buf(state->args->trans, addblk->bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); } node = oldblk->bp->b_addr; if (node->hdr.info.back) { ASSERT(be32_to_cpu(node->hdr.info.back) == addblk->blkno); node = addblk->bp->b_addr; node->hdr.info.forw = cpu_to_be32(oldblk->blkno); xfs_trans_log_buf(state->args->trans, addblk->bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); } addblk->bp = NULL; return 0; } /* * Split the root. We have to create a new root and point to the two * parts (the split old root) that we just created. Copy block zero to * the EOF, extending the inode in process. */ STATIC int /* error */ xfs_da3_root_split( struct xfs_da_state *state, struct xfs_da_state_blk *blk1, struct xfs_da_state_blk *blk2) { struct xfs_da_intnode *node; struct xfs_da_intnode *oldroot; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; struct xfs_da_args *args; struct xfs_buf *bp; struct xfs_inode *dp; struct xfs_trans *tp; struct xfs_dir2_leaf *leaf; xfs_dablk_t blkno; int level; int error; int size; trace_xfs_da_root_split(state->args); /* * Copy the existing (incorrect) block from the root node position * to a free space somewhere. */ args = state->args; error = xfs_da_grow_inode(args, &blkno); if (error) return error; dp = args->dp; tp = args->trans; error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, args->whichfork); if (error) return error; node = bp->b_addr; oldroot = blk1->bp->b_addr; if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { struct xfs_da3_icnode_hdr icnodehdr; dp->d_ops->node_hdr_from_disk(&icnodehdr, oldroot); btree = dp->d_ops->node_tree_p(oldroot); size = (int)((char *)&btree[icnodehdr.count] - (char *)oldroot); level = icnodehdr.level; /* * we are about to copy oldroot to bp, so set up the type * of bp while we know exactly what it will be. */ xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DA_NODE_BUF); } else { struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir2_leaf_entry *ents; leaf = (xfs_dir2_leaf_t *)oldroot; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); size = (int)((char *)&ents[leafhdr.count] - (char *)leaf); level = 0; /* * we are about to copy oldroot to bp, so set up the type * of bp while we know exactly what it will be. */ xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAFN_BUF); } /* * we can copy most of the information in the node from one block to * another, but for CRC enabled headers we have to make sure that the * block specific identifiers are kept intact. We update the buffer * directly for this. */ memcpy(node, oldroot, size); if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC) || oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { struct xfs_da3_intnode *node3 = (struct xfs_da3_intnode *)node; node3->hdr.info.blkno = cpu_to_be64(bp->b_bn); } xfs_trans_log_buf(tp, bp, 0, size - 1); bp->b_ops = blk1->bp->b_ops; xfs_trans_buf_copy_type(bp, blk1->bp); blk1->bp = bp; blk1->blkno = blkno; /* * Set up the new root node. */ error = xfs_da3_node_create(args, (args->whichfork == XFS_DATA_FORK) ? args->geo->leafblk : 0, level + 1, &bp, args->whichfork); if (error) return error; node = bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); btree[0].hashval = cpu_to_be32(blk1->hashval); btree[0].before = cpu_to_be32(blk1->blkno); btree[1].hashval = cpu_to_be32(blk2->hashval); btree[1].before = cpu_to_be32(blk2->blkno); nodehdr.count = 2; dp->d_ops->node_hdr_to_disk(node, &nodehdr); #ifdef DEBUG if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { ASSERT(blk1->blkno >= args->geo->leafblk && blk1->blkno < args->geo->freeblk); ASSERT(blk2->blkno >= args->geo->leafblk && blk2->blkno < args->geo->freeblk); } #endif /* Header is already logged by xfs_da_node_create */ xfs_trans_log_buf(tp, bp, XFS_DA_LOGRANGE(node, btree, sizeof(xfs_da_node_entry_t) * 2)); return 0; } /* * Split the node, rebalance, then add the new entry. */ STATIC int /* error */ xfs_da3_node_split( struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk, struct xfs_da_state_blk *addblk, int treelevel, int *result) { struct xfs_da_intnode *node; struct xfs_da3_icnode_hdr nodehdr; xfs_dablk_t blkno; int newcount; int error; int useextra; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_split(state->args); node = oldblk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); /* * With V2 dirs the extra block is data or freespace. */ useextra = state->extravalid && state->args->whichfork == XFS_ATTR_FORK; newcount = 1 + useextra; /* * Do we have to split the node? */ if (nodehdr.count + newcount > state->args->geo->node_ents) { /* * Allocate a new node, add to the doubly linked chain of * nodes, then move some of our excess entries into it. */ error = xfs_da_grow_inode(state->args, &blkno); if (error) return error; /* GROT: dir is inconsistent */ error = xfs_da3_node_create(state->args, blkno, treelevel, &newblk->bp, state->args->whichfork); if (error) return error; /* GROT: dir is inconsistent */ newblk->blkno = blkno; newblk->magic = XFS_DA_NODE_MAGIC; xfs_da3_node_rebalance(state, oldblk, newblk); error = xfs_da3_blk_link(state, oldblk, newblk); if (error) return error; *result = 1; } else { *result = 0; } /* * Insert the new entry(s) into the correct block * (updating last hashval in the process). * * xfs_da3_node_add() inserts BEFORE the given index, * and as a result of using node_lookup_int() we always * point to a valid entry (not after one), but a split * operation always results in a new block whose hashvals * FOLLOW the current block. * * If we had double-split op below us, then add the extra block too. */ node = oldblk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); if (oldblk->index <= nodehdr.count) { oldblk->index++; xfs_da3_node_add(state, oldblk, addblk); if (useextra) { if (state->extraafter) oldblk->index++; xfs_da3_node_add(state, oldblk, &state->extrablk); state->extravalid = 0; } } else { newblk->index++; xfs_da3_node_add(state, newblk, addblk); if (useextra) { if (state->extraafter) newblk->index++; xfs_da3_node_add(state, newblk, &state->extrablk); state->extravalid = 0; } } return 0; } /* * Balance the btree elements between two intermediate nodes, * usually one full and one empty. * * NOTE: if blk2 is empty, then it will get the upper half of blk1. */ STATIC void xfs_da3_node_rebalance( struct xfs_da_state *state, struct xfs_da_state_blk *blk1, struct xfs_da_state_blk *blk2) { struct xfs_da_intnode *node1; struct xfs_da_intnode *node2; struct xfs_da_intnode *tmpnode; struct xfs_da_node_entry *btree1; struct xfs_da_node_entry *btree2; struct xfs_da_node_entry *btree_s; struct xfs_da_node_entry *btree_d; struct xfs_da3_icnode_hdr nodehdr1; struct xfs_da3_icnode_hdr nodehdr2; struct xfs_trans *tp; int count; int tmp; int swap = 0; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_rebalance(state->args); node1 = blk1->bp->b_addr; node2 = blk2->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); /* * Figure out how many entries need to move, and in which direction. * Swap the nodes around if that makes it simpler. */ if (nodehdr1.count > 0 && nodehdr2.count > 0 && ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) || (be32_to_cpu(btree2[nodehdr2.count - 1].hashval) < be32_to_cpu(btree1[nodehdr1.count - 1].hashval)))) { tmpnode = node1; node1 = node2; node2 = tmpnode; dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); swap = 1; } count = (nodehdr1.count - nodehdr2.count) / 2; if (count == 0) return; tp = state->args->trans; /* * Two cases: high-to-low and low-to-high. */ if (count > 0) { /* * Move elements in node2 up to make a hole. */ tmp = nodehdr2.count; if (tmp > 0) { tmp *= (uint)sizeof(xfs_da_node_entry_t); btree_s = &btree2[0]; btree_d = &btree2[count]; memmove(btree_d, btree_s, tmp); } /* * Move the req'd B-tree elements from high in node1 to * low in node2. */ nodehdr2.count += count; tmp = count * (uint)sizeof(xfs_da_node_entry_t); btree_s = &btree1[nodehdr1.count - count]; btree_d = &btree2[0]; memcpy(btree_d, btree_s, tmp); nodehdr1.count -= count; } else { /* * Move the req'd B-tree elements from low in node2 to * high in node1. */ count = -count; tmp = count * (uint)sizeof(xfs_da_node_entry_t); btree_s = &btree2[0]; btree_d = &btree1[nodehdr1.count]; memcpy(btree_d, btree_s, tmp); nodehdr1.count += count; xfs_trans_log_buf(tp, blk1->bp, XFS_DA_LOGRANGE(node1, btree_d, tmp)); /* * Move elements in node2 down to fill the hole. */ tmp = nodehdr2.count - count; tmp *= (uint)sizeof(xfs_da_node_entry_t); btree_s = &btree2[count]; btree_d = &btree2[0]; memmove(btree_d, btree_s, tmp); nodehdr2.count -= count; } /* * Log header of node 1 and all current bits of node 2. */ dp->d_ops->node_hdr_to_disk(node1, &nodehdr1); xfs_trans_log_buf(tp, blk1->bp, XFS_DA_LOGRANGE(node1, &node1->hdr, dp->d_ops->node_hdr_size)); dp->d_ops->node_hdr_to_disk(node2, &nodehdr2); xfs_trans_log_buf(tp, blk2->bp, XFS_DA_LOGRANGE(node2, &node2->hdr, dp->d_ops->node_hdr_size + (sizeof(btree2[0]) * nodehdr2.count))); /* * Record the last hashval from each block for upward propagation. * (note: don't use the swapped node pointers) */ if (swap) { node1 = blk1->bp->b_addr; node2 = blk2->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); } blk1->hashval = be32_to_cpu(btree1[nodehdr1.count - 1].hashval); blk2->hashval = be32_to_cpu(btree2[nodehdr2.count - 1].hashval); /* * Adjust the expected index for insertion. */ if (blk1->index >= nodehdr1.count) { blk2->index = blk1->index - nodehdr1.count; blk1->index = nodehdr1.count + 1; /* make it invalid */ } } /* * Add a new entry to an intermediate node. */ STATIC void xfs_da3_node_add( struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk) { struct xfs_da_intnode *node; struct xfs_da3_icnode_hdr nodehdr; struct xfs_da_node_entry *btree; int tmp; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_add(state->args); node = oldblk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); ASSERT(newblk->blkno != 0); if (state->args->whichfork == XFS_DATA_FORK) ASSERT(newblk->blkno >= state->args->geo->leafblk && newblk->blkno < state->args->geo->freeblk); /* * We may need to make some room before we insert the new node. */ tmp = 0; if (oldblk->index < nodehdr.count) { tmp = (nodehdr.count - oldblk->index) * (uint)sizeof(*btree); memmove(&btree[oldblk->index + 1], &btree[oldblk->index], tmp); } btree[oldblk->index].hashval = cpu_to_be32(newblk->hashval); btree[oldblk->index].before = cpu_to_be32(newblk->blkno); xfs_trans_log_buf(state->args->trans, oldblk->bp, XFS_DA_LOGRANGE(node, &btree[oldblk->index], tmp + sizeof(*btree))); nodehdr.count += 1; dp->d_ops->node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, oldblk->bp, XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); /* * Copy the last hash value from the oldblk to propagate upwards. */ oldblk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); } /*======================================================================== * Routines used for shrinking the Btree. *========================================================================*/ /* * Deallocate an empty leaf node, remove it from its parent, * possibly deallocating that block, etc... */ int xfs_da3_join( struct xfs_da_state *state) { struct xfs_da_state_blk *drop_blk; struct xfs_da_state_blk *save_blk; int action = 0; int error; trace_xfs_da_join(state->args); drop_blk = &state->path.blk[ state->path.active-1 ]; save_blk = &state->altpath.blk[ state->path.active-1 ]; ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC); ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC || drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); /* * Walk back up the tree joining/deallocating as necessary. * When we stop dropping blocks, break out. */ for ( ; state->path.active >= 2; drop_blk--, save_blk--, state->path.active--) { /* * See if we can combine the block with a neighbor. * (action == 0) => no options, just leave * (action == 1) => coalesce, then unlink * (action == 2) => block empty, unlink it */ switch (drop_blk->magic) { case XFS_ATTR_LEAF_MAGIC: error = xfs_attr3_leaf_toosmall(state, &action); if (error) return error; if (action == 0) return 0; xfs_attr3_leaf_unbalance(state, drop_blk, save_blk); break; case XFS_DIR2_LEAFN_MAGIC: error = xfs_dir2_leafn_toosmall(state, &action); if (error) return error; if (action == 0) return 0; xfs_dir2_leafn_unbalance(state, drop_blk, save_blk); break; case XFS_DA_NODE_MAGIC: /* * Remove the offending node, fixup hashvals, * check for a toosmall neighbor. */ xfs_da3_node_remove(state, drop_blk); xfs_da3_fixhashpath(state, &state->path); error = xfs_da3_node_toosmall(state, &action); if (error) return error; if (action == 0) return 0; xfs_da3_node_unbalance(state, drop_blk, save_blk); break; } xfs_da3_fixhashpath(state, &state->altpath); error = xfs_da3_blk_unlink(state, drop_blk, save_blk); xfs_da_state_kill_altpath(state); if (error) return error; error = xfs_da_shrink_inode(state->args, drop_blk->blkno, drop_blk->bp); drop_blk->bp = NULL; if (error) return error; } /* * We joined all the way to the top. If it turns out that * we only have one entry in the root, make the child block * the new root. */ xfs_da3_node_remove(state, drop_blk); xfs_da3_fixhashpath(state, &state->path); error = xfs_da3_root_join(state, &state->path.blk[0]); return error; } #ifdef DEBUG static void xfs_da_blkinfo_onlychild_validate(struct xfs_da_blkinfo *blkinfo, __u16 level) { __be16 magic = blkinfo->magic; if (level == 1) { ASSERT(magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC) || magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC) || magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)); } else { ASSERT(magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)); } ASSERT(!blkinfo->forw); ASSERT(!blkinfo->back); } #else /* !DEBUG */ #define xfs_da_blkinfo_onlychild_validate(blkinfo, level) #endif /* !DEBUG */ /* * We have only one entry in the root. Copy the only remaining child of * the old root to block 0 as the new root node. */ STATIC int xfs_da3_root_join( struct xfs_da_state *state, struct xfs_da_state_blk *root_blk) { struct xfs_da_intnode *oldroot; struct xfs_da_args *args; xfs_dablk_t child; struct xfs_buf *bp; struct xfs_da3_icnode_hdr oldroothdr; struct xfs_da_node_entry *btree; int error; struct xfs_inode *dp = state->args->dp; trace_xfs_da_root_join(state->args); ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC); args = state->args; oldroot = root_blk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&oldroothdr, oldroot); ASSERT(oldroothdr.forw == 0); ASSERT(oldroothdr.back == 0); /* * If the root has more than one child, then don't do anything. */ if (oldroothdr.count > 1) return 0; /* * Read in the (only) child block, then copy those bytes into * the root block's buffer and free the original child block. */ btree = dp->d_ops->node_tree_p(oldroot); child = be32_to_cpu(btree[0].before); ASSERT(child != 0); error = xfs_da3_node_read(args->trans, dp, child, -1, &bp, args->whichfork); if (error) return error; xfs_da_blkinfo_onlychild_validate(bp->b_addr, oldroothdr.level); /* * This could be copying a leaf back into the root block in the case of * there only being a single leaf block left in the tree. Hence we have * to update the b_ops pointer as well to match the buffer type change * that could occur. For dir3 blocks we also need to update the block * number in the buffer header. */ memcpy(root_blk->bp->b_addr, bp->b_addr, args->geo->blksize); root_blk->bp->b_ops = bp->b_ops; xfs_trans_buf_copy_type(root_blk->bp, bp); if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) { struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr; da3->blkno = cpu_to_be64(root_blk->bp->b_bn); } xfs_trans_log_buf(args->trans, root_blk->bp, 0, args->geo->blksize - 1); error = xfs_da_shrink_inode(args, child, bp); return error; } /* * Check a node block and its neighbors to see if the block should be * collapsed into one or the other neighbor. Always keep the block * with the smaller block number. * If the current block is over 50% full, don't try to join it, return 0. * If the block is empty, fill in the state structure and return 2. * If it can be collapsed, fill in the state structure and return 1. * If nothing can be done, return 0. */ STATIC int xfs_da3_node_toosmall( struct xfs_da_state *state, int *action) { struct xfs_da_intnode *node; struct xfs_da_state_blk *blk; struct xfs_da_blkinfo *info; xfs_dablk_t blkno; struct xfs_buf *bp; struct xfs_da3_icnode_hdr nodehdr; int count; int forward; int error; int retval; int i; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_toosmall(state->args); /* * Check for the degenerate case of the block being over 50% full. * If so, it's not worth even looking to see if we might be able * to coalesce with a sibling. */ blk = &state->path.blk[ state->path.active-1 ]; info = blk->bp->b_addr; node = (xfs_da_intnode_t *)info; dp->d_ops->node_hdr_from_disk(&nodehdr, node); if (nodehdr.count > (state->args->geo->node_ents >> 1)) { *action = 0; /* blk over 50%, don't try to join */ return 0; /* blk over 50%, don't try to join */ } /* * Check for the degenerate case of the block being empty. * If the block is empty, we'll simply delete it, no need to * coalesce it with a sibling block. We choose (arbitrarily) * to merge with the forward block unless it is NULL. */ if (nodehdr.count == 0) { /* * Make altpath point to the block we want to keep and * path point to the block we want to drop (this one). */ forward = (info->forw != 0); memcpy(&state->altpath, &state->path, sizeof(state->path)); error = xfs_da3_path_shift(state, &state->altpath, forward, 0, &retval); if (error) return error; if (retval) { *action = 0; } else { *action = 2; } return 0; } /* * Examine each sibling block to see if we can coalesce with * at least 25% free space to spare. We need to figure out * whether to merge with the forward or the backward block. * We prefer coalescing with the lower numbered sibling so as * to shrink a directory over time. */ count = state->args->geo->node_ents; count -= state->args->geo->node_ents >> 2; count -= nodehdr.count; /* start with smaller blk num */ forward = nodehdr.forw < nodehdr.back; for (i = 0; i < 2; forward = !forward, i++) { struct xfs_da3_icnode_hdr thdr; if (forward) blkno = nodehdr.forw; else blkno = nodehdr.back; if (blkno == 0) continue; error = xfs_da3_node_read(state->args->trans, dp, blkno, -1, &bp, state->args->whichfork); if (error) return error; node = bp->b_addr; dp->d_ops->node_hdr_from_disk(&thdr, node); xfs_trans_brelse(state->args->trans, bp); if (count - thdr.count >= 0) break; /* fits with at least 25% to spare */ } if (i >= 2) { *action = 0; return 0; } /* * Make altpath point to the block we want to keep (the lower * numbered block) and path point to the block we want to drop. */ memcpy(&state->altpath, &state->path, sizeof(state->path)); if (blkno < blk->blkno) { error = xfs_da3_path_shift(state, &state->altpath, forward, 0, &retval); } else { error = xfs_da3_path_shift(state, &state->path, forward, 0, &retval); } if (error) return error; if (retval) { *action = 0; return 0; } *action = 1; return 0; } /* * Pick up the last hashvalue from an intermediate node. */ STATIC uint xfs_da3_node_lasthash( struct xfs_inode *dp, struct xfs_buf *bp, int *count) { struct xfs_da_intnode *node; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; node = bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); if (count) *count = nodehdr.count; if (!nodehdr.count) return 0; btree = dp->d_ops->node_tree_p(node); return be32_to_cpu(btree[nodehdr.count - 1].hashval); } /* * Walk back up the tree adjusting hash values as necessary, * when we stop making changes, return. */ void xfs_da3_fixhashpath( struct xfs_da_state *state, struct xfs_da_state_path *path) { struct xfs_da_state_blk *blk; struct xfs_da_intnode *node; struct xfs_da_node_entry *btree; xfs_dahash_t lasthash=0; int level; int count; struct xfs_inode *dp = state->args->dp; trace_xfs_da_fixhashpath(state->args); level = path->active-1; blk = &path->blk[ level ]; switch (blk->magic) { case XFS_ATTR_LEAF_MAGIC: lasthash = xfs_attr_leaf_lasthash(blk->bp, &count); if (count == 0) return; break; case XFS_DIR2_LEAFN_MAGIC: lasthash = xfs_dir2_leafn_lasthash(dp, blk->bp, &count); if (count == 0) return; break; case XFS_DA_NODE_MAGIC: lasthash = xfs_da3_node_lasthash(dp, blk->bp, &count); if (count == 0) return; break; } for (blk--, level--; level >= 0; blk--, level--) { struct xfs_da3_icnode_hdr nodehdr; node = blk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); if (be32_to_cpu(btree[blk->index].hashval) == lasthash) break; blk->hashval = lasthash; btree[blk->index].hashval = cpu_to_be32(lasthash); xfs_trans_log_buf(state->args->trans, blk->bp, XFS_DA_LOGRANGE(node, &btree[blk->index], sizeof(*btree))); lasthash = be32_to_cpu(btree[nodehdr.count - 1].hashval); } } /* * Remove an entry from an intermediate node. */ STATIC void xfs_da3_node_remove( struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk) { struct xfs_da_intnode *node; struct xfs_da3_icnode_hdr nodehdr; struct xfs_da_node_entry *btree; int index; int tmp; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_remove(state->args); node = drop_blk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); ASSERT(drop_blk->index < nodehdr.count); ASSERT(drop_blk->index >= 0); /* * Copy over the offending entry, or just zero it out. */ index = drop_blk->index; btree = dp->d_ops->node_tree_p(node); if (index < nodehdr.count - 1) { tmp = nodehdr.count - index - 1; tmp *= (uint)sizeof(xfs_da_node_entry_t); memmove(&btree[index], &btree[index + 1], tmp); xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &btree[index], tmp)); index = nodehdr.count - 1; } memset(&btree[index], 0, sizeof(xfs_da_node_entry_t)); xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index]))); nodehdr.count -= 1; dp->d_ops->node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); /* * Copy the last hash value from the block to propagate upwards. */ drop_blk->hashval = be32_to_cpu(btree[index - 1].hashval); } /* * Unbalance the elements between two intermediate nodes, * move all Btree elements from one node into another. */ STATIC void xfs_da3_node_unbalance( struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, struct xfs_da_state_blk *save_blk) { struct xfs_da_intnode *drop_node; struct xfs_da_intnode *save_node; struct xfs_da_node_entry *drop_btree; struct xfs_da_node_entry *save_btree; struct xfs_da3_icnode_hdr drop_hdr; struct xfs_da3_icnode_hdr save_hdr; struct xfs_trans *tp; int sindex; int tmp; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_unbalance(state->args); drop_node = drop_blk->bp->b_addr; save_node = save_blk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&drop_hdr, drop_node); dp->d_ops->node_hdr_from_disk(&save_hdr, save_node); drop_btree = dp->d_ops->node_tree_p(drop_node); save_btree = dp->d_ops->node_tree_p(save_node); tp = state->args->trans; /* * If the dying block has lower hashvals, then move all the * elements in the remaining block up to make a hole. */ if ((be32_to_cpu(drop_btree[0].hashval) < be32_to_cpu(save_btree[0].hashval)) || (be32_to_cpu(drop_btree[drop_hdr.count - 1].hashval) < be32_to_cpu(save_btree[save_hdr.count - 1].hashval))) { /* XXX: check this - is memmove dst correct? */ tmp = save_hdr.count * sizeof(xfs_da_node_entry_t); memmove(&save_btree[drop_hdr.count], &save_btree[0], tmp); sindex = 0; xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_btree[0], (save_hdr.count + drop_hdr.count) * sizeof(xfs_da_node_entry_t))); } else { sindex = save_hdr.count; xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_btree[sindex], drop_hdr.count * sizeof(xfs_da_node_entry_t))); } /* * Move all the B-tree elements from drop_blk to save_blk. */ tmp = drop_hdr.count * (uint)sizeof(xfs_da_node_entry_t); memcpy(&save_btree[sindex], &drop_btree[0], tmp); save_hdr.count += drop_hdr.count; dp->d_ops->node_hdr_to_disk(save_node, &save_hdr); xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_node->hdr, dp->d_ops->node_hdr_size)); /* * Save the last hashval in the remaining block for upward propagation. */ save_blk->hashval = be32_to_cpu(save_btree[save_hdr.count - 1].hashval); } /*======================================================================== * Routines used for finding things in the Btree. *========================================================================*/ /* * Walk down the Btree looking for a particular filename, filling * in the state structure as we go. * * We will set the state structure to point to each of the elements * in each of the nodes where either the hashval is or should be. * * We support duplicate hashval's so for each entry in the current * node that could contain the desired hashval, descend. This is a * pruned depth-first tree search. */ int /* error */ xfs_da3_node_lookup_int( struct xfs_da_state *state, int *result) { struct xfs_da_state_blk *blk; struct xfs_da_blkinfo *curr; struct xfs_da_intnode *node; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; struct xfs_da_args *args; xfs_dablk_t blkno; xfs_dahash_t hashval; xfs_dahash_t btreehashval; int probe; int span; int max; int error; int retval; struct xfs_inode *dp = state->args->dp; args = state->args; /* * Descend thru the B-tree searching each level for the right * node to use, until the right hashval is found. */ blkno = (args->whichfork == XFS_DATA_FORK)? args->geo->leafblk : 0; for (blk = &state->path.blk[0], state->path.active = 1; state->path.active <= XFS_DA_NODE_MAXDEPTH; blk++, state->path.active++) { /* * Read the next node down in the tree. */ blk->blkno = blkno; error = xfs_da3_node_read(args->trans, args->dp, blkno, -1, &blk->bp, args->whichfork); if (error) { blk->blkno = 0; state->path.active--; return error; } curr = blk->bp->b_addr; blk->magic = be16_to_cpu(curr->magic); if (blk->magic == XFS_ATTR_LEAF_MAGIC || blk->magic == XFS_ATTR3_LEAF_MAGIC) { blk->magic = XFS_ATTR_LEAF_MAGIC; blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); break; } if (blk->magic == XFS_DIR2_LEAFN_MAGIC || blk->magic == XFS_DIR3_LEAFN_MAGIC) { blk->magic = XFS_DIR2_LEAFN_MAGIC; blk->hashval = xfs_dir2_leafn_lasthash(args->dp, blk->bp, NULL); break; } blk->magic = XFS_DA_NODE_MAGIC; /* * Search an intermediate node for a match. */ node = blk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); max = nodehdr.count; blk->hashval = be32_to_cpu(btree[max - 1].hashval); /* * Binary search. (note: small blocks will skip loop) */ probe = span = max / 2; hashval = args->hashval; while (span > 4) { span /= 2; btreehashval = be32_to_cpu(btree[probe].hashval); if (btreehashval < hashval) probe += span; else if (btreehashval > hashval) probe -= span; else break; } ASSERT((probe >= 0) && (probe < max)); ASSERT((span <= 4) || (be32_to_cpu(btree[probe].hashval) == hashval)); /* * Since we may have duplicate hashval's, find the first * matching hashval in the node. */ while (probe > 0 && be32_to_cpu(btree[probe].hashval) >= hashval) { probe--; } while (probe < max && be32_to_cpu(btree[probe].hashval) < hashval) { probe++; } /* * Pick the right block to descend on. */ if (probe == max) { blk->index = max - 1; blkno = be32_to_cpu(btree[max - 1].before); } else { blk->index = probe; blkno = be32_to_cpu(btree[probe].before); } } /* * A leaf block that ends in the hashval that we are interested in * (final hashval == search hashval) means that the next block may * contain more entries with the same hashval, shift upward to the * next leaf and keep searching. */ for (;;) { if (blk->magic == XFS_DIR2_LEAFN_MAGIC) { retval = xfs_dir2_leafn_lookup_int(blk->bp, args, &blk->index, state); } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) { retval = xfs_attr3_leaf_lookup_int(blk->bp, args); blk->index = args->index; args->blkno = blk->blkno; } else { ASSERT(0); return -EFSCORRUPTED; } if (((retval == -ENOENT) || (retval == -ENOATTR)) && (blk->hashval == args->hashval)) { error = xfs_da3_path_shift(state, &state->path, 1, 1, &retval); if (error) return error; if (retval == 0) { continue; } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) { /* path_shift() gives ENOENT */ retval = -ENOATTR; } } break; } *result = retval; return 0; } /*======================================================================== * Utility routines. *========================================================================*/ /* * Compare two intermediate nodes for "order". */ STATIC int xfs_da3_node_order( struct xfs_inode *dp, struct xfs_buf *node1_bp, struct xfs_buf *node2_bp) { struct xfs_da_intnode *node1; struct xfs_da_intnode *node2; struct xfs_da_node_entry *btree1; struct xfs_da_node_entry *btree2; struct xfs_da3_icnode_hdr node1hdr; struct xfs_da3_icnode_hdr node2hdr; node1 = node1_bp->b_addr; node2 = node2_bp->b_addr; dp->d_ops->node_hdr_from_disk(&node1hdr, node1); dp->d_ops->node_hdr_from_disk(&node2hdr, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); if (node1hdr.count > 0 && node2hdr.count > 0 && ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) || (be32_to_cpu(btree2[node2hdr.count - 1].hashval) < be32_to_cpu(btree1[node1hdr.count - 1].hashval)))) { return 1; } return 0; } /* * Link a new block into a doubly linked list of blocks (of whatever type). */ int /* error */ xfs_da3_blk_link( struct xfs_da_state *state, struct xfs_da_state_blk *old_blk, struct xfs_da_state_blk *new_blk) { struct xfs_da_blkinfo *old_info; struct xfs_da_blkinfo *new_info; struct xfs_da_blkinfo *tmp_info; struct xfs_da_args *args; struct xfs_buf *bp; int before = 0; int error; struct xfs_inode *dp = state->args->dp; /* * Set up environment. */ args = state->args; ASSERT(args != NULL); old_info = old_blk->bp->b_addr; new_info = new_blk->bp->b_addr; ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || old_blk->magic == XFS_DIR2_LEAFN_MAGIC || old_blk->magic == XFS_ATTR_LEAF_MAGIC); switch (old_blk->magic) { case XFS_ATTR_LEAF_MAGIC: before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); break; case XFS_DIR2_LEAFN_MAGIC: before = xfs_dir2_leafn_order(dp, old_blk->bp, new_blk->bp); break; case XFS_DA_NODE_MAGIC: before = xfs_da3_node_order(dp, old_blk->bp, new_blk->bp); break; } /* * Link blocks in appropriate order. */ if (before) { /* * Link new block in before existing block. */ trace_xfs_da_link_before(args); new_info->forw = cpu_to_be32(old_blk->blkno); new_info->back = old_info->back; if (old_info->back) { error = xfs_da3_node_read(args->trans, dp, be32_to_cpu(old_info->back), -1, &bp, args->whichfork); if (error) return error; ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == old_info->magic); ASSERT(be32_to_cpu(tmp_info->forw) == old_blk->blkno); tmp_info->forw = cpu_to_be32(new_blk->blkno); xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); } old_info->back = cpu_to_be32(new_blk->blkno); } else { /* * Link new block in after existing block. */ trace_xfs_da_link_after(args); new_info->forw = old_info->forw; new_info->back = cpu_to_be32(old_blk->blkno); if (old_info->forw) { error = xfs_da3_node_read(args->trans, dp, be32_to_cpu(old_info->forw), -1, &bp, args->whichfork); if (error) return error; ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == old_info->magic); ASSERT(be32_to_cpu(tmp_info->back) == old_blk->blkno); tmp_info->back = cpu_to_be32(new_blk->blkno); xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); } old_info->forw = cpu_to_be32(new_blk->blkno); } xfs_trans_log_buf(args->trans, old_blk->bp, 0, sizeof(*tmp_info) - 1); xfs_trans_log_buf(args->trans, new_blk->bp, 0, sizeof(*tmp_info) - 1); return 0; } /* * Unlink a block from a doubly linked list of blocks. */ STATIC int /* error */ xfs_da3_blk_unlink( struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, struct xfs_da_state_blk *save_blk) { struct xfs_da_blkinfo *drop_info; struct xfs_da_blkinfo *save_info; struct xfs_da_blkinfo *tmp_info; struct xfs_da_args *args; struct xfs_buf *bp; int error; /* * Set up environment. */ args = state->args; ASSERT(args != NULL); save_info = save_blk->bp->b_addr; drop_info = drop_blk->bp->b_addr; ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || save_blk->magic == XFS_DIR2_LEAFN_MAGIC || save_blk->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(save_blk->magic == drop_blk->magic); ASSERT((be32_to_cpu(save_info->forw) == drop_blk->blkno) || (be32_to_cpu(save_info->back) == drop_blk->blkno)); ASSERT((be32_to_cpu(drop_info->forw) == save_blk->blkno) || (be32_to_cpu(drop_info->back) == save_blk->blkno)); /* * Unlink the leaf block from the doubly linked chain of leaves. */ if (be32_to_cpu(save_info->back) == drop_blk->blkno) { trace_xfs_da_unlink_back(args); save_info->back = drop_info->back; if (drop_info->back) { error = xfs_da3_node_read(args->trans, args->dp, be32_to_cpu(drop_info->back), -1, &bp, args->whichfork); if (error) return error; ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == save_info->magic); ASSERT(be32_to_cpu(tmp_info->forw) == drop_blk->blkno); tmp_info->forw = cpu_to_be32(save_blk->blkno); xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info) - 1); } } else { trace_xfs_da_unlink_forward(args); save_info->forw = drop_info->forw; if (drop_info->forw) { error = xfs_da3_node_read(args->trans, args->dp, be32_to_cpu(drop_info->forw), -1, &bp, args->whichfork); if (error) return error; ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == save_info->magic); ASSERT(be32_to_cpu(tmp_info->back) == drop_blk->blkno); tmp_info->back = cpu_to_be32(save_blk->blkno); xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info) - 1); } } xfs_trans_log_buf(args->trans, save_blk->bp, 0, sizeof(*save_info) - 1); return 0; } /* * Move a path "forward" or "!forward" one block at the current level. * * This routine will adjust a "path" to point to the next block * "forward" (higher hashvalues) or "!forward" (lower hashvals) in the * Btree, including updating pointers to the intermediate nodes between * the new bottom and the root. */ int /* error */ xfs_da3_path_shift( struct xfs_da_state *state, struct xfs_da_state_path *path, int forward, int release, int *result) { struct xfs_da_state_blk *blk; struct xfs_da_blkinfo *info; struct xfs_da_intnode *node; struct xfs_da_args *args; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; struct xfs_buf *bp; xfs_dablk_t blkno = 0; int level; int error; struct xfs_inode *dp = state->args->dp; trace_xfs_da_path_shift(state->args); /* * Roll up the Btree looking for the first block where our * current index is not at the edge of the block. Note that * we skip the bottom layer because we want the sibling block. */ args = state->args; ASSERT(args != NULL); ASSERT(path != NULL); ASSERT((path->active > 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); level = (path->active-1) - 1; /* skip bottom layer in path */ for (blk = &path->blk[level]; level >= 0; blk--, level--) { node = blk->bp->b_addr; dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); if (forward && (blk->index < nodehdr.count - 1)) { blk->index++; blkno = be32_to_cpu(btree[blk->index].before); break; } else if (!forward && (blk->index > 0)) { blk->index--; blkno = be32_to_cpu(btree[blk->index].before); break; } } if (level < 0) { *result = -ENOENT; /* we're out of our tree */ ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); return 0; } /* * Roll down the edge of the subtree until we reach the * same depth we were at originally. */ for (blk++, level++; level < path->active; blk++, level++) { /* * Read the next child block into a local buffer. */ error = xfs_da3_node_read(args->trans, dp, blkno, -1, &bp, args->whichfork); if (error) return error; /* * Release the old block (if it's dirty, the trans doesn't * actually let go) and swap the local buffer into the path * structure. This ensures failure of the above read doesn't set * a NULL buffer in an active slot in the path. */ if (release) xfs_trans_brelse(args->trans, blk->bp); blk->blkno = blkno; blk->bp = bp; info = blk->bp->b_addr; ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || info->magic == cpu_to_be16(XFS_DA3_NODE_MAGIC) || info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || info->magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC) || info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC) || info->magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)); /* * Note: we flatten the magic number to a single type so we * don't have to compare against crc/non-crc types elsewhere. */ switch (be16_to_cpu(info->magic)) { case XFS_DA_NODE_MAGIC: case XFS_DA3_NODE_MAGIC: blk->magic = XFS_DA_NODE_MAGIC; node = (xfs_da_intnode_t *)info; dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); if (forward) blk->index = 0; else blk->index = nodehdr.count - 1; blkno = be32_to_cpu(btree[blk->index].before); break; case XFS_ATTR_LEAF_MAGIC: case XFS_ATTR3_LEAF_MAGIC: blk->magic = XFS_ATTR_LEAF_MAGIC; ASSERT(level == path->active-1); blk->index = 0; blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); break; case XFS_DIR2_LEAFN_MAGIC: case XFS_DIR3_LEAFN_MAGIC: blk->magic = XFS_DIR2_LEAFN_MAGIC; ASSERT(level == path->active-1); blk->index = 0; blk->hashval = xfs_dir2_leafn_lasthash(args->dp, blk->bp, NULL); break; default: ASSERT(0); break; } } *result = 0; return 0; } /*======================================================================== * Utility routines. *========================================================================*/ /* * Implement a simple hash on a character string. * Rotate the hash value by 7 bits, then XOR each character in. * This is implemented with some source-level loop unrolling. */ xfs_dahash_t xfs_da_hashname(const __uint8_t *name, int namelen) { xfs_dahash_t hash; /* * Do four characters at a time as long as we can. */ for (hash = 0; namelen >= 4; namelen -= 4, name += 4) hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^ (name[3] << 0) ^ rol32(hash, 7 * 4); /* * Now do the rest of the characters. */ switch (namelen) { case 3: return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^ rol32(hash, 7 * 3); case 2: return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2); case 1: return (name[0] << 0) ^ rol32(hash, 7 * 1); default: /* case 0: */ return hash; } } enum xfs_dacmp xfs_da_compname( struct xfs_da_args *args, const unsigned char *name, int len) { return (args->namelen == len && memcmp(args->name, name, len) == 0) ? XFS_CMP_EXACT : XFS_CMP_DIFFERENT; } static xfs_dahash_t xfs_default_hashname( struct xfs_name *name) { return xfs_da_hashname(name->name, name->len); } const struct xfs_nameops xfs_default_nameops = { .hashname = xfs_default_hashname, .compname = xfs_da_compname }; int xfs_da_grow_inode_int( struct xfs_da_args *args, xfs_fileoff_t *bno, int count) { struct xfs_trans *tp = args->trans; struct xfs_inode *dp = args->dp; int w = args->whichfork; xfs_rfsblock_t nblks = dp->i_d.di_nblocks; struct xfs_bmbt_irec map, *mapp; int nmap, error, got, i, mapi; /* * Find a spot in the file space to put the new block. */ error = xfs_bmap_first_unused(tp, dp, count, bno, w); if (error) return error; /* * Try mapping it in one filesystem block. */ nmap = 1; ASSERT(args->firstblock != NULL); error = xfs_bmapi_write(tp, dp, *bno, count, xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, args->firstblock, args->total, &map, &nmap, args->dfops); if (error) return error; ASSERT(nmap <= 1); if (nmap == 1) { mapp = ↦ mapi = 1; } else if (nmap == 0 && count > 1) { xfs_fileoff_t b; int c; /* * If we didn't get it and the block might work if fragmented, * try without the CONTIG flag. Loop until we get it all. */ mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP); for (b = *bno, mapi = 0; b < *bno + count; ) { nmap = MIN(XFS_BMAP_MAX_NMAP, count); c = (int)(*bno + count - b); error = xfs_bmapi_write(tp, dp, b, c, xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, args->firstblock, args->total, &mapp[mapi], &nmap, args->dfops); if (error) goto out_free_map; if (nmap < 1) break; mapi += nmap; b = mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount; } } else { mapi = 0; mapp = NULL; } /* * Count the blocks we got, make sure it matches the total. */ for (i = 0, got = 0; i < mapi; i++) got += mapp[i].br_blockcount; if (got != count || mapp[0].br_startoff != *bno || mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != *bno + count) { error = -ENOSPC; goto out_free_map; } /* account for newly allocated blocks in reserved blocks total */ args->total -= dp->i_d.di_nblocks - nblks; out_free_map: if (mapp != &map) kmem_free(mapp); return error; } /* * Add a block to the btree ahead of the file. * Return the new block number to the caller. */ int xfs_da_grow_inode( struct xfs_da_args *args, xfs_dablk_t *new_blkno) { xfs_fileoff_t bno; int error; trace_xfs_da_grow_inode(args); bno = args->geo->leafblk; error = xfs_da_grow_inode_int(args, &bno, args->geo->fsbcount); if (!error) *new_blkno = (xfs_dablk_t)bno; return error; } /* * Ick. We need to always be able to remove a btree block, even * if there's no space reservation because the filesystem is full. * This is called if xfs_bunmapi on a btree block fails due to ENOSPC. * It swaps the target block with the last block in the file. The * last block in the file can always be removed since it can't cause * a bmap btree split to do that. */ STATIC int xfs_da3_swap_lastblock( struct xfs_da_args *args, xfs_dablk_t *dead_blknop, struct xfs_buf **dead_bufp) { struct xfs_da_blkinfo *dead_info; struct xfs_da_blkinfo *sib_info; struct xfs_da_intnode *par_node; struct xfs_da_intnode *dead_node; struct xfs_dir2_leaf *dead_leaf2; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr par_hdr; struct xfs_inode *dp; struct xfs_trans *tp; struct xfs_mount *mp; struct xfs_buf *dead_buf; struct xfs_buf *last_buf; struct xfs_buf *sib_buf; struct xfs_buf *par_buf; xfs_dahash_t dead_hash; xfs_fileoff_t lastoff; xfs_dablk_t dead_blkno; xfs_dablk_t last_blkno; xfs_dablk_t sib_blkno; xfs_dablk_t par_blkno; int error; int w; int entno; int level; int dead_level; trace_xfs_da_swap_lastblock(args); dead_buf = *dead_bufp; dead_blkno = *dead_blknop; tp = args->trans; dp = args->dp; w = args->whichfork; ASSERT(w == XFS_DATA_FORK); mp = dp->i_mount; lastoff = args->geo->freeblk; error = xfs_bmap_last_before(tp, dp, &lastoff, w); if (error) return error; if (unlikely(lastoff == 0)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(1)", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } /* * Read the last block in the btree space. */ last_blkno = (xfs_dablk_t)lastoff - args->geo->fsbcount; error = xfs_da3_node_read(tp, dp, last_blkno, -1, &last_buf, w); if (error) return error; /* * Copy the last block into the dead buffer and log it. */ memcpy(dead_buf->b_addr, last_buf->b_addr, args->geo->blksize); xfs_trans_log_buf(tp, dead_buf, 0, args->geo->blksize - 1); dead_info = dead_buf->b_addr; /* * Get values from the moved block. */ if (dead_info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || dead_info->magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir2_leaf_entry *ents; dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; dp->d_ops->leaf_hdr_from_disk(&leafhdr, dead_leaf2); ents = dp->d_ops->leaf_ents_p(dead_leaf2); dead_level = 0; dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); } else { struct xfs_da3_icnode_hdr deadhdr; dead_node = (xfs_da_intnode_t *)dead_info; dp->d_ops->node_hdr_from_disk(&deadhdr, dead_node); btree = dp->d_ops->node_tree_p(dead_node); dead_level = deadhdr.level; dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval); } sib_buf = par_buf = NULL; /* * If the moved block has a left sibling, fix up the pointers. */ if ((sib_blkno = be32_to_cpu(dead_info->back))) { error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w); if (error) goto done; sib_info = sib_buf->b_addr; if (unlikely( be32_to_cpu(sib_info->forw) != last_blkno || sib_info->magic != dead_info->magic)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto done; } sib_info->forw = cpu_to_be32(dead_blkno); xfs_trans_log_buf(tp, sib_buf, XFS_DA_LOGRANGE(sib_info, &sib_info->forw, sizeof(sib_info->forw))); sib_buf = NULL; } /* * If the moved block has a right sibling, fix up the pointers. */ if ((sib_blkno = be32_to_cpu(dead_info->forw))) { error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w); if (error) goto done; sib_info = sib_buf->b_addr; if (unlikely( be32_to_cpu(sib_info->back) != last_blkno || sib_info->magic != dead_info->magic)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto done; } sib_info->back = cpu_to_be32(dead_blkno); xfs_trans_log_buf(tp, sib_buf, XFS_DA_LOGRANGE(sib_info, &sib_info->back, sizeof(sib_info->back))); sib_buf = NULL; } par_blkno = args->geo->leafblk; level = -1; /* * Walk down the tree looking for the parent of the moved block. */ for (;;) { error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w); if (error) goto done; par_node = par_buf->b_addr; dp->d_ops->node_hdr_from_disk(&par_hdr, par_node); if (level >= 0 && level != par_hdr.level + 1) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto done; } level = par_hdr.level; btree = dp->d_ops->node_tree_p(par_node); for (entno = 0; entno < par_hdr.count && be32_to_cpu(btree[entno].hashval) < dead_hash; entno++) continue; if (entno == par_hdr.count) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto done; } par_blkno = be32_to_cpu(btree[entno].before); if (level == dead_level + 1) break; xfs_trans_brelse(tp, par_buf); par_buf = NULL; } /* * We're in the right parent block. * Look for the right entry. */ for (;;) { for (; entno < par_hdr.count && be32_to_cpu(btree[entno].before) != last_blkno; entno++) continue; if (entno < par_hdr.count) break; par_blkno = par_hdr.forw; xfs_trans_brelse(tp, par_buf); par_buf = NULL; if (unlikely(par_blkno == 0)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto done; } error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w); if (error) goto done; par_node = par_buf->b_addr; dp->d_ops->node_hdr_from_disk(&par_hdr, par_node); if (par_hdr.level != level) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto done; } btree = dp->d_ops->node_tree_p(par_node); entno = 0; } /* * Update the parent entry pointing to the moved block. */ btree[entno].before = cpu_to_be32(dead_blkno); xfs_trans_log_buf(tp, par_buf, XFS_DA_LOGRANGE(par_node, &btree[entno].before, sizeof(btree[entno].before))); *dead_blknop = last_blkno; *dead_bufp = last_buf; return 0; done: if (par_buf) xfs_trans_brelse(tp, par_buf); if (sib_buf) xfs_trans_brelse(tp, sib_buf); xfs_trans_brelse(tp, last_buf); return error; } /* * Remove a btree block from a directory or attribute. */ int xfs_da_shrink_inode( xfs_da_args_t *args, xfs_dablk_t dead_blkno, struct xfs_buf *dead_buf) { xfs_inode_t *dp; int done, error, w, count; xfs_trans_t *tp; trace_xfs_da_shrink_inode(args); dp = args->dp; w = args->whichfork; tp = args->trans; count = args->geo->fsbcount; for (;;) { /* * Remove extents. If we get ENOSPC for a dir we have to move * the last block to the place we want to kill. */ error = xfs_bunmapi(tp, dp, dead_blkno, count, xfs_bmapi_aflag(w), 0, args->firstblock, args->dfops, &done); if (error == -ENOSPC) { if (w != XFS_DATA_FORK) break; error = xfs_da3_swap_lastblock(args, &dead_blkno, &dead_buf); if (error) break; } else { break; } } xfs_trans_binval(tp, dead_buf); return error; } /* * See if the mapping(s) for this btree block are valid, i.e. * don't contain holes, are logically contiguous, and cover the whole range. */ STATIC int xfs_da_map_covers_blocks( int nmap, xfs_bmbt_irec_t *mapp, xfs_dablk_t bno, int count) { int i; xfs_fileoff_t off; for (i = 0, off = bno; i < nmap; i++) { if (mapp[i].br_startblock == HOLESTARTBLOCK || mapp[i].br_startblock == DELAYSTARTBLOCK) { return 0; } if (off != mapp[i].br_startoff) { return 0; } off += mapp[i].br_blockcount; } return off == bno + count; } /* * Convert a struct xfs_bmbt_irec to a struct xfs_buf_map. * * For the single map case, it is assumed that the caller has provided a pointer * to a valid xfs_buf_map. For the multiple map case, this function will * allocate the xfs_buf_map to hold all the maps and replace the caller's single * map pointer with the allocated map. */ static int xfs_buf_map_from_irec( struct xfs_mount *mp, struct xfs_buf_map **mapp, int *nmaps, struct xfs_bmbt_irec *irecs, int nirecs) { struct xfs_buf_map *map; int i; ASSERT(*nmaps == 1); ASSERT(nirecs >= 1); if (nirecs > 1) { map = kmem_zalloc(nirecs * sizeof(struct xfs_buf_map), KM_SLEEP | KM_NOFS); if (!map) return -ENOMEM; *mapp = map; } *nmaps = nirecs; map = *mapp; for (i = 0; i < *nmaps; i++) { ASSERT(irecs[i].br_startblock != DELAYSTARTBLOCK && irecs[i].br_startblock != HOLESTARTBLOCK); map[i].bm_bn = XFS_FSB_TO_DADDR(mp, irecs[i].br_startblock); map[i].bm_len = XFS_FSB_TO_BB(mp, irecs[i].br_blockcount); } return 0; } /* * Map the block we are given ready for reading. There are three possible return * values: * -1 - will be returned if we land in a hole and mappedbno == -2 so the * caller knows not to execute a subsequent read. * 0 - if we mapped the block successfully * >0 - positive error number if there was an error. */ static int xfs_dabuf_map( struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, int whichfork, struct xfs_buf_map **map, int *nmaps) { struct xfs_mount *mp = dp->i_mount; int nfsb; int error = 0; struct xfs_bmbt_irec irec; struct xfs_bmbt_irec *irecs = &irec; int nirecs; ASSERT(map && *map); ASSERT(*nmaps == 1); if (whichfork == XFS_DATA_FORK) nfsb = mp->m_dir_geo->fsbcount; else nfsb = mp->m_attr_geo->fsbcount; /* * Caller doesn't have a mapping. -2 means don't complain * if we land in a hole. */ if (mappedbno == -1 || mappedbno == -2) { /* * Optimize the one-block case. */ if (nfsb != 1) irecs = kmem_zalloc(sizeof(irec) * nfsb, KM_SLEEP | KM_NOFS); nirecs = nfsb; error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, irecs, &nirecs, xfs_bmapi_aflag(whichfork)); if (error) goto out; } else { irecs->br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); irecs->br_startoff = (xfs_fileoff_t)bno; irecs->br_blockcount = nfsb; irecs->br_state = 0; nirecs = 1; } if (!xfs_da_map_covers_blocks(nirecs, irecs, bno, nfsb)) { error = mappedbno == -2 ? -1 : -EFSCORRUPTED; if (unlikely(error == -EFSCORRUPTED)) { if (xfs_error_level >= XFS_ERRLEVEL_LOW) { int i; xfs_alert(mp, "%s: bno %lld dir: inode %lld", __func__, (long long)bno, (long long)dp->i_ino); for (i = 0; i < *nmaps; i++) { xfs_alert(mp, "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", i, (long long)irecs[i].br_startoff, (long long)irecs[i].br_startblock, (long long)irecs[i].br_blockcount, irecs[i].br_state); } } XFS_ERROR_REPORT("xfs_da_do_buf(1)", XFS_ERRLEVEL_LOW, mp); } goto out; } error = xfs_buf_map_from_irec(mp, map, nmaps, irecs, nirecs); out: if (irecs != &irec) kmem_free(irecs); return error; } /* * Get a buffer for the dir/attr block. */ int xfs_da_get_buf( struct xfs_trans *trans, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp, int whichfork) { struct xfs_buf *bp; struct xfs_buf_map map; struct xfs_buf_map *mapp; int nmap; int error; *bpp = NULL; mapp = ↦ nmap = 1; error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, &mapp, &nmap); if (error) { /* mapping a hole is not an error, but we don't continue */ if (error == -1) error = 0; goto out_free; } bp = xfs_trans_get_buf_map(trans, dp->i_mount->m_ddev_targp, mapp, nmap, 0); error = bp ? bp->b_error : -EIO; if (error) { if (bp) xfs_trans_brelse(trans, bp); goto out_free; } *bpp = bp; out_free: if (mapp != &map) kmem_free(mapp); return error; } /* * Get a buffer for the dir/attr block, fill in the contents. */ int xfs_da_read_buf( struct xfs_trans *trans, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp, int whichfork, const struct xfs_buf_ops *ops) { struct xfs_buf *bp; struct xfs_buf_map map; struct xfs_buf_map *mapp; int nmap; int error; *bpp = NULL; mapp = ↦ nmap = 1; error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, &mapp, &nmap); if (error) { /* mapping a hole is not an error, but we don't continue */ if (error == -1) error = 0; goto out_free; } error = xfs_trans_read_buf_map(dp->i_mount, trans, dp->i_mount->m_ddev_targp, mapp, nmap, 0, &bp, ops); if (error) goto out_free; if (whichfork == XFS_ATTR_FORK) xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); else xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); *bpp = bp; out_free: if (mapp != &map) kmem_free(mapp); return error; } /* * Readahead the dir/attr block. */ xfs_daddr_t xfs_da_reada_buf( struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, int whichfork, const struct xfs_buf_ops *ops) { struct xfs_buf_map map; struct xfs_buf_map *mapp; int nmap; int error; mapp = ↦ nmap = 1; error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, &mapp, &nmap); if (error) { /* mapping a hole is not an error, but we don't continue */ if (error == -1) error = 0; goto out_free; } mappedbno = mapp[0].bm_bn; xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap, ops); out_free: if (mapp != &map) kmem_free(mapp); if (error) return -1; return mappedbno; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_da_btree.h0000644000000000000000000002033213063067170016556 0ustar /* * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_DA_BTREE_H__ #define __XFS_DA_BTREE_H__ struct xfs_defer_ops; struct xfs_inode; struct xfs_trans; struct zone; struct xfs_dir_ops; /* * Directory/attribute geometry information. There will be one of these for each * data fork type, and it will be passed around via the xfs_da_args. Global * structures will be attached to the xfs_mount. */ struct xfs_da_geometry { int blksize; /* da block size in bytes */ int fsbcount; /* da block size in filesystem blocks */ uint8_t fsblog; /* log2 of _filesystem_ block size */ uint8_t blklog; /* log2 of da block size */ uint node_ents; /* # of entries in a danode */ int magicpct; /* 37% of block size in bytes */ xfs_dablk_t datablk; /* blockno of dir data v2 */ xfs_dablk_t leafblk; /* blockno of leaf data v2 */ xfs_dablk_t freeblk; /* blockno of free data v2 */ }; /*======================================================================== * Btree searching and modification structure definitions. *========================================================================*/ /* * Search comparison results */ enum xfs_dacmp { XFS_CMP_DIFFERENT, /* names are completely different */ XFS_CMP_EXACT, /* names are exactly the same */ XFS_CMP_CASE /* names are same but differ in case */ }; /* * Structure to ease passing around component names. */ typedef struct xfs_da_args { struct xfs_da_geometry *geo; /* da block geometry */ const __uint8_t *name; /* string (maybe not NULL terminated) */ int namelen; /* length of string (maybe no NULL) */ __uint8_t filetype; /* filetype of inode for directories */ __uint8_t *value; /* set of bytes (maybe contain NULLs) */ int valuelen; /* length of value */ int flags; /* argument flags (eg: ATTR_NOCREATE) */ xfs_dahash_t hashval; /* hash value of name */ xfs_ino_t inumber; /* input/output inode number */ struct xfs_inode *dp; /* directory inode to manipulate */ xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */ struct xfs_defer_ops *dfops; /* ptr to freelist for bmap_finish */ struct xfs_trans *trans; /* current trans (changes over time) */ xfs_extlen_t total; /* total blocks needed, for 1st bmap */ int whichfork; /* data or attribute fork */ xfs_dablk_t blkno; /* blkno of attr leaf of interest */ int index; /* index of attr of interest in blk */ xfs_dablk_t rmtblkno; /* remote attr value starting blkno */ int rmtblkcnt; /* remote attr value block count */ int rmtvaluelen; /* remote attr value length in bytes */ xfs_dablk_t blkno2; /* blkno of 2nd attr leaf of interest */ int index2; /* index of 2nd attr in blk */ xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */ int rmtblkcnt2; /* remote attr value block count */ int rmtvaluelen2; /* remote attr value length in bytes */ int op_flags; /* operation flags */ enum xfs_dacmp cmpresult; /* name compare result for lookups */ } xfs_da_args_t; /* * Operation flags: */ #define XFS_DA_OP_JUSTCHECK 0x0001 /* check for ok with no space */ #define XFS_DA_OP_RENAME 0x0002 /* this is an atomic rename op */ #define XFS_DA_OP_ADDNAME 0x0004 /* this is an add operation */ #define XFS_DA_OP_OKNOENT 0x0008 /* lookup/add op, ENOENT ok, else die */ #define XFS_DA_OP_CILOOKUP 0x0010 /* lookup to return CI name if found */ #define XFS_DA_OP_FLAGS \ { XFS_DA_OP_JUSTCHECK, "JUSTCHECK" }, \ { XFS_DA_OP_RENAME, "RENAME" }, \ { XFS_DA_OP_ADDNAME, "ADDNAME" }, \ { XFS_DA_OP_OKNOENT, "OKNOENT" }, \ { XFS_DA_OP_CILOOKUP, "CILOOKUP" } /* * Storage for holding state during Btree searches and split/join ops. * * Only need space for 5 intermediate nodes. With a minimum of 62-way * fanout to the Btree, we can support over 900 million directory blocks, * which is slightly more than enough. */ typedef struct xfs_da_state_blk { struct xfs_buf *bp; /* buffer containing block */ xfs_dablk_t blkno; /* filesystem blkno of buffer */ xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */ int index; /* relevant index into block */ xfs_dahash_t hashval; /* last hash value in block */ int magic; /* blk's magic number, ie: blk type */ } xfs_da_state_blk_t; typedef struct xfs_da_state_path { int active; /* number of active levels */ xfs_da_state_blk_t blk[XFS_DA_NODE_MAXDEPTH]; } xfs_da_state_path_t; typedef struct xfs_da_state { xfs_da_args_t *args; /* filename arguments */ struct xfs_mount *mp; /* filesystem mount point */ xfs_da_state_path_t path; /* search/split paths */ xfs_da_state_path_t altpath; /* alternate path for join */ unsigned char inleaf; /* insert into 1->lf, 0->splf */ unsigned char extravalid; /* T/F: extrablk is in use */ unsigned char extraafter; /* T/F: extrablk is after new */ xfs_da_state_blk_t extrablk; /* for double-splits on leaves */ /* for dirv2 extrablk is data */ } xfs_da_state_t; /* * Utility macros to aid in logging changed structure fields. */ #define XFS_DA_LOGOFF(BASE, ADDR) ((char *)(ADDR) - (char *)(BASE)) #define XFS_DA_LOGRANGE(BASE, ADDR, SIZE) \ (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \ (uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1) /* * Name ops for directory and/or attr name operations */ struct xfs_nameops { xfs_dahash_t (*hashname)(struct xfs_name *); enum xfs_dacmp (*compname)(struct xfs_da_args *, const unsigned char *, int); }; /*======================================================================== * Function prototypes. *========================================================================*/ /* * Routines used for growing the Btree. */ int xfs_da3_node_create(struct xfs_da_args *args, xfs_dablk_t blkno, int level, struct xfs_buf **bpp, int whichfork); int xfs_da3_split(xfs_da_state_t *state); /* * Routines used for shrinking the Btree. */ int xfs_da3_join(xfs_da_state_t *state); void xfs_da3_fixhashpath(struct xfs_da_state *state, struct xfs_da_state_path *path_to_to_fix); /* * Routines used for finding things in the Btree. */ int xfs_da3_node_lookup_int(xfs_da_state_t *state, int *result); int xfs_da3_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, int forward, int release, int *result); /* * Utility routines. */ int xfs_da3_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, xfs_da_state_blk_t *new_blk); int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp, int which_fork); /* * Utility routines. */ int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno); int xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno, int count); int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bp, int whichfork); int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp, int whichfork, const struct xfs_buf_ops *ops); xfs_daddr_t xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mapped_bno, int whichfork, const struct xfs_buf_ops *ops); int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, struct xfs_buf *dead_buf); uint xfs_da_hashname(const __uint8_t *name_string, int name_length); enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, const unsigned char *name, int len); xfs_da_state_t *xfs_da_state_alloc(void); void xfs_da_state_free(xfs_da_state_t *state); extern struct kmem_zone *xfs_da_state_zone; extern const struct xfs_nameops xfs_default_nameops; #endif /* __XFS_DA_BTREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_da_format.c0000644000000000000000000005762413063067171016757 0ustar /* * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" /* * Shortform directory ops */ static int xfs_dir2_sf_entsize( struct xfs_dir2_sf_hdr *hdr, int len) { int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */ count += len; /* name */ count += hdr->i8count ? XFS_INO64_SIZE : XFS_INO32_SIZE; /* ino # */ return count; } static int xfs_dir3_sf_entsize( struct xfs_dir2_sf_hdr *hdr, int len) { return xfs_dir2_sf_entsize(hdr, len) + sizeof(__uint8_t); } static struct xfs_dir2_sf_entry * xfs_dir2_sf_nextentry( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep) { return (struct xfs_dir2_sf_entry *) ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen)); } static struct xfs_dir2_sf_entry * xfs_dir3_sf_nextentry( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep) { return (struct xfs_dir2_sf_entry *) ((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen)); } /* * For filetype enabled shortform directories, the file type field is stored at * the end of the name. Because it's only a single byte, endian conversion is * not necessary. For non-filetype enable directories, the type is always * unknown and we never store the value. */ static __uint8_t xfs_dir2_sfe_get_ftype( struct xfs_dir2_sf_entry *sfep) { return XFS_DIR3_FT_UNKNOWN; } static void xfs_dir2_sfe_put_ftype( struct xfs_dir2_sf_entry *sfep, __uint8_t ftype) { ASSERT(ftype < XFS_DIR3_FT_MAX); } static __uint8_t xfs_dir3_sfe_get_ftype( struct xfs_dir2_sf_entry *sfep) { __uint8_t ftype; ftype = sfep->name[sfep->namelen]; if (ftype >= XFS_DIR3_FT_MAX) return XFS_DIR3_FT_UNKNOWN; return ftype; } static void xfs_dir3_sfe_put_ftype( struct xfs_dir2_sf_entry *sfep, __uint8_t ftype) { ASSERT(ftype < XFS_DIR3_FT_MAX); sfep->name[sfep->namelen] = ftype; } /* * Inode numbers in short-form directories can come in two versions, * either 4 bytes or 8 bytes wide. These helpers deal with the * two forms transparently by looking at the headers i8count field. * * For 64-bit inode number the most significant byte must be zero. */ static xfs_ino_t xfs_dir2_sf_get_ino( struct xfs_dir2_sf_hdr *hdr, __uint8_t *from) { if (hdr->i8count) return get_unaligned_be64(from) & 0x00ffffffffffffffULL; else return get_unaligned_be32(from); } static void xfs_dir2_sf_put_ino( struct xfs_dir2_sf_hdr *hdr, __uint8_t *to, xfs_ino_t ino) { ASSERT((ino & 0xff00000000000000ULL) == 0); if (hdr->i8count) put_unaligned_be64(ino, to); else put_unaligned_be32(ino, to); } static xfs_ino_t xfs_dir2_sf_get_parent_ino( struct xfs_dir2_sf_hdr *hdr) { return xfs_dir2_sf_get_ino(hdr, hdr->parent); } static void xfs_dir2_sf_put_parent_ino( struct xfs_dir2_sf_hdr *hdr, xfs_ino_t ino) { xfs_dir2_sf_put_ino(hdr, hdr->parent, ino); } /* * In short-form directory entries the inode numbers are stored at variable * offset behind the entry name. If the entry stores a filetype value, then it * sits between the name and the inode number. Hence the inode numbers may only * be accessed through the helpers below. */ static xfs_ino_t xfs_dir2_sfe_get_ino( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep) { return xfs_dir2_sf_get_ino(hdr, &sfep->name[sfep->namelen]); } static void xfs_dir2_sfe_put_ino( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino) { xfs_dir2_sf_put_ino(hdr, &sfep->name[sfep->namelen], ino); } static xfs_ino_t xfs_dir3_sfe_get_ino( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep) { return xfs_dir2_sf_get_ino(hdr, &sfep->name[sfep->namelen + 1]); } static void xfs_dir3_sfe_put_ino( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino) { xfs_dir2_sf_put_ino(hdr, &sfep->name[sfep->namelen + 1], ino); } /* * Directory data block operations */ /* * For special situations, the dirent size ends up fixed because we always know * what the size of the entry is. That's true for the "." and "..", and * therefore we know that they are a fixed size and hence their offsets are * constant, as is the first entry. * * Hence, this calculation is written as a macro to be able to be calculated at * compile time and so certain offsets can be calculated directly in the * structure initaliser via the macro. There are two macros - one for dirents * with ftype and without so there are no unresolvable conditionals in the * calculations. We also use round_up() as XFS_DIR2_DATA_ALIGN is always a power * of 2 and the compiler doesn't reject it (unlike roundup()). */ #define XFS_DIR2_DATA_ENTSIZE(n) \ round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \ sizeof(xfs_dir2_data_off_t)), XFS_DIR2_DATA_ALIGN) #define XFS_DIR3_DATA_ENTSIZE(n) \ round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \ sizeof(xfs_dir2_data_off_t) + sizeof(__uint8_t)), \ XFS_DIR2_DATA_ALIGN) static int xfs_dir2_data_entsize( int n) { return XFS_DIR2_DATA_ENTSIZE(n); } static int xfs_dir3_data_entsize( int n) { return XFS_DIR3_DATA_ENTSIZE(n); } static __uint8_t xfs_dir2_data_get_ftype( struct xfs_dir2_data_entry *dep) { return XFS_DIR3_FT_UNKNOWN; } static void xfs_dir2_data_put_ftype( struct xfs_dir2_data_entry *dep, __uint8_t ftype) { ASSERT(ftype < XFS_DIR3_FT_MAX); } static __uint8_t xfs_dir3_data_get_ftype( struct xfs_dir2_data_entry *dep) { __uint8_t ftype = dep->name[dep->namelen]; if (ftype >= XFS_DIR3_FT_MAX) return XFS_DIR3_FT_UNKNOWN; return ftype; } static void xfs_dir3_data_put_ftype( struct xfs_dir2_data_entry *dep, __uint8_t type) { ASSERT(type < XFS_DIR3_FT_MAX); ASSERT(dep->namelen != 0); dep->name[dep->namelen] = type; } /* * Pointer to an entry's tag word. */ static __be16 * xfs_dir2_data_entry_tag_p( struct xfs_dir2_data_entry *dep) { return (__be16 *)((char *)dep + xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16)); } static __be16 * xfs_dir3_data_entry_tag_p( struct xfs_dir2_data_entry *dep) { return (__be16 *)((char *)dep + xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16)); } /* * location of . and .. in data space (always block 0) */ static struct xfs_dir2_data_entry * xfs_dir2_data_dot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); } static struct xfs_dir2_data_entry * xfs_dir2_data_dotdot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + XFS_DIR2_DATA_ENTSIZE(1)); } static struct xfs_dir2_data_entry * xfs_dir2_data_first_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + XFS_DIR2_DATA_ENTSIZE(1) + XFS_DIR2_DATA_ENTSIZE(2)); } static struct xfs_dir2_data_entry * xfs_dir2_ftype_data_dotdot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1)); } static struct xfs_dir2_data_entry * xfs_dir2_ftype_data_first_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1) + XFS_DIR3_DATA_ENTSIZE(2)); } static struct xfs_dir2_data_entry * xfs_dir3_data_dot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); } static struct xfs_dir2_data_entry * xfs_dir3_data_dotdot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1)); } static struct xfs_dir2_data_entry * xfs_dir3_data_first_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1) + XFS_DIR3_DATA_ENTSIZE(2)); } static struct xfs_dir2_data_free * xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) { return hdr->bestfree; } static struct xfs_dir2_data_free * xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) { return ((struct xfs_dir3_data_hdr *)hdr)->best_free; } static struct xfs_dir2_data_entry * xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); } static struct xfs_dir2_data_unused * xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_unused *) ((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); } static struct xfs_dir2_data_entry * xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) ((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); } static struct xfs_dir2_data_unused * xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_unused *) ((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); } /* * Directory Leaf block operations */ static int xfs_dir2_max_leaf_ents(struct xfs_da_geometry *geo) { return (geo->blksize - sizeof(struct xfs_dir2_leaf_hdr)) / (uint)sizeof(struct xfs_dir2_leaf_entry); } static struct xfs_dir2_leaf_entry * xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp) { return lp->__ents; } static int xfs_dir3_max_leaf_ents(struct xfs_da_geometry *geo) { return (geo->blksize - sizeof(struct xfs_dir3_leaf_hdr)) / (uint)sizeof(struct xfs_dir2_leaf_entry); } static struct xfs_dir2_leaf_entry * xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) { return ((struct xfs_dir3_leaf *)lp)->__ents; } static void xfs_dir2_leaf_hdr_from_disk( struct xfs_dir3_icleaf_hdr *to, struct xfs_dir2_leaf *from) { to->forw = be32_to_cpu(from->hdr.info.forw); to->back = be32_to_cpu(from->hdr.info.back); to->magic = be16_to_cpu(from->hdr.info.magic); to->count = be16_to_cpu(from->hdr.count); to->stale = be16_to_cpu(from->hdr.stale); ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC || to->magic == XFS_DIR2_LEAFN_MAGIC); } static void xfs_dir2_leaf_hdr_to_disk( struct xfs_dir2_leaf *to, struct xfs_dir3_icleaf_hdr *from) { ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC || from->magic == XFS_DIR2_LEAFN_MAGIC); to->hdr.info.forw = cpu_to_be32(from->forw); to->hdr.info.back = cpu_to_be32(from->back); to->hdr.info.magic = cpu_to_be16(from->magic); to->hdr.count = cpu_to_be16(from->count); to->hdr.stale = cpu_to_be16(from->stale); } static void xfs_dir3_leaf_hdr_from_disk( struct xfs_dir3_icleaf_hdr *to, struct xfs_dir2_leaf *from) { struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from; to->forw = be32_to_cpu(hdr3->info.hdr.forw); to->back = be32_to_cpu(hdr3->info.hdr.back); to->magic = be16_to_cpu(hdr3->info.hdr.magic); to->count = be16_to_cpu(hdr3->count); to->stale = be16_to_cpu(hdr3->stale); ASSERT(to->magic == XFS_DIR3_LEAF1_MAGIC || to->magic == XFS_DIR3_LEAFN_MAGIC); } static void xfs_dir3_leaf_hdr_to_disk( struct xfs_dir2_leaf *to, struct xfs_dir3_icleaf_hdr *from) { struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to; ASSERT(from->magic == XFS_DIR3_LEAF1_MAGIC || from->magic == XFS_DIR3_LEAFN_MAGIC); hdr3->info.hdr.forw = cpu_to_be32(from->forw); hdr3->info.hdr.back = cpu_to_be32(from->back); hdr3->info.hdr.magic = cpu_to_be16(from->magic); hdr3->count = cpu_to_be16(from->count); hdr3->stale = cpu_to_be16(from->stale); } /* * Directory/Attribute Node block operations */ static struct xfs_da_node_entry * xfs_da2_node_tree_p(struct xfs_da_intnode *dap) { return dap->__btree; } static struct xfs_da_node_entry * xfs_da3_node_tree_p(struct xfs_da_intnode *dap) { return ((struct xfs_da3_intnode *)dap)->__btree; } static void xfs_da2_node_hdr_from_disk( struct xfs_da3_icnode_hdr *to, struct xfs_da_intnode *from) { ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); to->forw = be32_to_cpu(from->hdr.info.forw); to->back = be32_to_cpu(from->hdr.info.back); to->magic = be16_to_cpu(from->hdr.info.magic); to->count = be16_to_cpu(from->hdr.__count); to->level = be16_to_cpu(from->hdr.__level); } static void xfs_da2_node_hdr_to_disk( struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from) { ASSERT(from->magic == XFS_DA_NODE_MAGIC); to->hdr.info.forw = cpu_to_be32(from->forw); to->hdr.info.back = cpu_to_be32(from->back); to->hdr.info.magic = cpu_to_be16(from->magic); to->hdr.__count = cpu_to_be16(from->count); to->hdr.__level = cpu_to_be16(from->level); } static void xfs_da3_node_hdr_from_disk( struct xfs_da3_icnode_hdr *to, struct xfs_da_intnode *from) { struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from; ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)); to->forw = be32_to_cpu(hdr3->info.hdr.forw); to->back = be32_to_cpu(hdr3->info.hdr.back); to->magic = be16_to_cpu(hdr3->info.hdr.magic); to->count = be16_to_cpu(hdr3->__count); to->level = be16_to_cpu(hdr3->__level); } static void xfs_da3_node_hdr_to_disk( struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from) { struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to; ASSERT(from->magic == XFS_DA3_NODE_MAGIC); hdr3->info.hdr.forw = cpu_to_be32(from->forw); hdr3->info.hdr.back = cpu_to_be32(from->back); hdr3->info.hdr.magic = cpu_to_be16(from->magic); hdr3->__count = cpu_to_be16(from->count); hdr3->__level = cpu_to_be16(from->level); } /* * Directory free space block operations */ static int xfs_dir2_free_max_bests(struct xfs_da_geometry *geo) { return (geo->blksize - sizeof(struct xfs_dir2_free_hdr)) / sizeof(xfs_dir2_data_off_t); } static __be16 * xfs_dir2_free_bests_p(struct xfs_dir2_free *free) { return (__be16 *)((char *)free + sizeof(struct xfs_dir2_free_hdr)); } /* * Convert data space db to the corresponding free db. */ static xfs_dir2_db_t xfs_dir2_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db) { return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) + (db / xfs_dir2_free_max_bests(geo)); } /* * Convert data space db to the corresponding index in a free db. */ static int xfs_dir2_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db) { return db % xfs_dir2_free_max_bests(geo); } static int xfs_dir3_free_max_bests(struct xfs_da_geometry *geo) { return (geo->blksize - sizeof(struct xfs_dir3_free_hdr)) / sizeof(xfs_dir2_data_off_t); } static __be16 * xfs_dir3_free_bests_p(struct xfs_dir2_free *free) { return (__be16 *)((char *)free + sizeof(struct xfs_dir3_free_hdr)); } /* * Convert data space db to the corresponding free db. */ static xfs_dir2_db_t xfs_dir3_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db) { return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) + (db / xfs_dir3_free_max_bests(geo)); } /* * Convert data space db to the corresponding index in a free db. */ static int xfs_dir3_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db) { return db % xfs_dir3_free_max_bests(geo); } static void xfs_dir2_free_hdr_from_disk( struct xfs_dir3_icfree_hdr *to, struct xfs_dir2_free *from) { to->magic = be32_to_cpu(from->hdr.magic); to->firstdb = be32_to_cpu(from->hdr.firstdb); to->nvalid = be32_to_cpu(from->hdr.nvalid); to->nused = be32_to_cpu(from->hdr.nused); ASSERT(to->magic == XFS_DIR2_FREE_MAGIC); } static void xfs_dir2_free_hdr_to_disk( struct xfs_dir2_free *to, struct xfs_dir3_icfree_hdr *from) { ASSERT(from->magic == XFS_DIR2_FREE_MAGIC); to->hdr.magic = cpu_to_be32(from->magic); to->hdr.firstdb = cpu_to_be32(from->firstdb); to->hdr.nvalid = cpu_to_be32(from->nvalid); to->hdr.nused = cpu_to_be32(from->nused); } static void xfs_dir3_free_hdr_from_disk( struct xfs_dir3_icfree_hdr *to, struct xfs_dir2_free *from) { struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from; to->magic = be32_to_cpu(hdr3->hdr.magic); to->firstdb = be32_to_cpu(hdr3->firstdb); to->nvalid = be32_to_cpu(hdr3->nvalid); to->nused = be32_to_cpu(hdr3->nused); ASSERT(to->magic == XFS_DIR3_FREE_MAGIC); } static void xfs_dir3_free_hdr_to_disk( struct xfs_dir2_free *to, struct xfs_dir3_icfree_hdr *from) { struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to; ASSERT(from->magic == XFS_DIR3_FREE_MAGIC); hdr3->hdr.magic = cpu_to_be32(from->magic); hdr3->firstdb = cpu_to_be32(from->firstdb); hdr3->nvalid = cpu_to_be32(from->nvalid); hdr3->nused = cpu_to_be32(from->nused); } static const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, .sf_get_ftype = xfs_dir2_sfe_get_ftype, .sf_put_ftype = xfs_dir2_sfe_put_ftype, .sf_get_ino = xfs_dir2_sfe_get_ino, .sf_put_ino = xfs_dir2_sfe_put_ino, .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, .data_entsize = xfs_dir2_data_entsize, .data_get_ftype = xfs_dir2_data_get_ftype, .data_put_ftype = xfs_dir2_data_put_ftype, .data_entry_tag_p = xfs_dir2_data_entry_tag_p, .data_bestfree_p = xfs_dir2_data_bestfree_p, .data_dot_offset = sizeof(struct xfs_dir2_data_hdr), .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) + XFS_DIR2_DATA_ENTSIZE(1), .data_first_offset = sizeof(struct xfs_dir2_data_hdr) + XFS_DIR2_DATA_ENTSIZE(1) + XFS_DIR2_DATA_ENTSIZE(2), .data_entry_offset = sizeof(struct xfs_dir2_data_hdr), .data_dot_entry_p = xfs_dir2_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, .data_first_entry_p = xfs_dir2_data_first_entry_p, .data_entry_p = xfs_dir2_data_entry_p, .data_unused_p = xfs_dir2_data_unused_p, .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr), .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk, .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, .node_hdr_size = sizeof(struct xfs_da_node_hdr), .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, .free_hdr_size = sizeof(struct xfs_dir2_free_hdr), .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, .free_max_bests = xfs_dir2_free_max_bests, .free_bests_p = xfs_dir2_free_bests_p, .db_to_fdb = xfs_dir2_db_to_fdb, .db_to_fdindex = xfs_dir2_db_to_fdindex, }; static const struct xfs_dir_ops xfs_dir2_ftype_ops = { .sf_entsize = xfs_dir3_sf_entsize, .sf_nextentry = xfs_dir3_sf_nextentry, .sf_get_ftype = xfs_dir3_sfe_get_ftype, .sf_put_ftype = xfs_dir3_sfe_put_ftype, .sf_get_ino = xfs_dir3_sfe_get_ino, .sf_put_ino = xfs_dir3_sfe_put_ino, .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, .data_entsize = xfs_dir3_data_entsize, .data_get_ftype = xfs_dir3_data_get_ftype, .data_put_ftype = xfs_dir3_data_put_ftype, .data_entry_tag_p = xfs_dir3_data_entry_tag_p, .data_bestfree_p = xfs_dir2_data_bestfree_p, .data_dot_offset = sizeof(struct xfs_dir2_data_hdr), .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1), .data_first_offset = sizeof(struct xfs_dir2_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1) + XFS_DIR3_DATA_ENTSIZE(2), .data_entry_offset = sizeof(struct xfs_dir2_data_hdr), .data_dot_entry_p = xfs_dir2_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir2_ftype_data_dotdot_entry_p, .data_first_entry_p = xfs_dir2_ftype_data_first_entry_p, .data_entry_p = xfs_dir2_data_entry_p, .data_unused_p = xfs_dir2_data_unused_p, .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr), .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk, .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, .node_hdr_size = sizeof(struct xfs_da_node_hdr), .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, .free_hdr_size = sizeof(struct xfs_dir2_free_hdr), .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, .free_max_bests = xfs_dir2_free_max_bests, .free_bests_p = xfs_dir2_free_bests_p, .db_to_fdb = xfs_dir2_db_to_fdb, .db_to_fdindex = xfs_dir2_db_to_fdindex, }; static const struct xfs_dir_ops xfs_dir3_ops = { .sf_entsize = xfs_dir3_sf_entsize, .sf_nextentry = xfs_dir3_sf_nextentry, .sf_get_ftype = xfs_dir3_sfe_get_ftype, .sf_put_ftype = xfs_dir3_sfe_put_ftype, .sf_get_ino = xfs_dir3_sfe_get_ino, .sf_put_ino = xfs_dir3_sfe_put_ino, .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, .data_entsize = xfs_dir3_data_entsize, .data_get_ftype = xfs_dir3_data_get_ftype, .data_put_ftype = xfs_dir3_data_put_ftype, .data_entry_tag_p = xfs_dir3_data_entry_tag_p, .data_bestfree_p = xfs_dir3_data_bestfree_p, .data_dot_offset = sizeof(struct xfs_dir3_data_hdr), .data_dotdot_offset = sizeof(struct xfs_dir3_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1), .data_first_offset = sizeof(struct xfs_dir3_data_hdr) + XFS_DIR3_DATA_ENTSIZE(1) + XFS_DIR3_DATA_ENTSIZE(2), .data_entry_offset = sizeof(struct xfs_dir3_data_hdr), .data_dot_entry_p = xfs_dir3_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p, .data_first_entry_p = xfs_dir3_data_first_entry_p, .data_entry_p = xfs_dir3_data_entry_p, .data_unused_p = xfs_dir3_data_unused_p, .leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr), .leaf_hdr_to_disk = xfs_dir3_leaf_hdr_to_disk, .leaf_hdr_from_disk = xfs_dir3_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir3_max_leaf_ents, .leaf_ents_p = xfs_dir3_leaf_ents_p, .node_hdr_size = sizeof(struct xfs_da3_node_hdr), .node_hdr_to_disk = xfs_da3_node_hdr_to_disk, .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, .node_tree_p = xfs_da3_node_tree_p, .free_hdr_size = sizeof(struct xfs_dir3_free_hdr), .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir3_free_hdr_from_disk, .free_max_bests = xfs_dir3_free_max_bests, .free_bests_p = xfs_dir3_free_bests_p, .db_to_fdb = xfs_dir3_db_to_fdb, .db_to_fdindex = xfs_dir3_db_to_fdindex, }; static const struct xfs_dir_ops xfs_dir2_nondir_ops = { .node_hdr_size = sizeof(struct xfs_da_node_hdr), .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, }; static const struct xfs_dir_ops xfs_dir3_nondir_ops = { .node_hdr_size = sizeof(struct xfs_da3_node_hdr), .node_hdr_to_disk = xfs_da3_node_hdr_to_disk, .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, .node_tree_p = xfs_da3_node_tree_p, }; /* * Return the ops structure according to the current config. If we are passed * an inode, then that overrides the default config we use which is based on * feature bits. */ const struct xfs_dir_ops * xfs_dir_get_ops( struct xfs_mount *mp, struct xfs_inode *dp) { if (dp) return dp->d_ops; if (mp->m_dir_inode_ops) return mp->m_dir_inode_ops; if (xfs_sb_version_hascrc(&mp->m_sb)) return &xfs_dir3_ops; if (xfs_sb_version_hasftype(&mp->m_sb)) return &xfs_dir2_ftype_ops; return &xfs_dir2_ops; } const struct xfs_dir_ops * xfs_nondir_get_ops( struct xfs_mount *mp, struct xfs_inode *dp) { if (dp) return dp->d_ops; if (mp->m_nondir_inode_ops) return mp->m_nondir_inode_ops; if (xfs_sb_version_hascrc(&mp->m_sb)) return &xfs_dir3_nondir_ops; return &xfs_dir2_nondir_ops; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_da_format.h0000644000000000000000000007177713063067171016771 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_DA_FORMAT_H__ #define __XFS_DA_FORMAT_H__ /* * This structure is common to both leaf nodes and non-leaf nodes in the Btree. * * It is used to manage a doubly linked list of all blocks at the same * level in the Btree, and to identify which type of block this is. */ #define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ #define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ #define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ #define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ typedef struct xfs_da_blkinfo { __be32 forw; /* previous block in list */ __be32 back; /* following block in list */ __be16 magic; /* validity check on block */ __be16 pad; /* unused */ } xfs_da_blkinfo_t; /* * CRC enabled directory structure types * * The headers change size for the additional verification information, but * otherwise the tree layouts and contents are unchanged. Hence the da btree * code can use the struct xfs_da_blkinfo for manipulating the tree links and * magic numbers without modification for both v2 and v3 nodes. */ #define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */ #define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */ #define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */ #define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */ struct xfs_da3_blkinfo { /* * the node link manipulation code relies on the fact that the first * element of this structure is the struct xfs_da_blkinfo so it can * ignore the differences in the rest of the structures. */ struct xfs_da_blkinfo hdr; __be32 crc; /* CRC of block */ __be64 blkno; /* first block of the buffer */ __be64 lsn; /* sequence number of last write */ uuid_t uuid; /* filesystem we belong to */ __be64 owner; /* inode that owns the block */ }; /* * This is the structure of the root and intermediate nodes in the Btree. * The leaf nodes are defined above. * * Entries are not packed. * * Since we have duplicate keys, use a binary search but always follow * all match in the block, not just the first match found. */ #define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */ typedef struct xfs_da_node_hdr { struct xfs_da_blkinfo info; /* block type, links, etc. */ __be16 __count; /* count of active entries */ __be16 __level; /* level above leaves (leaf == 0) */ } xfs_da_node_hdr_t; struct xfs_da3_node_hdr { struct xfs_da3_blkinfo info; /* block type, links, etc. */ __be16 __count; /* count of active entries */ __be16 __level; /* level above leaves (leaf == 0) */ __be32 __pad32; }; #define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc)) typedef struct xfs_da_node_entry { __be32 hashval; /* hash value for this descendant */ __be32 before; /* Btree block before this key */ } xfs_da_node_entry_t; typedef struct xfs_da_intnode { struct xfs_da_node_hdr hdr; struct xfs_da_node_entry __btree[]; } xfs_da_intnode_t; struct xfs_da3_intnode { struct xfs_da3_node_hdr hdr; struct xfs_da_node_entry __btree[]; }; /* * In-core version of the node header to abstract the differences in the v2 and * v3 disk format of the headers. Callers need to convert to/from disk format as * appropriate. */ struct xfs_da3_icnode_hdr { __uint32_t forw; __uint32_t back; __uint16_t magic; __uint16_t count; __uint16_t level; }; /* * Directory version 2. * * There are 4 possible formats: * - shortform - embedded into the inode * - single block - data with embedded leaf at the end * - multiple data blocks, single leaf+freeindex block * - data blocks, node and leaf blocks (btree), freeindex blocks * * Note: many node blocks structures and constants are shared with the attr * code and defined in xfs_da_btree.h. */ #define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */ #define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */ #define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */ /* * Directory Version 3 With CRCs. * * The tree formats are the same as for version 2 directories. The difference * is in the block header and dirent formats. In many cases the v3 structures * use v2 definitions as they are no different and this makes code sharing much * easier. * * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the * format is v2 then they switch to the existing v2 code, or the format is v3 * they implement the v3 functionality. This means the existing dir2 is a mix of * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called * where there is a difference in the formats, otherwise the code is unchanged. * * Where it is possible, the code decides what to do based on the magic numbers * in the blocks rather than feature bits in the superblock. This means the code * is as independent of the external XFS code as possible as doesn't require * passing struct xfs_mount pointers into places where it isn't really * necessary. * * Version 3 includes: * * - a larger block header for CRC and identification purposes and so the * offsets of all the structures inside the blocks are different. * * - new magic numbers to be able to detect the v2/v3 types on the fly. */ #define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */ #define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */ #define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */ /* * Dirents in version 3 directories have a file type field. Additions to this * list are an on-disk format change, requiring feature bits. Valid values * are as follows: */ #define XFS_DIR3_FT_UNKNOWN 0 #define XFS_DIR3_FT_REG_FILE 1 #define XFS_DIR3_FT_DIR 2 #define XFS_DIR3_FT_CHRDEV 3 #define XFS_DIR3_FT_BLKDEV 4 #define XFS_DIR3_FT_FIFO 5 #define XFS_DIR3_FT_SOCK 6 #define XFS_DIR3_FT_SYMLINK 7 #define XFS_DIR3_FT_WHT 8 #define XFS_DIR3_FT_MAX 9 /* * Byte offset in data block and shortform entry. */ typedef __uint16_t xfs_dir2_data_off_t; #define NULLDATAOFF 0xffffU typedef uint xfs_dir2_data_aoff_t; /* argument form */ /* * Offset in data space of a data entry. */ typedef __uint32_t xfs_dir2_dataptr_t; #define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff) #define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0) /* * Byte offset in a directory. */ typedef xfs_off_t xfs_dir2_off_t; /* * Directory block number (logical dirblk in file) */ typedef __uint32_t xfs_dir2_db_t; #define XFS_INO32_SIZE 4 #define XFS_INO64_SIZE 8 #define XFS_INO64_DIFF (XFS_INO64_SIZE - XFS_INO32_SIZE) #define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL) /* * Directory layout when stored internal to an inode. * * Small directories are packed as tightly as possible so as to fit into the * literal area of the inode. These "shortform" directories consist of a * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry * structures. Due the different inode number storage size and the variable * length name field in the xfs_dir2_sf_entry all these structure are * variable length, and the accessors in this file should be used to iterate * over them. */ typedef struct xfs_dir2_sf_hdr { __uint8_t count; /* count of entries */ __uint8_t i8count; /* count of 8-byte inode #s */ __uint8_t parent[8]; /* parent dir inode number */ } __packed xfs_dir2_sf_hdr_t; typedef struct xfs_dir2_sf_entry { __u8 namelen; /* actual name length */ __u8 offset[2]; /* saved offset */ __u8 name[]; /* name, variable size */ /* * A single byte containing the file type field follows the inode * number for version 3 directory entries. * * A 64-bit or 32-bit inode number follows here, at a variable offset * after the name. */ } xfs_dir2_sf_entry_t; static inline int xfs_dir2_sf_hdr_size(int i8count) { return sizeof(struct xfs_dir2_sf_hdr) - (i8count == 0) * XFS_INO64_DIFF; } static inline xfs_dir2_data_aoff_t xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) { return get_unaligned_be16(sfep->offset); } static inline void xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) { put_unaligned_be16(off, sfep->offset); } static inline struct xfs_dir2_sf_entry * xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) { return (struct xfs_dir2_sf_entry *) ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); } /* * Data block structures. * * A pure data block looks like the following drawing on disk: * * +-------------------------------------------------+ * | xfs_dir2_data_hdr_t | * +-------------------------------------------------+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | * | ... | * +-------------------------------------------------+ * | unused space | * +-------------------------------------------------+ * * As all the entries are variable size structures the accessors below should * be used to iterate over them. * * In addition to the pure data blocks for the data and node formats, * most structures are also used for the combined data/freespace "block" * format below. */ #define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ #define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG) #define XFS_DIR2_DATA_FREE_TAG 0xffff #define XFS_DIR2_DATA_FD_COUNT 3 /* * Directory address space divided into sections, * spaces separated by 32GB. */ #define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) #define XFS_DIR2_DATA_SPACE 0 #define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) /* * Describe a free area in the data block. * * The freespace will be formatted as a xfs_dir2_data_unused_t. */ typedef struct xfs_dir2_data_free { __be16 offset; /* start of freespace */ __be16 length; /* length of freespace */ } xfs_dir2_data_free_t; /* * Header for the data blocks. * * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. */ typedef struct xfs_dir2_data_hdr { __be32 magic; /* XFS_DIR2_DATA_MAGIC or */ /* XFS_DIR2_BLOCK_MAGIC */ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; } xfs_dir2_data_hdr_t; /* * define a structure for all the verification fields we are adding to the * directory block structures. This will be used in several structures. * The magic number must be the first entry to align with all the dir2 * structures so we determine how to decode them just by the magic number. */ struct xfs_dir3_blk_hdr { __be32 magic; /* magic number */ __be32 crc; /* CRC of block */ __be64 blkno; /* first block of the buffer */ __be64 lsn; /* sequence number of last write */ uuid_t uuid; /* filesystem we belong to */ __be64 owner; /* inode that owns the block */ }; struct xfs_dir3_data_hdr { struct xfs_dir3_blk_hdr hdr; xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT]; __be32 pad; /* 64 bit alignment */ }; #define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) /* * Active entry in a data block. * * Aligned to 8 bytes. After the variable length name field there is a * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p. * * For dir3 structures, there is file type field between the name and the tag. * This can only be manipulated by helper functions. It is packed hard against * the end of the name so any padding for rounding is between the file type and * the tag. */ typedef struct xfs_dir2_data_entry { __be64 inumber; /* inode number */ __u8 namelen; /* name length */ __u8 name[]; /* name bytes, no null */ /* __u8 filetype; */ /* type of inode we point to */ /* __be16 tag; */ /* starting offset of us */ } xfs_dir2_data_entry_t; /* * Unused entry in a data block. * * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed * using xfs_dir2_data_unused_tag_p. */ typedef struct xfs_dir2_data_unused { __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */ __be16 length; /* total free length */ /* variable offset */ __be16 tag; /* starting offset of us */ } xfs_dir2_data_unused_t; /* * Pointer to a freespace's tag word. */ static inline __be16 * xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) { return (__be16 *)((char *)dup + be16_to_cpu(dup->length) - sizeof(__be16)); } /* * Leaf block structures. * * A pure leaf block looks like the following drawing on disk: * * +---------------------------+ * | xfs_dir2_leaf_hdr_t | * +---------------------------+ * | xfs_dir2_leaf_entry_t | * | xfs_dir2_leaf_entry_t | * | xfs_dir2_leaf_entry_t | * | xfs_dir2_leaf_entry_t | * | ... | * +---------------------------+ * | xfs_dir2_data_off_t | * | xfs_dir2_data_off_t | * | xfs_dir2_data_off_t | * | ... | * +---------------------------+ * | xfs_dir2_leaf_tail_t | * +---------------------------+ * * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present * for directories with separate leaf nodes and free space blocks * (magic = XFS_DIR2_LEAFN_MAGIC). * * As all the entries are variable size structures the accessors below should * be used to iterate over them. */ /* * Offset of the leaf/node space. First block in this space * is the btree root. */ #define XFS_DIR2_LEAF_SPACE 1 #define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) /* * Leaf block header. */ typedef struct xfs_dir2_leaf_hdr { xfs_da_blkinfo_t info; /* header for da routines */ __be16 count; /* count of entries */ __be16 stale; /* count of stale entries */ } xfs_dir2_leaf_hdr_t; struct xfs_dir3_leaf_hdr { struct xfs_da3_blkinfo info; /* header for da routines */ __be16 count; /* count of entries */ __be16 stale; /* count of stale entries */ __be32 pad; /* 64 bit alignment */ }; struct xfs_dir3_icleaf_hdr { __uint32_t forw; __uint32_t back; __uint16_t magic; __uint16_t count; __uint16_t stale; }; /* * Leaf block entry. */ typedef struct xfs_dir2_leaf_entry { __be32 hashval; /* hash value of name */ __be32 address; /* address of data entry */ } xfs_dir2_leaf_entry_t; /* * Leaf block tail. */ typedef struct xfs_dir2_leaf_tail { __be32 bestcount; } xfs_dir2_leaf_tail_t; /* * Leaf block. */ typedef struct xfs_dir2_leaf { xfs_dir2_leaf_hdr_t hdr; /* leaf header */ xfs_dir2_leaf_entry_t __ents[]; /* entries */ } xfs_dir2_leaf_t; struct xfs_dir3_leaf { struct xfs_dir3_leaf_hdr hdr; /* leaf header */ struct xfs_dir2_leaf_entry __ents[]; /* entries */ }; #define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) /* * Get address of the bests array in the single-leaf block. */ static inline __be16 * xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) { return (__be16 *)ltp - be32_to_cpu(ltp->bestcount); } /* * Free space block defintions for the node format. */ /* * Offset of the freespace index. */ #define XFS_DIR2_FREE_SPACE 2 #define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) typedef struct xfs_dir2_free_hdr { __be32 magic; /* XFS_DIR2_FREE_MAGIC */ __be32 firstdb; /* db of first entry */ __be32 nvalid; /* count of valid entries */ __be32 nused; /* count of used entries */ } xfs_dir2_free_hdr_t; typedef struct xfs_dir2_free { xfs_dir2_free_hdr_t hdr; /* block header */ __be16 bests[]; /* best free counts */ /* unused entries are -1 */ } xfs_dir2_free_t; struct xfs_dir3_free_hdr { struct xfs_dir3_blk_hdr hdr; __be32 firstdb; /* db of first entry */ __be32 nvalid; /* count of valid entries */ __be32 nused; /* count of used entries */ __be32 pad; /* 64 bit alignment */ }; struct xfs_dir3_free { struct xfs_dir3_free_hdr hdr; __be16 bests[]; /* best free counts */ /* unused entries are -1 */ }; #define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc) /* * In core version of the free block header, abstracted away from on-disk format * differences. Use this in the code, and convert to/from the disk version using * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk. */ struct xfs_dir3_icfree_hdr { __uint32_t magic; __uint32_t firstdb; __uint32_t nvalid; __uint32_t nused; }; /* * Single block format. * * The single block format looks like the following drawing on disk: * * +-------------------------------------------------+ * | xfs_dir2_data_hdr_t | * +-------------------------------------------------+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t : * | ... | * +-------------------------------------------------+ * | unused space | * +-------------------------------------------------+ * | ... | * | xfs_dir2_leaf_entry_t | * | xfs_dir2_leaf_entry_t | * +-------------------------------------------------+ * | xfs_dir2_block_tail_t | * +-------------------------------------------------+ * * As all the entries are variable size structures the accessors below should * be used to iterate over them. */ typedef struct xfs_dir2_block_tail { __be32 count; /* count of leaf entries */ __be32 stale; /* count of stale lf entries */ } xfs_dir2_block_tail_t; /* * Pointer to the leaf entries embedded in a data block (1-block format) */ static inline struct xfs_dir2_leaf_entry * xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp) { return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); } /* * Attribute storage layout * * Attribute lists are structured around Btrees where all the data * elements are in the leaf nodes. Attribute names are hashed into an int, * then that int is used as the index into the Btree. Since the hashval * of an attribute name may not be unique, we may have duplicate keys. The * internal links in the Btree are logical block offsets into the file. * * Struct leaf_entry's are packed from the top. Name/values grow from the * bottom but are not packed. The freemap contains run-length-encoded entries * for the free bytes after the leaf_entry's, but only the N largest such, * smaller runs are dropped. When the freemap doesn't show enough space * for an allocation, we compact the name/value area and try again. If we * still don't have enough space, then we have to split the block. The * name/value structs (both local and remote versions) must be 32bit aligned. * * Since we have duplicate hash keys, for each key that matches, compare * the actual name string. The root and intermediate node search always * takes the first-in-the-block key match found, so we should only have * to work "forw"ard. If none matches, continue with the "forw"ard leaf * nodes until the hash key changes or the attribute name is found. * * We store the fact that an attribute is a ROOT/USER/SECURE attribute in * the leaf_entry. The namespaces are independent only because we also look * at the namespace bit when we are looking for a matching attribute name. * * We also store an "incomplete" bit in the leaf_entry. It shows that an * attribute is in the middle of being created and should not be shown to * the user if we crash during the time that the bit is set. We clear the * bit when we have finished setting up the attribute. We do this because * we cannot create some large attributes inside a single transaction, and we * need some indication that we weren't finished if we crash in the middle. */ #define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */ /* * Entries are packed toward the top as tight as possible. */ typedef struct xfs_attr_shortform { struct xfs_attr_sf_hdr { /* constant-structure header block */ __be16 totsize; /* total bytes in shortform list */ __u8 count; /* count of active entries */ __u8 padding; } hdr; struct xfs_attr_sf_entry { __uint8_t namelen; /* actual length of name (no NULL) */ __uint8_t valuelen; /* actual length of value (no NULL) */ __uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */ __uint8_t nameval[1]; /* name & value bytes concatenated */ } list[1]; /* variable sized array */ } xfs_attr_shortform_t; typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */ __be16 base; /* base of free region */ __be16 size; /* length of free region */ } xfs_attr_leaf_map_t; typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */ xfs_da_blkinfo_t info; /* block type, links, etc. */ __be16 count; /* count of active leaf_entry's */ __be16 usedbytes; /* num bytes of names/values stored */ __be16 firstused; /* first used byte in name area */ __u8 holes; /* != 0 if blk needs compaction */ __u8 pad1; xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE]; /* N largest free regions */ } xfs_attr_leaf_hdr_t; typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */ __be32 hashval; /* hash value of name */ __be16 nameidx; /* index into buffer of name/value */ __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ __u8 pad2; /* unused pad byte */ } xfs_attr_leaf_entry_t; typedef struct xfs_attr_leaf_name_local { __be16 valuelen; /* number of bytes in value */ __u8 namelen; /* length of name bytes */ __u8 nameval[1]; /* name/value bytes */ } xfs_attr_leaf_name_local_t; typedef struct xfs_attr_leaf_name_remote { __be32 valueblk; /* block number of value bytes */ __be32 valuelen; /* number of bytes in value */ __u8 namelen; /* length of name bytes */ __u8 name[1]; /* name bytes */ } xfs_attr_leaf_name_remote_t; typedef struct xfs_attr_leafblock { xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */ xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */ /* * The rest of the block contains the following structures after the * leaf entries, growing from the bottom up. The variables are never * referenced and definining them can actually make gcc optimize away * accesses to the 'entries' array above index 0 so don't do that. * * xfs_attr_leaf_name_local_t namelist; * xfs_attr_leaf_name_remote_t valuelist; */ } xfs_attr_leafblock_t; /* * CRC enabled leaf structures. Called "version 3" structures to match the * version number of the directory and dablk structures for this feature, and * attr2 is already taken by the variable inode attribute fork size feature. */ struct xfs_attr3_leaf_hdr { struct xfs_da3_blkinfo info; __be16 count; __be16 usedbytes; __be16 firstused; __u8 holes; __u8 pad1; struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE]; __be32 pad2; /* 64 bit alignment */ }; #define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc)) struct xfs_attr3_leafblock { struct xfs_attr3_leaf_hdr hdr; struct xfs_attr_leaf_entry entries[1]; /* * The rest of the block contains the following structures after the * leaf entries, growing from the bottom up. The variables are never * referenced, the locations accessed purely from helper functions. * * struct xfs_attr_leaf_name_local * struct xfs_attr_leaf_name_remote */ }; /* * incore, neutral version of the attribute leaf header */ struct xfs_attr3_icleaf_hdr { __uint32_t forw; __uint32_t back; __uint16_t magic; __uint16_t count; __uint16_t usedbytes; /* * firstused is 32-bit here instead of 16-bit like the on-disk variant * to support maximum fsb size of 64k without overflow issues throughout * the attr code. Instead, the overflow condition is handled on * conversion to/from disk. */ __uint32_t firstused; __u8 holes; struct { __uint16_t base; __uint16_t size; } freemap[XFS_ATTR_LEAF_MAPSIZE]; }; /* * Special value to represent fs block size in the leaf header firstused field. * Only used when block size overflows the 2-bytes available on disk. */ #define XFS_ATTR3_LEAF_NULLOFF 0 /* * Flags used in the leaf_entry[i].flags field. * NOTE: the INCOMPLETE bit must not collide with the flags bits specified * on the system call, they are "or"ed together for various operations. */ #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ #define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ #define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ #define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) #define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) #define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) /* * Conversion macros for converting namespace bits from argument flags * to ondisk flags. */ #define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE) #define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE) #define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK) #define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK) #define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\ ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0)) #define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\ ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0)) /* * Alignment for namelist and valuelist entries (since they are mixed * there can be only one alignment value) */ #define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t)) static inline int xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp) { if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) return sizeof(struct xfs_attr3_leaf_hdr); return sizeof(struct xfs_attr_leaf_hdr); } static inline struct xfs_attr_leaf_entry * xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp) { if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) return &((struct xfs_attr3_leafblock *)leafp)->entries[0]; return &leafp->entries[0]; } /* * Cast typed pointers for "local" and "remote" name/value structs. */ static inline char * xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx) { struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp); return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)]; } static inline xfs_attr_leaf_name_remote_t * xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx) { return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx); } static inline xfs_attr_leaf_name_local_t * xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx) { return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx); } /* * Calculate total bytes used (including trailing pad for alignment) for * a "local" name/value structure, a "remote" name/value structure, and * a pointer which might be either. */ static inline int xfs_attr_leaf_entsize_remote(int nlen) { return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \ XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); } static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen) { return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) + XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); } static inline int xfs_attr_leaf_entsize_local_max(int bsize) { return (((bsize) >> 1) + ((bsize) >> 2)); } /* * Remote attribute block format definition * * There is one of these headers per filesystem block in a remote attribute. * This is done to ensure there is a 1:1 mapping between the attribute value * length and the number of blocks needed to store the attribute. This makes the * verification of a buffer a little more complex, but greatly simplifies the * allocation, reading and writing of these attributes as we don't have to guess * the number of blocks needed to store the attribute data. */ #define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */ struct xfs_attr3_rmt_hdr { __be32 rm_magic; __be32 rm_offset; __be32 rm_bytes; __be32 rm_crc; uuid_t rm_uuid; __be64 rm_owner; __be64 rm_blkno; __be64 rm_lsn; }; #define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc) #define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \ ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ sizeof(struct xfs_attr3_rmt_hdr) : 0)) #endif /* __XFS_DA_FORMAT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_defer.c0000644000000000000000000004115013033541503016064 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_trans.h" #include "xfs_trace.h" /* * Deferred Operations in XFS * * Due to the way locking rules work in XFS, certain transactions (block * mapping and unmapping, typically) have permanent reservations so that * we can roll the transaction to adhere to AG locking order rules and * to unlock buffers between metadata updates. Prior to rmap/reflink, * the mapping code had a mechanism to perform these deferrals for * extents that were going to be freed; this code makes that facility * more generic. * * When adding the reverse mapping and reflink features, it became * necessary to perform complex remapping multi-transactions to comply * with AG locking order rules, and to be able to spread a single * refcount update operation (an operation on an n-block extent can * update as many as n records!) among multiple transactions. XFS can * roll a transaction to facilitate this, but using this facility * requires us to log "intent" items in case log recovery needs to * redo the operation, and to log "done" items to indicate that redo * is not necessary. * * Deferred work is tracked in xfs_defer_pending items. Each pending * item tracks one type of deferred work. Incoming work items (which * have not yet had an intent logged) are attached to a pending item * on the dop_intake list, where they wait for the caller to finish * the deferred operations. * * Finishing a set of deferred operations is an involved process. To * start, we define "rolling a deferred-op transaction" as follows: * * > For each xfs_defer_pending item on the dop_intake list, * - Sort the work items in AG order. XFS locking * order rules require us to lock buffers in AG order. * - Create a log intent item for that type. * - Attach it to the pending item. * - Move the pending item from the dop_intake list to the * dop_pending list. * > Roll the transaction. * * NOTE: To avoid exceeding the transaction reservation, we limit the * number of items that we attach to a given xfs_defer_pending. * * The actual finishing process looks like this: * * > For each xfs_defer_pending in the dop_pending list, * - Roll the deferred-op transaction as above. * - Create a log done item for that type, and attach it to the * log intent item. * - For each work item attached to the log intent item, * * Perform the described action. * * Attach the work item to the log done item. * * If the result of doing the work was -EAGAIN, ->finish work * wants a new transaction. See the "Requesting a Fresh * Transaction while Finishing Deferred Work" section below for * details. * * The key here is that we must log an intent item for all pending * work items every time we roll the transaction, and that we must log * a done item as soon as the work is completed. With this mechanism * we can perform complex remapping operations, chaining intent items * as needed. * * Requesting a Fresh Transaction while Finishing Deferred Work * * If ->finish_item decides that it needs a fresh transaction to * finish the work, it must ask its caller (xfs_defer_finish) for a * continuation. The most likely cause of this circumstance are the * refcount adjust functions deciding that they've logged enough items * to be at risk of exceeding the transaction reservation. * * To get a fresh transaction, we want to log the existing log done * item to prevent the log intent item from replaying, immediately log * a new log intent item with the unfinished work items, roll the * transaction, and re-call ->finish_item wherever it left off. The * log done item and the new log intent item must be in the same * transaction or atomicity cannot be guaranteed; defer_finish ensures * that this happens. * * This requires some coordination between ->finish_item and * defer_finish. Upon deciding to request a new transaction, * ->finish_item should update the current work item to reflect the * unfinished work. Next, it should reset the log done item's list * count to the number of items finished, and return -EAGAIN. * defer_finish sees the -EAGAIN, logs the new log intent item * with the remaining work items, and leaves the xfs_defer_pending * item at the head of the dop_work queue. Then it rolls the * transaction and picks up processing where it left off. It is * required that ->finish_item must be careful to leave enough * transaction reservation to fit the new log intent item. * * This is an example of remapping the extent (E, E+B) into file X at * offset A and dealing with the extent (C, C+B) already being mapped * there: * +-------------------------------------------------+ * | Unmap file X startblock C offset A length B | t0 * | Intent to reduce refcount for extent (C, B) | * | Intent to remove rmap (X, C, A, B) | * | Intent to free extent (D, 1) (bmbt block) | * | Intent to map (X, A, B) at startblock E | * +-------------------------------------------------+ * | Map file X startblock E offset A length B | t1 * | Done mapping (X, E, A, B) | * | Intent to increase refcount for extent (E, B) | * | Intent to add rmap (X, E, A, B) | * +-------------------------------------------------+ * | Reduce refcount for extent (C, B) | t2 * | Done reducing refcount for extent (C, 9) | * | Intent to reduce refcount for extent (C+9, B-9) | * | (ran out of space after 9 refcount updates) | * +-------------------------------------------------+ * | Reduce refcount for extent (C+9, B+9) | t3 * | Done reducing refcount for extent (C+9, B-9) | * | Increase refcount for extent (E, B) | * | Done increasing refcount for extent (E, B) | * | Intent to free extent (C, B) | * | Intent to free extent (F, 1) (refcountbt block) | * | Intent to remove rmap (F, 1, REFC) | * +-------------------------------------------------+ * | Remove rmap (X, C, A, B) | t4 * | Done removing rmap (X, C, A, B) | * | Add rmap (X, E, A, B) | * | Done adding rmap (X, E, A, B) | * | Remove rmap (F, 1, REFC) | * | Done removing rmap (F, 1, REFC) | * +-------------------------------------------------+ * | Free extent (C, B) | t5 * | Done freeing extent (C, B) | * | Free extent (D, 1) | * | Done freeing extent (D, 1) | * | Free extent (F, 1) | * | Done freeing extent (F, 1) | * +-------------------------------------------------+ * * If we should crash before t2 commits, log recovery replays * the following intent items: * * - Intent to reduce refcount for extent (C, B) * - Intent to remove rmap (X, C, A, B) * - Intent to free extent (D, 1) (bmbt block) * - Intent to increase refcount for extent (E, B) * - Intent to add rmap (X, E, A, B) * * In the process of recovering, it should also generate and take care * of these intent items: * * - Intent to free extent (C, B) * - Intent to free extent (F, 1) (refcountbt block) * - Intent to remove rmap (F, 1, REFC) * * Note that the continuation requested between t2 and t3 is likely to * reoccur. */ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; /* * For each pending item in the intake list, log its intent item and the * associated extents, then add the entire intake list to the end of * the pending list. */ STATIC void xfs_defer_intake_work( struct xfs_trans *tp, struct xfs_defer_ops *dop) { struct list_head *li; struct xfs_defer_pending *dfp; list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { dfp->dfp_intent = dfp->dfp_type->create_intent(tp, dfp->dfp_count); trace_xfs_defer_intake_work(tp->t_mountp, dfp); list_sort(tp->t_mountp, &dfp->dfp_work, dfp->dfp_type->diff_items); list_for_each(li, &dfp->dfp_work) dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); } list_splice_tail_init(&dop->dop_intake, &dop->dop_pending); } /* Abort all the intents that were committed. */ STATIC void xfs_defer_trans_abort( struct xfs_trans *tp, struct xfs_defer_ops *dop, int error) { struct xfs_defer_pending *dfp; trace_xfs_defer_trans_abort(tp->t_mountp, dop); /* Abort intent items that don't have a done item. */ list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { trace_xfs_defer_pending_abort(tp->t_mountp, dfp); if (dfp->dfp_intent && !dfp->dfp_done) { dfp->dfp_type->abort_intent(dfp->dfp_intent); dfp->dfp_intent = NULL; } } /* Shut down FS. */ xfs_force_shutdown(tp->t_mountp, (error == -EFSCORRUPTED) ? SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR); } /* Roll a transaction so we can do some deferred op processing. */ STATIC int xfs_defer_trans_roll( struct xfs_trans **tp, struct xfs_defer_ops *dop, struct xfs_inode *ip) { int i; int error; /* Log all the joined inodes except the one we passed in. */ for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { if (dop->dop_inodes[i] == ip) continue; xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); } trace_xfs_defer_trans_roll((*tp)->t_mountp, dop); /* Roll the transaction. */ error = xfs_trans_roll(tp, ip); if (error) { trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error); xfs_defer_trans_abort(*tp, dop, error); return error; } dop->dop_committed = true; /* Rejoin the joined inodes except the one we passed in. */ for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { if (dop->dop_inodes[i] == ip) continue; xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); } return error; } /* Do we have any work items to finish? */ bool xfs_defer_has_unfinished_work( struct xfs_defer_ops *dop) { return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake); } /* * Add this inode to the deferred op. Each joined inode is relogged * each time we roll the transaction, in addition to any inode passed * to xfs_defer_finish(). */ int xfs_defer_join( struct xfs_defer_ops *dop, struct xfs_inode *ip) { int i; for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) { if (dop->dop_inodes[i] == ip) return 0; else if (dop->dop_inodes[i] == NULL) { dop->dop_inodes[i] = ip; return 0; } } return -EFSCORRUPTED; } /* * Finish all the pending work. This involves logging intent items for * any work items that wandered in since the last transaction roll (if * one has even happened), rolling the transaction, and finishing the * work items in the first item on the logged-and-pending list. * * If an inode is provided, relog it to the new transaction. */ int xfs_defer_finish( struct xfs_trans **tp, struct xfs_defer_ops *dop, struct xfs_inode *ip) { struct xfs_defer_pending *dfp; struct list_head *li; struct list_head *n; void *state; int error = 0; void (*cleanup_fn)(struct xfs_trans *, void *, int); ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); trace_xfs_defer_finish((*tp)->t_mountp, dop); /* Until we run out of pending work to finish... */ while (xfs_defer_has_unfinished_work(dop)) { /* Log intents for work items sitting in the intake. */ xfs_defer_intake_work(*tp, dop); /* Roll the transaction. */ error = xfs_defer_trans_roll(tp, dop, ip); if (error) goto out; /* Log an intent-done item for the first pending item. */ dfp = list_first_entry(&dop->dop_pending, struct xfs_defer_pending, dfp_list); trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, dfp->dfp_count); cleanup_fn = dfp->dfp_type->finish_cleanup; /* Finish the work items. */ state = NULL; list_for_each_safe(li, n, &dfp->dfp_work) { list_del(li); dfp->dfp_count--; error = dfp->dfp_type->finish_item(*tp, dop, li, dfp->dfp_done, &state); if (error == -EAGAIN) { /* * Caller wants a fresh transaction; * put the work item back on the list * and jump out. */ list_add(li, &dfp->dfp_work); dfp->dfp_count++; break; } else if (error) { /* * Clean up after ourselves and jump out. * xfs_defer_cancel will take care of freeing * all these lists and stuff. */ if (cleanup_fn) cleanup_fn(*tp, state, error); xfs_defer_trans_abort(*tp, dop, error); goto out; } } if (error == -EAGAIN) { /* * Caller wants a fresh transaction, so log a * new log intent item to replace the old one * and roll the transaction. See "Requesting * a Fresh Transaction while Finishing * Deferred Work" above. */ dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, dfp->dfp_count); dfp->dfp_done = NULL; list_for_each(li, &dfp->dfp_work) dfp->dfp_type->log_item(*tp, dfp->dfp_intent, li); } else { /* Done with the dfp, free it. */ list_del(&dfp->dfp_list); kmem_free(dfp); } if (cleanup_fn) cleanup_fn(*tp, state, error); } out: if (error) trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); else trace_xfs_defer_finish_done((*tp)->t_mountp, dop); return error; } /* * Free up any items left in the list. */ void xfs_defer_cancel( struct xfs_defer_ops *dop) { struct xfs_defer_pending *dfp; struct xfs_defer_pending *pli; struct list_head *pwi; struct list_head *n; trace_xfs_defer_cancel(NULL, dop); /* * Free the pending items. Caller should already have arranged * for the intent items to be released. */ list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { trace_xfs_defer_intake_cancel(NULL, dfp); list_del(&dfp->dfp_list); list_for_each_safe(pwi, n, &dfp->dfp_work) { list_del(pwi); dfp->dfp_count--; dfp->dfp_type->cancel_item(pwi); } ASSERT(dfp->dfp_count == 0); kmem_free(dfp); } list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { trace_xfs_defer_pending_cancel(NULL, dfp); list_del(&dfp->dfp_list); list_for_each_safe(pwi, n, &dfp->dfp_work) { list_del(pwi); dfp->dfp_count--; dfp->dfp_type->cancel_item(pwi); } ASSERT(dfp->dfp_count == 0); kmem_free(dfp); } } /* Add an item for later deferred processing. */ void xfs_defer_add( struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *li) { struct xfs_defer_pending *dfp = NULL; /* * Add the item to a pending item at the end of the intake list. * If the last pending item has the same type, reuse it. Else, * create a new pending item at the end of the intake list. */ if (!list_empty(&dop->dop_intake)) { dfp = list_last_entry(&dop->dop_intake, struct xfs_defer_pending, dfp_list); if (dfp->dfp_type->type != type || (dfp->dfp_type->max_items && dfp->dfp_count >= dfp->dfp_type->max_items)) dfp = NULL; } if (!dfp) { dfp = kmem_alloc(sizeof(struct xfs_defer_pending), KM_SLEEP | KM_NOFS); dfp->dfp_type = defer_op_types[type]; dfp->dfp_intent = NULL; dfp->dfp_done = NULL; dfp->dfp_count = 0; INIT_LIST_HEAD(&dfp->dfp_work); list_add_tail(&dfp->dfp_list, &dop->dop_intake); } list_add_tail(li, &dfp->dfp_work); dfp->dfp_count++; } /* Initialize a deferred operation list. */ void xfs_defer_init_op_type( const struct xfs_defer_op_type *type) { defer_op_types[type->type] = type; } /* Initialize a deferred operation. */ void xfs_defer_init( struct xfs_defer_ops *dop, xfs_fsblock_t *fbp) { dop->dop_committed = false; dop->dop_low = false; memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); *fbp = NULLFSBLOCK; INIT_LIST_HEAD(&dop->dop_intake); INIT_LIST_HEAD(&dop->dop_pending); trace_xfs_defer_init(NULL, dop); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_defer.h0000644000000000000000000000741213033541503016074 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __XFS_DEFER_H__ #define __XFS_DEFER_H__ struct xfs_defer_op_type; /* * Save a log intent item and a list of extents, so that we can replay * whatever action had to happen to the extent list and file the log done * item. */ struct xfs_defer_pending { const struct xfs_defer_op_type *dfp_type; /* function pointers */ struct list_head dfp_list; /* pending items */ void *dfp_intent; /* log intent item */ void *dfp_done; /* log done item */ struct list_head dfp_work; /* work items */ unsigned int dfp_count; /* # extent items */ }; /* * Header for deferred operation list. * * dop_low is used by the allocator to activate the lowspace algorithm - * when free space is running low the extent allocator may choose to * allocate an extent from an AG without leaving sufficient space for * a btree split when inserting the new extent. In this case the allocator * will enable the lowspace algorithm which is supposed to allow further * allocations (such as btree splits and newroots) to allocate from * sequential AGs. In order to avoid locking AGs out of order the lowspace * algorithm will start searching for free space from AG 0. If the correct * transaction reservations have been made then this algorithm will eventually * find all the space it needs. */ enum xfs_defer_ops_type { XFS_DEFER_OPS_TYPE_BMAP, XFS_DEFER_OPS_TYPE_REFCOUNT, XFS_DEFER_OPS_TYPE_RMAP, XFS_DEFER_OPS_TYPE_FREE, XFS_DEFER_OPS_TYPE_MAX, }; #define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ struct xfs_defer_ops { bool dop_committed; /* did any trans commit? */ bool dop_low; /* alloc in low mode */ struct list_head dop_intake; /* unlogged pending work */ struct list_head dop_pending; /* logged pending work */ /* relog these inodes with each roll */ struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; }; void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop, struct xfs_inode *ip); void xfs_defer_cancel(struct xfs_defer_ops *dop); void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip); /* Description of a deferred type. */ struct xfs_defer_op_type { enum xfs_defer_ops_type type; unsigned int max_items; void (*abort_intent)(void *); void *(*create_done)(struct xfs_trans *, void *, unsigned int); int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, struct list_head *, void *, void **); void (*finish_cleanup)(struct xfs_trans *, void *, int); void (*cancel_item)(struct list_head *); int (*diff_items)(void *, struct list_head *, struct list_head *); void *(*create_intent)(struct xfs_trans *, uint); void (*log_item)(struct xfs_trans *, void *, struct list_head *); }; void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); #endif /* __XFS_DEFER_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2.c0000644000000000000000000004327313063067171015656 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trace.h" struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; /* * @mode, if set, indicates that the type field needs to be set up. * This uses the transformation from file mode to DT_* as defined in linux/fs.h * for file type specification. This will be propagated into the directory * structure if appropriate for the given operation and filesystem config. */ const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = { [0] = XFS_DIR3_FT_UNKNOWN, [S_IFREG >> S_SHIFT] = XFS_DIR3_FT_REG_FILE, [S_IFDIR >> S_SHIFT] = XFS_DIR3_FT_DIR, [S_IFCHR >> S_SHIFT] = XFS_DIR3_FT_CHRDEV, [S_IFBLK >> S_SHIFT] = XFS_DIR3_FT_BLKDEV, [S_IFIFO >> S_SHIFT] = XFS_DIR3_FT_FIFO, [S_IFSOCK >> S_SHIFT] = XFS_DIR3_FT_SOCK, [S_IFLNK >> S_SHIFT] = XFS_DIR3_FT_SYMLINK, }; /* * ASCII case-insensitive (ie. A-Z) support for directories that was * used in IRIX. */ STATIC xfs_dahash_t xfs_ascii_ci_hashname( struct xfs_name *name) { xfs_dahash_t hash; int i; for (i = 0, hash = 0; i < name->len; i++) hash = tolower(name->name[i]) ^ rol32(hash, 7); return hash; } STATIC enum xfs_dacmp xfs_ascii_ci_compname( struct xfs_da_args *args, const unsigned char *name, int len) { enum xfs_dacmp result; int i; if (args->namelen != len) return XFS_CMP_DIFFERENT; result = XFS_CMP_EXACT; for (i = 0; i < len; i++) { if (args->name[i] == name[i]) continue; if (tolower(args->name[i]) != tolower(name[i])) return XFS_CMP_DIFFERENT; result = XFS_CMP_CASE; } return result; } static struct xfs_nameops xfs_ascii_ci_nameops = { .hashname = xfs_ascii_ci_hashname, .compname = xfs_ascii_ci_compname, }; int xfs_da_mount( struct xfs_mount *mp) { struct xfs_da_geometry *dageo; int nodehdr_size; ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT); ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= XFS_MAX_BLOCKSIZE); mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), KM_SLEEP | KM_MAYFAIL); mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), KM_SLEEP | KM_MAYFAIL); if (!mp->m_dir_geo || !mp->m_attr_geo) { kmem_free(mp->m_dir_geo); kmem_free(mp->m_attr_geo); return -ENOMEM; } /* set up directory geometry */ dageo = mp->m_dir_geo; dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog; dageo->fsblog = mp->m_sb.sb_blocklog; dageo->blksize = 1 << dageo->blklog; dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog; /* * Now we've set up the block conversion variables, we can calculate the * segment block constants using the geometry structure. */ dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET); dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET); dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET); dageo->node_ents = (dageo->blksize - nodehdr_size) / (uint)sizeof(xfs_da_node_entry_t); dageo->magicpct = (dageo->blksize * 37) / 100; /* set up attribute geometry - single fsb only */ dageo = mp->m_attr_geo; dageo->blklog = mp->m_sb.sb_blocklog; dageo->fsblog = mp->m_sb.sb_blocklog; dageo->blksize = 1 << dageo->blklog; dageo->fsbcount = 1; dageo->node_ents = (dageo->blksize - nodehdr_size) / (uint)sizeof(xfs_da_node_entry_t); dageo->magicpct = (dageo->blksize * 37) / 100; if (xfs_sb_version_hasasciici(&mp->m_sb)) mp->m_dirnameops = &xfs_ascii_ci_nameops; else mp->m_dirnameops = &xfs_default_nameops; return 0; } void xfs_da_unmount( struct xfs_mount *mp) { kmem_free(mp->m_dir_geo); kmem_free(mp->m_attr_geo); } /* * Return 1 if directory contains only "." and "..". */ int xfs_dir_isempty( xfs_inode_t *dp) { xfs_dir2_sf_hdr_t *sfp; ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); if (dp->i_d.di_size == 0) /* might happen during shutdown. */ return 1; if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) return 0; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; return !sfp->count; } /* * Validate a given inode number. */ int xfs_dir_ino_validate( xfs_mount_t *mp, xfs_ino_t ino) { xfs_agblock_t agblkno; xfs_agino_t agino; xfs_agnumber_t agno; int ino_ok; int ioff; agno = XFS_INO_TO_AGNO(mp, ino); agblkno = XFS_INO_TO_AGBNO(mp, ino); ioff = XFS_INO_TO_OFFSET(mp, ino); agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); ino_ok = agno < mp->m_sb.sb_agcount && agblkno < mp->m_sb.sb_agblocks && agblkno != 0 && ioff < (1 << mp->m_sb.sb_inopblog) && XFS_AGINO_TO_INO(mp, agno, agino) == ino; if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, XFS_RANDOM_DIR_INO_VALIDATE))) { xfs_warn(mp, "Invalid inode number 0x%Lx", (unsigned long long) ino); XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } return 0; } /* * Initialize a directory with its "." and ".." entries. */ int xfs_dir_init( xfs_trans_t *tp, xfs_inode_t *dp, xfs_inode_t *pdp) { struct xfs_da_args *args; int error; ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino); if (error) return error; args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); if (!args) return -ENOMEM; args->geo = dp->i_mount->m_dir_geo; args->dp = dp; args->trans = tp; error = xfs_dir2_sf_create(args, pdp->i_ino); kmem_free(args); return error; } /* * Enter a name in a directory, or check for available space. * If inum is 0, only the available space test is performed. */ int xfs_dir_createname( xfs_trans_t *tp, xfs_inode_t *dp, struct xfs_name *name, xfs_ino_t inum, /* new entry inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; int rval; int v; /* type-checking value */ ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); if (inum) { rval = xfs_dir_ino_validate(tp->t_mountp, inum); if (rval) return rval; XFS_STATS_INC(dp->i_mount, xs_dir_create); } args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); if (!args) return -ENOMEM; args->geo = dp->i_mount->m_dir_geo; args->name = name->name; args->namelen = name->len; args->filetype = name->type; args->hashval = dp->i_mount->m_dirnameops->hashname(name); args->inumber = inum; args->dp = dp; args->firstblock = first; args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; if (!inum) args->op_flags |= XFS_DA_OP_JUSTCHECK; if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { rval = xfs_dir2_sf_addname(args); goto out_free; } rval = xfs_dir2_isblock(args, &v); if (rval) goto out_free; if (v) { rval = xfs_dir2_block_addname(args); goto out_free; } rval = xfs_dir2_isleaf(args, &v); if (rval) goto out_free; if (v) rval = xfs_dir2_leaf_addname(args); else rval = xfs_dir2_node_addname(args); out_free: kmem_free(args); return rval; } /* * If doing a CI lookup and case-insensitive match, dup actual name into * args.value. Return EEXIST for success (ie. name found) or an error. */ int xfs_dir_cilookup_result( struct xfs_da_args *args, const unsigned char *name, int len) { if (args->cmpresult == XFS_CMP_DIFFERENT) return -ENOENT; if (args->cmpresult != XFS_CMP_CASE || !(args->op_flags & XFS_DA_OP_CILOOKUP)) return -EEXIST; args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL); if (!args->value) return -ENOMEM; memcpy(args->value, name, len); args->valuelen = len; return -EEXIST; } /* * Lookup a name in a directory, give back the inode number. * If ci_name is not NULL, returns the actual name in ci_name if it differs * to name, or ci_name->name is set to NULL for an exact match. */ int xfs_dir_lookup( xfs_trans_t *tp, xfs_inode_t *dp, struct xfs_name *name, xfs_ino_t *inum, /* out: inode number */ struct xfs_name *ci_name) /* out: actual name if CI match */ { struct xfs_da_args *args; int rval; int v; /* type-checking value */ int lock_mode; ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); XFS_STATS_INC(dp->i_mount, xs_dir_lookup); /* * We need to use KM_NOFS here so that lockdep will not throw false * positive deadlock warnings on a non-transactional lookup path. It is * safe to recurse into inode recalim in that case, but lockdep can't * easily be taught about it. Hence KM_NOFS avoids having to add more * lockdep Doing this avoids having to add a bunch of lockdep class * annotations into the reclaim path for the ilock. */ args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); args->geo = dp->i_mount->m_dir_geo; args->name = name->name; args->namelen = name->len; args->filetype = name->type; args->hashval = dp->i_mount->m_dirnameops->hashname(name); args->dp = dp; args->whichfork = XFS_DATA_FORK; args->trans = tp; args->op_flags = XFS_DA_OP_OKNOENT; if (ci_name) args->op_flags |= XFS_DA_OP_CILOOKUP; lock_mode = xfs_ilock_data_map_shared(dp); if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { rval = xfs_dir2_sf_lookup(args); goto out_check_rval; } rval = xfs_dir2_isblock(args, &v); if (rval) goto out_free; if (v) { rval = xfs_dir2_block_lookup(args); goto out_check_rval; } rval = xfs_dir2_isleaf(args, &v); if (rval) goto out_free; if (v) rval = xfs_dir2_leaf_lookup(args); else rval = xfs_dir2_node_lookup(args); out_check_rval: if (rval == -EEXIST) rval = 0; if (!rval) { *inum = args->inumber; if (ci_name) { ci_name->name = args->value; ci_name->len = args->valuelen; } } out_free: xfs_iunlock(dp, lock_mode); kmem_free(args); return rval; } /* * Remove an entry from a directory. */ int xfs_dir_removename( xfs_trans_t *tp, xfs_inode_t *dp, struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, /* bmap's firstblock */ struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; int rval; int v; /* type-checking value */ ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); XFS_STATS_INC(dp->i_mount, xs_dir_remove); args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); if (!args) return -ENOMEM; args->geo = dp->i_mount->m_dir_geo; args->name = name->name; args->namelen = name->len; args->filetype = name->type; args->hashval = dp->i_mount->m_dirnameops->hashname(name); args->inumber = ino; args->dp = dp; args->firstblock = first; args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { rval = xfs_dir2_sf_removename(args); goto out_free; } rval = xfs_dir2_isblock(args, &v); if (rval) goto out_free; if (v) { rval = xfs_dir2_block_removename(args); goto out_free; } rval = xfs_dir2_isleaf(args, &v); if (rval) goto out_free; if (v) rval = xfs_dir2_leaf_removename(args); else rval = xfs_dir2_node_removename(args); out_free: kmem_free(args); return rval; } /* * Replace the inode number of a directory entry. */ int xfs_dir_replace( xfs_trans_t *tp, xfs_inode_t *dp, struct xfs_name *name, /* name of entry to replace */ xfs_ino_t inum, /* new inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; int rval; int v; /* type-checking value */ ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); rval = xfs_dir_ino_validate(tp->t_mountp, inum); if (rval) return rval; args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); if (!args) return -ENOMEM; args->geo = dp->i_mount->m_dir_geo; args->name = name->name; args->namelen = name->len; args->filetype = name->type; args->hashval = dp->i_mount->m_dirnameops->hashname(name); args->inumber = inum; args->dp = dp; args->firstblock = first; args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { rval = xfs_dir2_sf_replace(args); goto out_free; } rval = xfs_dir2_isblock(args, &v); if (rval) goto out_free; if (v) { rval = xfs_dir2_block_replace(args); goto out_free; } rval = xfs_dir2_isleaf(args, &v); if (rval) goto out_free; if (v) rval = xfs_dir2_leaf_replace(args); else rval = xfs_dir2_node_replace(args); out_free: kmem_free(args); return rval; } /* * See if this entry can be added to the directory without allocating space. */ int xfs_dir_canenter( xfs_trans_t *tp, xfs_inode_t *dp, struct xfs_name *name) /* name of entry to add */ { return xfs_dir_createname(tp, dp, name, 0, NULL, NULL, 0); } /* * Utility routines. */ /* * Add a block to the directory. * * This routine is for data and free blocks, not leaf/node blocks which are * handled by xfs_da_grow_inode. */ int xfs_dir2_grow_inode( struct xfs_da_args *args, int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ xfs_dir2_db_t *dbp) /* out: block number added */ { struct xfs_inode *dp = args->dp; struct xfs_mount *mp = dp->i_mount; xfs_fileoff_t bno; /* directory offset of new block */ int count; /* count of filesystem blocks */ int error; trace_xfs_dir2_grow_inode(args, space); /* * Set lowest possible block in the space requested. */ bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); count = args->geo->fsbcount; error = xfs_da_grow_inode_int(args, &bno, count); if (error) return error; *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno); /* * Update file's size if this is the data space and it grew. */ if (space == XFS_DIR2_DATA_SPACE) { xfs_fsize_t size; /* directory file (data) size */ size = XFS_FSB_TO_B(mp, bno + count); if (size > dp->i_d.di_size) { dp->i_d.di_size = size; xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); } } return 0; } /* * See if the directory is a single-block form directory. */ int xfs_dir2_isblock( struct xfs_da_args *args, int *vp) /* out: 1 is block, 0 is not block */ { xfs_fileoff_t last; /* last file offset */ int rval; if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) return rval; rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize); *vp = rval; return 0; } /* * See if the directory is a single-leaf form directory. */ int xfs_dir2_isleaf( struct xfs_da_args *args, int *vp) /* out: 1 is block, 0 is not block */ { xfs_fileoff_t last; /* last file offset */ int rval; if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) return rval; *vp = last == args->geo->leafblk + args->geo->fsbcount; return 0; } /* * Remove the given block from the directory. * This routine is used for data and free blocks, leaf/node are done * by xfs_da_shrink_inode. */ int xfs_dir2_shrink_inode( xfs_da_args_t *args, xfs_dir2_db_t db, struct xfs_buf *bp) { xfs_fileoff_t bno; /* directory file offset */ xfs_dablk_t da; /* directory file offset */ int done; /* bunmap is finished */ xfs_inode_t *dp; int error; xfs_mount_t *mp; xfs_trans_t *tp; trace_xfs_dir2_shrink_inode(args, db); dp = args->dp; mp = dp->i_mount; tp = args->trans; da = xfs_dir2_db_to_da(args->geo, db); /* Unmap the fsblock(s). */ error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, args->firstblock, args->dfops, &done); if (error) { /* * ENOSPC actually can happen if we're in a removename with no * space reservation, and the resulting block removal would * cause a bmap btree split or conversion from extents to btree. * This can only happen for un-fragmented directory blocks, * since you need to be punching out the middle of an extent. * In this case we need to leave the block in the file, and not * binval it. So the block has to be in a consistent empty * state and appropriately logged. We don't free up the buffer, * the caller can tell it hasn't happened since it got an error * back. */ return error; } ASSERT(done); /* * Invalidate the buffer from the transaction. */ xfs_trans_binval(tp, bp); /* * If it's not a data block, we're done. */ if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET)) return 0; /* * If the block isn't the last one in the directory, we're done. */ if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0)) return 0; bno = da; if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { /* * This can't really happen unless there's kernel corruption. */ return error; } if (db == args->geo->datablk) ASSERT(bno == 0); else ASSERT(bno > 0); /* * Set the size to the new last block. */ dp->i_d.di_size = XFS_FSB_TO_B(mp, bno); xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2.h0000644000000000000000000002411513063067171015655 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_DIR2_H__ #define __XFS_DIR2_H__ struct xfs_defer_ops; struct xfs_da_args; struct xfs_inode; struct xfs_mount; struct xfs_trans; struct xfs_dir2_sf_hdr; struct xfs_dir2_sf_entry; struct xfs_dir2_data_hdr; struct xfs_dir2_data_entry; struct xfs_dir2_data_unused; extern struct xfs_name xfs_name_dotdot; /* * directory filetype conversion tables. */ #define S_SHIFT 12 extern const unsigned char xfs_mode_to_ftype[]; /* * directory operations vector for encode/decode routines */ struct xfs_dir_ops { int (*sf_entsize)(struct xfs_dir2_sf_hdr *hdr, int len); struct xfs_dir2_sf_entry * (*sf_nextentry)(struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep); __uint8_t (*sf_get_ftype)(struct xfs_dir2_sf_entry *sfep); void (*sf_put_ftype)(struct xfs_dir2_sf_entry *sfep, __uint8_t ftype); xfs_ino_t (*sf_get_ino)(struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep); void (*sf_put_ino)(struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino); xfs_ino_t (*sf_get_parent_ino)(struct xfs_dir2_sf_hdr *hdr); void (*sf_put_parent_ino)(struct xfs_dir2_sf_hdr *hdr, xfs_ino_t ino); int (*data_entsize)(int len); __uint8_t (*data_get_ftype)(struct xfs_dir2_data_entry *dep); void (*data_put_ftype)(struct xfs_dir2_data_entry *dep, __uint8_t ftype); __be16 * (*data_entry_tag_p)(struct xfs_dir2_data_entry *dep); struct xfs_dir2_data_free * (*data_bestfree_p)(struct xfs_dir2_data_hdr *hdr); xfs_dir2_data_aoff_t data_dot_offset; xfs_dir2_data_aoff_t data_dotdot_offset; xfs_dir2_data_aoff_t data_first_offset; size_t data_entry_offset; struct xfs_dir2_data_entry * (*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr); struct xfs_dir2_data_entry * (*data_dotdot_entry_p)(struct xfs_dir2_data_hdr *hdr); struct xfs_dir2_data_entry * (*data_first_entry_p)(struct xfs_dir2_data_hdr *hdr); struct xfs_dir2_data_entry * (*data_entry_p)(struct xfs_dir2_data_hdr *hdr); struct xfs_dir2_data_unused * (*data_unused_p)(struct xfs_dir2_data_hdr *hdr); int leaf_hdr_size; void (*leaf_hdr_to_disk)(struct xfs_dir2_leaf *to, struct xfs_dir3_icleaf_hdr *from); void (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to, struct xfs_dir2_leaf *from); int (*leaf_max_ents)(struct xfs_da_geometry *geo); struct xfs_dir2_leaf_entry * (*leaf_ents_p)(struct xfs_dir2_leaf *lp); int node_hdr_size; void (*node_hdr_to_disk)(struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from); void (*node_hdr_from_disk)(struct xfs_da3_icnode_hdr *to, struct xfs_da_intnode *from); struct xfs_da_node_entry * (*node_tree_p)(struct xfs_da_intnode *dap); int free_hdr_size; void (*free_hdr_to_disk)(struct xfs_dir2_free *to, struct xfs_dir3_icfree_hdr *from); void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to, struct xfs_dir2_free *from); int (*free_max_bests)(struct xfs_da_geometry *geo); __be16 * (*free_bests_p)(struct xfs_dir2_free *free); xfs_dir2_db_t (*db_to_fdb)(struct xfs_da_geometry *geo, xfs_dir2_db_t db); int (*db_to_fdindex)(struct xfs_da_geometry *geo, xfs_dir2_db_t db); }; extern const struct xfs_dir_ops * xfs_dir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); extern const struct xfs_dir_ops * xfs_nondir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); /* * Generic directory interface routines */ extern void xfs_dir_startup(void); extern int xfs_da_mount(struct xfs_mount *mp); extern void xfs_da_unmount(struct xfs_mount *mp); extern int xfs_dir_isempty(struct xfs_inode *dp); extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_inode *pdp); extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t *inum, struct xfs_name *ci_name); extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name); /* * Direct call from the bmap code, bypassing the generic directory layer. */ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args); /* * Interface routines used by userspace utilities */ extern int xfs_dir2_isblock(struct xfs_da_args *args, int *r); extern int xfs_dir2_isleaf(struct xfs_da_args *args, int *r); extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, struct xfs_buf *bp); extern void __xfs_dir2_data_freescan(struct xfs_da_geometry *geo, const struct xfs_dir_ops *ops, struct xfs_dir2_data_hdr *hdr, int *loghead); extern void xfs_dir2_data_log_entry(struct xfs_da_args *args, struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); extern void xfs_dir2_data_log_header(struct xfs_da_args *args, struct xfs_buf *bp); extern void xfs_dir2_data_log_unused(struct xfs_da_args *args, struct xfs_buf *bp, struct xfs_dir2_data_unused *dup); extern void xfs_dir2_data_make_free(struct xfs_da_args *args, struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); extern void xfs_dir2_data_use_free(struct xfs_da_args *args, struct xfs_buf *bp, struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf, struct xfs_dir2_data_unused *dup); extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops; extern const struct xfs_buf_ops xfs_dir3_free_buf_ops; extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; /* * Directory offset/block conversion functions. * * DB blocks here are logical directory block numbers, not filesystem blocks. */ /* * Convert dataptr to byte in file space */ static inline xfs_dir2_off_t xfs_dir2_dataptr_to_byte(xfs_dir2_dataptr_t dp) { return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; } /* * Convert byte in file space to dataptr. It had better be aligned. */ static inline xfs_dir2_dataptr_t xfs_dir2_byte_to_dataptr(xfs_dir2_off_t by) { return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); } /* * Convert byte in space to (DB) block */ static inline xfs_dir2_db_t xfs_dir2_byte_to_db(struct xfs_da_geometry *geo, xfs_dir2_off_t by) { return (xfs_dir2_db_t)(by >> geo->blklog); } /* * Convert dataptr to a block number */ static inline xfs_dir2_db_t xfs_dir2_dataptr_to_db(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp) { return xfs_dir2_byte_to_db(geo, xfs_dir2_dataptr_to_byte(dp)); } /* * Convert byte in space to offset in a block */ static inline xfs_dir2_data_aoff_t xfs_dir2_byte_to_off(struct xfs_da_geometry *geo, xfs_dir2_off_t by) { return (xfs_dir2_data_aoff_t)(by & (geo->blksize - 1)); } /* * Convert dataptr to a byte offset in a block */ static inline xfs_dir2_data_aoff_t xfs_dir2_dataptr_to_off(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp) { return xfs_dir2_byte_to_off(geo, xfs_dir2_dataptr_to_byte(dp)); } /* * Convert block and offset to byte in space */ static inline xfs_dir2_off_t xfs_dir2_db_off_to_byte(struct xfs_da_geometry *geo, xfs_dir2_db_t db, xfs_dir2_data_aoff_t o) { return ((xfs_dir2_off_t)db << geo->blklog) + o; } /* * Convert block (DB) to block (dablk) */ static inline xfs_dablk_t xfs_dir2_db_to_da(struct xfs_da_geometry *geo, xfs_dir2_db_t db) { return (xfs_dablk_t)(db << (geo->blklog - geo->fsblog)); } /* * Convert byte in space to (DA) block */ static inline xfs_dablk_t xfs_dir2_byte_to_da(struct xfs_da_geometry *geo, xfs_dir2_off_t by) { return xfs_dir2_db_to_da(geo, xfs_dir2_byte_to_db(geo, by)); } /* * Convert block and offset to dataptr */ static inline xfs_dir2_dataptr_t xfs_dir2_db_off_to_dataptr(struct xfs_da_geometry *geo, xfs_dir2_db_t db, xfs_dir2_data_aoff_t o) { return xfs_dir2_byte_to_dataptr(xfs_dir2_db_off_to_byte(geo, db, o)); } /* * Convert block (dablk) to block (DB) */ static inline xfs_dir2_db_t xfs_dir2_da_to_db(struct xfs_da_geometry *geo, xfs_dablk_t da) { return (xfs_dir2_db_t)(da >> (geo->blklog - geo->fsblog)); } /* * Convert block (dablk) to byte offset in space */ static inline xfs_dir2_off_t xfs_dir2_da_to_byte(struct xfs_da_geometry *geo, xfs_dablk_t da) { return xfs_dir2_db_off_to_byte(geo, xfs_dir2_da_to_db(geo, da), 0); } /* * Directory tail pointer accessor functions. Based on block geometry. */ static inline struct xfs_dir2_block_tail * xfs_dir2_block_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_data_hdr *hdr) { return ((struct xfs_dir2_block_tail *) ((char *)hdr + geo->blksize)) - 1; } static inline struct xfs_dir2_leaf_tail * xfs_dir2_leaf_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_leaf *lp) { return (struct xfs_dir2_leaf_tail *) ((char *)lp + geo->blksize - sizeof(struct xfs_dir2_leaf_tail)); } #endif /* __XFS_DIR2_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2_block.c0000644000000000000000000010606413063067171017026 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trace.h" #include "xfs_cksum.h" /* * Local function prototypes. */ static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, struct xfs_buf *bp, int first, int last); static void xfs_dir2_block_log_tail(xfs_trans_t *tp, struct xfs_buf *bp); static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, struct xfs_buf **bpp, int *entno); static int xfs_dir2_block_sort(const void *a, const void *b); static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; /* * One-time startup routine called from xfs_init(). */ void xfs_dir_startup(void) { xfs_dir_hash_dot = xfs_da_hashname((unsigned char *)".", 1); xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2); } static bool xfs_dir3_block_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; if (xfs_sb_version_hascrc(&mp->m_sb)) { if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) return false; if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(hdr3->blkno) != bp->b_bn) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn))) return false; } else { if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) return false; } if (__xfs_dir3_data_check(NULL, bp)) return false; return true; } static void xfs_dir3_block_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&mp->m_sb) && !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_dir3_block_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void xfs_dir3_block_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; if (!xfs_dir3_block_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF); } const struct xfs_buf_ops xfs_dir3_block_buf_ops = { .name = "xfs_dir3_block", .verify_read = xfs_dir3_block_read_verify, .verify_write = xfs_dir3_block_write_verify, }; int xfs_dir3_block_read( struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf **bpp) { struct xfs_mount *mp = dp->i_mount; int err; err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, -1, bpp, XFS_DATA_FORK, &xfs_dir3_block_buf_ops); if (!err && tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF); return err; } static void xfs_dir3_block_init( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_inode *dp) { struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; bp->b_ops = &xfs_dir3_block_buf_ops; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_BLOCK_BUF); if (xfs_sb_version_hascrc(&mp->m_sb)) { memset(hdr3, 0, sizeof(*hdr3)); hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); hdr3->blkno = cpu_to_be64(bp->b_bn); hdr3->owner = cpu_to_be64(dp->i_ino); uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); return; } hdr3->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); } static void xfs_dir2_block_need_space( struct xfs_inode *dp, struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_block_tail *btp, struct xfs_dir2_leaf_entry *blp, __be16 **tagpp, struct xfs_dir2_data_unused **dupp, struct xfs_dir2_data_unused **enddupp, int *compact, int len) { struct xfs_dir2_data_free *bf; __be16 *tagp = NULL; struct xfs_dir2_data_unused *dup = NULL; struct xfs_dir2_data_unused *enddup = NULL; *compact = 0; bf = dp->d_ops->data_bestfree_p(hdr); /* * If there are stale entries we'll use one for the leaf. */ if (btp->stale) { if (be16_to_cpu(bf[0].length) >= len) { /* * The biggest entry enough to avoid compaction. */ dup = (xfs_dir2_data_unused_t *) ((char *)hdr + be16_to_cpu(bf[0].offset)); goto out; } /* * Will need to compact to make this work. * Tag just before the first leaf entry. */ *compact = 1; tagp = (__be16 *)blp - 1; /* Data object just before the first leaf entry. */ dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); /* * If it's not free then the data will go where the * leaf data starts now, if it works at all. */ if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len) dup = NULL; } else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len) dup = NULL; else dup = (xfs_dir2_data_unused_t *)blp; goto out; } /* * no stale entries, so just use free space. * Tag just before the first leaf entry. */ tagp = (__be16 *)blp - 1; /* Data object just before the first leaf entry. */ enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); /* * If it's not free then can't do this add without cleaning up: * the space before the first leaf entry needs to be free so it * can be expanded to hold the pointer to the new entry. */ if (be16_to_cpu(enddup->freetag) == XFS_DIR2_DATA_FREE_TAG) { /* * Check out the biggest freespace and see if it's the same one. */ dup = (xfs_dir2_data_unused_t *) ((char *)hdr + be16_to_cpu(bf[0].offset)); if (dup != enddup) { /* * Not the same free entry, just check its length. */ if (be16_to_cpu(dup->length) < len) dup = NULL; goto out; } /* * It is the biggest freespace, can it hold the leaf too? */ if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) { /* * Yes, use the second-largest entry instead if it works. */ if (be16_to_cpu(bf[1].length) >= len) dup = (xfs_dir2_data_unused_t *) ((char *)hdr + be16_to_cpu(bf[1].offset)); else dup = NULL; } } out: *tagpp = tagp; *dupp = dup; *enddupp = enddup; } /* * compact the leaf entries. * Leave the highest-numbered stale entry stale. * XXX should be the one closest to mid but mid is not yet computed. */ static void xfs_dir2_block_compact( struct xfs_da_args *args, struct xfs_buf *bp, struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_block_tail *btp, struct xfs_dir2_leaf_entry *blp, int *needlog, int *lfloghigh, int *lfloglow) { int fromidx; /* source leaf index */ int toidx; /* target leaf index */ int needscan = 0; int highstale; /* high stale index */ fromidx = toidx = be32_to_cpu(btp->count) - 1; highstale = *lfloghigh = -1; for (; fromidx >= 0; fromidx--) { if (blp[fromidx].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) { if (highstale == -1) highstale = toidx; else { if (*lfloghigh == -1) *lfloghigh = toidx; continue; } } if (fromidx < toidx) blp[toidx] = blp[fromidx]; toidx--; } *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1); *lfloghigh -= be32_to_cpu(btp->stale) - 1; be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1)); xfs_dir2_data_make_free(args, bp, (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)), needlog, &needscan); btp->stale = cpu_to_be32(1); /* * If we now need to rebuild the bestfree map, do so. * This needs to happen before the next call to use_free. */ if (needscan) xfs_dir2_data_freescan(args->dp, hdr, needlog); } /* * Add an entry to a block directory. */ int /* error */ xfs_dir2_block_addname( xfs_da_args_t *args) /* directory op arguments */ { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ struct xfs_buf *bp; /* buffer for block */ xfs_dir2_block_tail_t *btp; /* block tail */ int compact; /* need to compact leaf ents */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* directory inode */ xfs_dir2_data_unused_t *dup; /* block unused entry */ int error; /* error return value */ xfs_dir2_data_unused_t *enddup=NULL; /* unused at end of data */ xfs_dahash_t hash; /* hash value of found entry */ int high; /* high index for binary srch */ int highstale; /* high stale index */ int lfloghigh=0; /* last final leaf to log */ int lfloglow=0; /* first final leaf to log */ int len; /* length of the new entry */ int low; /* low index for binary srch */ int lowstale; /* low stale index */ int mid=0; /* midpoint for binary srch */ int needlog; /* need to log header */ int needscan; /* need to rescan freespace */ __be16 *tagp; /* pointer to tag value */ xfs_trans_t *tp; /* transaction structure */ trace_xfs_dir2_block_addname(args); dp = args->dp; tp = args->trans; /* Read the (one and only) directory block into bp. */ error = xfs_dir3_block_read(tp, dp, &bp); if (error) return error; len = dp->d_ops->data_entsize(args->namelen); /* * Set up pointers to parts of the block. */ hdr = bp->b_addr; btp = xfs_dir2_block_tail_p(args->geo, hdr); blp = xfs_dir2_block_leaf_p(btp); /* * Find out if we can reuse stale entries or whether we need extra * space for entry and new leaf. */ xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup, &enddup, &compact, len); /* * Done everything we need for a space check now. */ if (args->op_flags & XFS_DA_OP_JUSTCHECK) { xfs_trans_brelse(tp, bp); if (!dup) return -ENOSPC; return 0; } /* * If we don't have space for the new entry & leaf ... */ if (!dup) { /* Don't have a space reservation: return no-space. */ if (args->total == 0) return -ENOSPC; /* * Convert to the next larger format. * Then add the new entry in that format. */ error = xfs_dir2_block_to_leaf(args, bp); if (error) return error; return xfs_dir2_leaf_addname(args); } needlog = needscan = 0; /* * If need to compact the leaf entries, do it now. */ if (compact) { xfs_dir2_block_compact(args, bp, hdr, btp, blp, &needlog, &lfloghigh, &lfloglow); /* recalculate blp post-compaction */ blp = xfs_dir2_block_leaf_p(btp); } else if (btp->stale) { /* * Set leaf logging boundaries to impossible state. * For the no-stale case they're set explicitly. */ lfloglow = be32_to_cpu(btp->count); lfloghigh = -1; } /* * Find the slot that's first lower than our hash value, -1 if none. */ for (low = 0, high = be32_to_cpu(btp->count) - 1; low <= high; ) { mid = (low + high) >> 1; if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval) break; if (hash < args->hashval) low = mid + 1; else high = mid - 1; } while (mid >= 0 && be32_to_cpu(blp[mid].hashval) >= args->hashval) { mid--; } /* * No stale entries, will use enddup space to hold new leaf. */ if (!btp->stale) { /* * Mark the space needed for the new leaf entry, now in use. */ xfs_dir2_data_use_free(args, bp, enddup, (xfs_dir2_data_aoff_t) ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) - sizeof(*blp)), (xfs_dir2_data_aoff_t)sizeof(*blp), &needlog, &needscan); /* * Update the tail (entry count). */ be32_add_cpu(&btp->count, 1); /* * If we now need to rebuild the bestfree map, do so. * This needs to happen before the next call to use_free. */ if (needscan) { xfs_dir2_data_freescan(dp, hdr, &needlog); needscan = 0; } /* * Adjust pointer to the first leaf entry, we're about to move * the table up one to open up space for the new leaf entry. * Then adjust our index to match. */ blp--; mid++; if (mid) memmove(blp, &blp[1], mid * sizeof(*blp)); lfloglow = 0; lfloghigh = mid; } /* * Use a stale leaf for our new entry. */ else { for (lowstale = mid; lowstale >= 0 && blp[lowstale].address != cpu_to_be32(XFS_DIR2_NULL_DATAPTR); lowstale--) continue; for (highstale = mid + 1; highstale < be32_to_cpu(btp->count) && blp[highstale].address != cpu_to_be32(XFS_DIR2_NULL_DATAPTR) && (lowstale < 0 || mid - lowstale > highstale - mid); highstale++) continue; /* * Move entries toward the low-numbered stale entry. */ if (lowstale >= 0 && (highstale == be32_to_cpu(btp->count) || mid - lowstale <= highstale - mid)) { if (mid - lowstale) memmove(&blp[lowstale], &blp[lowstale + 1], (mid - lowstale) * sizeof(*blp)); lfloglow = MIN(lowstale, lfloglow); lfloghigh = MAX(mid, lfloghigh); } /* * Move entries toward the high-numbered stale entry. */ else { ASSERT(highstale < be32_to_cpu(btp->count)); mid++; if (highstale - mid) memmove(&blp[mid + 1], &blp[mid], (highstale - mid) * sizeof(*blp)); lfloglow = MIN(mid, lfloglow); lfloghigh = MAX(highstale, lfloghigh); } be32_add_cpu(&btp->stale, -1); } /* * Point to the new data entry. */ dep = (xfs_dir2_data_entry_t *)dup; /* * Fill in the leaf entry. */ blp[mid].hashval = cpu_to_be32(args->hashval); blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( (char *)dep - (char *)hdr)); xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh); /* * Mark space for the data entry used. */ xfs_dir2_data_use_free(args, bp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), (xfs_dir2_data_aoff_t)len, &needlog, &needscan); /* * Create the new data entry. */ dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, args->namelen); dp->d_ops->data_put_ftype(dep, args->filetype); tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); /* * Clean up the bestfree array and log the header, tail, and entry. */ if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(args, bp); xfs_dir2_block_log_tail(tp, bp); xfs_dir2_data_log_entry(args, bp, dep); xfs_dir3_data_check(dp, bp); return 0; } /* * Log leaf entries from the block. */ static void xfs_dir2_block_log_leaf( xfs_trans_t *tp, /* transaction structure */ struct xfs_buf *bp, /* block buffer */ int first, /* index of first logged leaf */ int last) /* index of last logged leaf */ { xfs_dir2_data_hdr_t *hdr = bp->b_addr; xfs_dir2_leaf_entry_t *blp; xfs_dir2_block_tail_t *btp; btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr); blp = xfs_dir2_block_leaf_p(btp); xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr), (uint)((char *)&blp[last + 1] - (char *)hdr - 1)); } /* * Log the block tail. */ static void xfs_dir2_block_log_tail( xfs_trans_t *tp, /* transaction structure */ struct xfs_buf *bp) /* block buffer */ { xfs_dir2_data_hdr_t *hdr = bp->b_addr; xfs_dir2_block_tail_t *btp; btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr); xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr), (uint)((char *)(btp + 1) - (char *)hdr - 1)); } /* * Look up an entry in the block. This is the external routine, * xfs_dir2_block_lookup_int does the real work. */ int /* error */ xfs_dir2_block_lookup( xfs_da_args_t *args) /* dir lookup arguments */ { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ int ent; /* entry index */ int error; /* error return value */ trace_xfs_dir2_block_lookup(args); /* * Get the buffer, look up the entry. * If not found (ENOENT) then return, have no buffer. */ if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) return error; dp = args->dp; hdr = bp->b_addr; xfs_dir3_data_check(dp, bp); btp = xfs_dir2_block_tail_p(args->geo, hdr); blp = xfs_dir2_block_leaf_p(btp); /* * Get the offset from the leaf entry, to point to the data. */ dep = (xfs_dir2_data_entry_t *)((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(blp[ent].address))); /* * Fill in inode number, CI name if appropriate, release the block. */ args->inumber = be64_to_cpu(dep->inumber); args->filetype = dp->d_ops->data_get_ftype(dep); error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); xfs_trans_brelse(args->trans, bp); return error; } /* * Internal block lookup routine. */ static int /* error */ xfs_dir2_block_lookup_int( xfs_da_args_t *args, /* dir lookup arguments */ struct xfs_buf **bpp, /* returned block buffer */ int *entno) /* returned entry number */ { xfs_dir2_dataptr_t addr; /* data entry address */ xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ int error; /* error return value */ xfs_dahash_t hash; /* found hash value */ int high; /* binary search high index */ int low; /* binary search low index */ int mid; /* binary search current idx */ xfs_mount_t *mp; /* filesystem mount point */ xfs_trans_t *tp; /* transaction pointer */ enum xfs_dacmp cmp; /* comparison result */ dp = args->dp; tp = args->trans; mp = dp->i_mount; error = xfs_dir3_block_read(tp, dp, &bp); if (error) return error; hdr = bp->b_addr; xfs_dir3_data_check(dp, bp); btp = xfs_dir2_block_tail_p(args->geo, hdr); blp = xfs_dir2_block_leaf_p(btp); /* * Loop doing a binary search for our hash value. * Find our entry, ENOENT if it's not there. */ for (low = 0, high = be32_to_cpu(btp->count) - 1; ; ) { ASSERT(low <= high); mid = (low + high) >> 1; if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval) break; if (hash < args->hashval) low = mid + 1; else high = mid - 1; if (low > high) { ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); xfs_trans_brelse(tp, bp); return -ENOENT; } } /* * Back up to the first one with the right hash value. */ while (mid > 0 && be32_to_cpu(blp[mid - 1].hashval) == args->hashval) { mid--; } /* * Now loop forward through all the entries with the * right hash value looking for our name. */ do { if ((addr = be32_to_cpu(blp[mid].address)) == XFS_DIR2_NULL_DATAPTR) continue; /* * Get pointer to the entry from the leaf. */ dep = (xfs_dir2_data_entry_t *) ((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, addr)); /* * Compare name and if it's an exact match, return the index * and buffer. If it's the first case-insensitive match, store * the index and buffer and continue looking for an exact match. */ cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { args->cmpresult = cmp; *bpp = bp; *entno = mid; if (cmp == XFS_CMP_EXACT) return 0; } } while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash); ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); /* * Here, we can only be doing a lookup (not a rename or replace). * If a case-insensitive match was found earlier, return success. */ if (args->cmpresult == XFS_CMP_CASE) return 0; /* * No match, release the buffer and return ENOENT. */ xfs_trans_brelse(tp, bp); return -ENOENT; } /* * Remove an entry from a block format directory. * If that makes the block small enough to fit in shortform, transform it. */ int /* error */ xfs_dir2_block_removename( xfs_da_args_t *args) /* directory operation args */ { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf pointer */ struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ int ent; /* block leaf entry index */ int error; /* error return value */ int needlog; /* need to log block header */ int needscan; /* need to fixup bestfree */ xfs_dir2_sf_hdr_t sfh; /* shortform header */ int size; /* shortform size */ xfs_trans_t *tp; /* transaction pointer */ trace_xfs_dir2_block_removename(args); /* * Look up the entry in the block. Gets the buffer and entry index. * It will always be there, the vnodeops level does a lookup first. */ if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) { return error; } dp = args->dp; tp = args->trans; hdr = bp->b_addr; btp = xfs_dir2_block_tail_p(args->geo, hdr); blp = xfs_dir2_block_leaf_p(btp); /* * Point to the data entry using the leaf entry. */ dep = (xfs_dir2_data_entry_t *)((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(blp[ent].address))); /* * Mark the data entry's space free. */ needlog = needscan = 0; xfs_dir2_data_make_free(args, bp, (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* * Fix up the block tail. */ be32_add_cpu(&btp->stale, 1); xfs_dir2_block_log_tail(tp, bp); /* * Remove the leaf entry by marking it stale. */ blp[ent].address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); xfs_dir2_block_log_leaf(tp, bp, ent, ent); /* * Fix up bestfree, log the header if necessary. */ if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(args, bp); xfs_dir3_data_check(dp, bp); /* * See if the size as a shortform is good enough. */ size = xfs_dir2_block_sfsize(dp, hdr, &sfh); if (size > XFS_IFORK_DSIZE(dp)) return 0; /* * If it works, do the conversion. */ return xfs_dir2_block_to_sf(args, bp, size, &sfh); } /* * Replace an entry in a V2 block directory. * Change the inode number to the new value. */ int /* error */ xfs_dir2_block_replace( xfs_da_args_t *args) /* directory operation args */ { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ int ent; /* leaf entry index */ int error; /* error return value */ trace_xfs_dir2_block_replace(args); /* * Lookup the entry in the directory. Get buffer and entry index. * This will always succeed since the caller has already done a lookup. */ if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) { return error; } dp = args->dp; hdr = bp->b_addr; btp = xfs_dir2_block_tail_p(args->geo, hdr); blp = xfs_dir2_block_leaf_p(btp); /* * Point to the data entry we need to change. */ dep = (xfs_dir2_data_entry_t *)((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(blp[ent].address))); ASSERT(be64_to_cpu(dep->inumber) != args->inumber); /* * Change the inode number to the new value. */ dep->inumber = cpu_to_be64(args->inumber); dp->d_ops->data_put_ftype(dep, args->filetype); xfs_dir2_data_log_entry(args, bp, dep); xfs_dir3_data_check(dp, bp); return 0; } /* * Qsort comparison routine for the block leaf entries. */ static int /* sort order */ xfs_dir2_block_sort( const void *a, /* first leaf entry */ const void *b) /* second leaf entry */ { const xfs_dir2_leaf_entry_t *la; /* first leaf entry */ const xfs_dir2_leaf_entry_t *lb; /* second leaf entry */ la = a; lb = b; return be32_to_cpu(la->hashval) < be32_to_cpu(lb->hashval) ? -1 : (be32_to_cpu(la->hashval) > be32_to_cpu(lb->hashval) ? 1 : 0); } /* * Convert a V2 leaf directory to a V2 block directory if possible. */ int /* error */ xfs_dir2_leaf_to_block( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *lbp, /* leaf buffer */ struct xfs_buf *dbp) /* data buffer */ { __be16 *bestsp; /* leaf bests table */ xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* unused data entry */ int error; /* error return value */ int from; /* leaf from index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ xfs_mount_t *mp; /* file system mount point */ int needlog; /* need to log data header */ int needscan; /* need to scan for bestfree */ xfs_dir2_sf_hdr_t sfh; /* shortform header */ int size; /* bytes used */ __be16 *tagp; /* end of entry (tag) */ int to; /* block/leaf to index */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; trace_xfs_dir2_leaf_to_block(args); dp = args->dp; tp = args->trans; mp = dp->i_mount; leaf = lbp->b_addr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || leafhdr.magic == XFS_DIR3_LEAF1_MAGIC); /* * If there are data blocks other than the first one, take this * opportunity to remove trailing empty data blocks that may have * been left behind during no-space-reservation operations. * These will show up in the leaf bests table. */ while (dp->i_d.di_size > args->geo->blksize) { int hdrsz; hdrsz = dp->d_ops->data_entry_offset; bestsp = xfs_dir2_leaf_bests_p(ltp); if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == args->geo->blksize - hdrsz) { if ((error = xfs_dir2_leaf_trim_data(args, lbp, (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1)))) return error; } else return 0; } /* * Read the data block if we don't already have it, give up if it fails. */ if (!dbp) { error = xfs_dir3_data_read(tp, dp, args->geo->datablk, -1, &dbp); if (error) return error; } hdr = dbp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); /* * Size of the "leaf" area in the block. */ size = (uint)sizeof(xfs_dir2_block_tail_t) + (uint)sizeof(*lep) * (leafhdr.count - leafhdr.stale); /* * Look at the last data entry. */ tagp = (__be16 *)((char *)hdr + args->geo->blksize) - 1; dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); /* * If it's not free or is too short we can't do it. */ if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG || be16_to_cpu(dup->length) < size) return 0; /* * Start converting it to block form. */ xfs_dir3_block_init(mp, tp, dbp, dp); needlog = 1; needscan = 0; /* * Use up the space at the end of the block (blp/btp). */ xfs_dir2_data_use_free(args, dbp, dup, args->geo->blksize - size, size, &needlog, &needscan); /* * Initialize the block tail. */ btp = xfs_dir2_block_tail_p(args->geo, hdr); btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale); btp->stale = 0; xfs_dir2_block_log_tail(tp, dbp); /* * Initialize the block leaf area. We compact out stale entries. */ lep = xfs_dir2_block_leaf_p(btp); for (from = to = 0; from < leafhdr.count; from++) { if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) continue; lep[to++] = ents[from]; } ASSERT(to == be32_to_cpu(btp->count)); xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1); /* * Scan the bestfree if we need it and log the data block header. */ if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(args, dbp); /* * Pitch the old leaf block. */ error = xfs_da_shrink_inode(args, args->geo->leafblk, lbp); if (error) return error; /* * Now see if the resulting block can be shrunken to shortform. */ size = xfs_dir2_block_sfsize(dp, hdr, &sfh); if (size > XFS_IFORK_DSIZE(dp)) return 0; return xfs_dir2_block_to_sf(args, dbp, size, &sfh); } /* * Convert the shortform directory to block form. */ int /* error */ xfs_dir2_sf_to_block( xfs_da_args_t *args) /* operation arguments */ { xfs_dir2_db_t blkno; /* dir-relative block # (0) */ xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail pointer */ xfs_dir2_data_entry_t *dep; /* data entry pointer */ xfs_inode_t *dp; /* incore directory inode */ int dummy; /* trash */ xfs_dir2_data_unused_t *dup; /* unused entry pointer */ int endoffset; /* end of data objects */ int error; /* error return value */ int i; /* index */ xfs_mount_t *mp; /* filesystem mount point */ int needlog; /* need to log block header */ int needscan; /* need to scan block freespc */ int newoffset; /* offset from current entry */ int offset; /* target block offset */ xfs_dir2_sf_entry_t *sfep; /* sf entry pointer */ xfs_dir2_sf_hdr_t *oldsfp; /* old shortform header */ xfs_dir2_sf_hdr_t *sfp; /* shortform header */ __be16 *tagp; /* end of data entry */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_name name; struct xfs_ifork *ifp; trace_xfs_dir2_sf_to_block(args); dp = args->dp; tp = args->trans; mp = dp->i_mount; ifp = XFS_IFORK_PTR(dp, XFS_DATA_FORK); ASSERT(ifp->if_flags & XFS_IFINLINE); /* * Bomb out if the shortform directory is way too short. */ if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { ASSERT(XFS_FORCED_SHUTDOWN(mp)); return -EIO; } oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data; ASSERT(ifp->if_bytes == dp->i_d.di_size); ASSERT(ifp->if_u1.if_data != NULL); ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count)); ASSERT(dp->i_d.di_nextents == 0); /* * Copy the directory into a temporary buffer. * Then pitch the incore inode data so we can make extents. */ sfp = kmem_alloc(ifp->if_bytes, KM_SLEEP); memcpy(sfp, oldsfp, ifp->if_bytes); xfs_idata_realloc(dp, -ifp->if_bytes, XFS_DATA_FORK); xfs_bmap_local_to_extents_empty(dp, XFS_DATA_FORK); dp->i_d.di_size = 0; /* * Add block 0 to the inode. */ error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno); if (error) { kmem_free(sfp); return error; } /* * Initialize the data block, then convert it to block format. */ error = xfs_dir3_data_init(args, blkno, &bp); if (error) { kmem_free(sfp); return error; } xfs_dir3_block_init(mp, tp, bp, dp); hdr = bp->b_addr; /* * Compute size of block "tail" area. */ i = (uint)sizeof(*btp) + (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t); /* * The whole thing is initialized to free by the init routine. * Say we're using the leaf and tail area. */ dup = dp->d_ops->data_unused_p(hdr); needlog = needscan = 0; xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i, i, &needlog, &needscan); ASSERT(needscan == 0); /* * Fill in the tail. */ btp = xfs_dir2_block_tail_p(args->geo, hdr); btp->count = cpu_to_be32(sfp->count + 2); /* ., .. */ btp->stale = 0; blp = xfs_dir2_block_leaf_p(btp); endoffset = (uint)((char *)blp - (char *)hdr); /* * Remove the freespace, we'll manage it. */ xfs_dir2_data_use_free(args, bp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), be16_to_cpu(dup->length), &needlog, &needscan); /* * Create entry for . */ dep = dp->d_ops->data_dot_entry_p(hdr); dep->inumber = cpu_to_be64(dp->i_ino); dep->namelen = 1; dep->name[0] = '.'; dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); xfs_dir2_data_log_entry(args, bp, dep); blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( (char *)dep - (char *)hdr)); /* * Create entry for .. */ dep = dp->d_ops->data_dotdot_entry_p(hdr); dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp)); dep->namelen = 2; dep->name[0] = dep->name[1] = '.'; dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); xfs_dir2_data_log_entry(args, bp, dep); blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( (char *)dep - (char *)hdr)); offset = dp->d_ops->data_first_offset; /* * Loop over existing entries, stuff them in. */ i = 0; if (!sfp->count) sfep = NULL; else sfep = xfs_dir2_sf_firstentry(sfp); /* * Need to preserve the existing offset values in the sf directory. * Insert holes (unused entries) where necessary. */ while (offset < endoffset) { /* * sfep is null when we reach the end of the list. */ if (sfep == NULL) newoffset = endoffset; else newoffset = xfs_dir2_sf_get_offset(sfep); /* * There should be a hole here, make one. */ if (offset < newoffset) { dup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); dup->length = cpu_to_be16(newoffset - offset); *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16( ((char *)dup - (char *)hdr)); xfs_dir2_data_log_unused(args, bp, dup); xfs_dir2_data_freeinsert(hdr, dp->d_ops->data_bestfree_p(hdr), dup, &dummy); offset += be16_to_cpu(dup->length); continue; } /* * Copy a real entry. */ dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset); dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep)); dep->namelen = sfep->namelen; dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep)); memcpy(dep->name, sfep->name, dep->namelen); tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); xfs_dir2_data_log_entry(args, bp, dep); name.name = sfep->name; name.len = sfep->namelen; blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> hashname(&name)); blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( (char *)dep - (char *)hdr)); offset = (int)((char *)(tagp + 1) - (char *)hdr); if (++i == sfp->count) sfep = NULL; else sfep = dp->d_ops->sf_nextentry(sfp, sfep); } /* Done with the temporary buffer */ kmem_free(sfp); /* * Sort the leaf entries by hash value. */ xfs_sort(blp, be32_to_cpu(btp->count), sizeof(*blp), xfs_dir2_block_sort); /* * Log the leaf entry area and tail. * Already logged the header in data_init, ignore needlog. */ ASSERT(needscan == 0); xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1); xfs_dir2_block_log_tail(tp, bp); xfs_dir3_data_check(dp, bp); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2_data.c0000644000000000000000000007503313063067171016646 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trans.h" #include "xfs_cksum.h" /* * Check the consistency of the data block. * The input can also be a block-format directory. * Return 0 is the buffer is good, otherwise an error. */ int __xfs_dir3_data_check( struct xfs_inode *dp, /* incore inode pointer */ struct xfs_buf *bp) /* data block's buffer */ { xfs_dir2_dataptr_t addr; /* addr for leaf lookup */ xfs_dir2_data_free_t *bf; /* bestfree table */ xfs_dir2_block_tail_t *btp=NULL; /* block tail */ int count; /* count of entries found */ xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_data_entry_t *dep; /* data entry */ xfs_dir2_data_free_t *dfp; /* bestfree entry */ xfs_dir2_data_unused_t *dup; /* unused entry */ char *endp; /* end of useful data */ int freeseen; /* mask of bestfrees seen */ xfs_dahash_t hash; /* hash of current name */ int i; /* leaf index */ int lastfree; /* last entry was unused */ xfs_dir2_leaf_entry_t *lep=NULL; /* block leaf entries */ xfs_mount_t *mp; /* filesystem mount point */ char *p; /* current data position */ int stale; /* count of stale leaves */ struct xfs_name name; const struct xfs_dir_ops *ops; struct xfs_da_geometry *geo; mp = bp->b_target->bt_mount; geo = mp->m_dir_geo; /* * We can be passed a null dp here from a verifier, so we need to go the * hard way to get them. */ ops = xfs_dir_get_ops(mp, dp); hdr = bp->b_addr; p = (char *)ops->data_entry_p(hdr); switch (hdr->magic) { case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): btp = xfs_dir2_block_tail_p(geo, hdr); lep = xfs_dir2_block_leaf_p(btp); endp = (char *)lep; /* * The number of leaf entries is limited by the size of the * block and the amount of space used by the data entries. * We don't know how much space is used by the data entries yet, * so just ensure that the count falls somewhere inside the * block right now. */ XFS_WANT_CORRUPTED_RETURN(mp, be32_to_cpu(btp->count) < ((char *)btp - p) / sizeof(struct xfs_dir2_leaf_entry)); break; case cpu_to_be32(XFS_DIR3_DATA_MAGIC): case cpu_to_be32(XFS_DIR2_DATA_MAGIC): endp = (char *)hdr + geo->blksize; break; default: XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } /* * Account for zero bestfree entries. */ bf = ops->data_bestfree_p(hdr); count = lastfree = freeseen = 0; if (!bf[0].length) { XFS_WANT_CORRUPTED_RETURN(mp, !bf[0].offset); freeseen |= 1 << 0; } if (!bf[1].length) { XFS_WANT_CORRUPTED_RETURN(mp, !bf[1].offset); freeseen |= 1 << 1; } if (!bf[2].length) { XFS_WANT_CORRUPTED_RETURN(mp, !bf[2].offset); freeseen |= 1 << 2; } XFS_WANT_CORRUPTED_RETURN(mp, be16_to_cpu(bf[0].length) >= be16_to_cpu(bf[1].length)); XFS_WANT_CORRUPTED_RETURN(mp, be16_to_cpu(bf[1].length) >= be16_to_cpu(bf[2].length)); /* * Loop over the data/unused entries. */ while (p < endp) { dup = (xfs_dir2_data_unused_t *)p; /* * If it's unused, look for the space in the bestfree table. * If we find it, account for that, else make sure it * doesn't need to be there. */ if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { XFS_WANT_CORRUPTED_RETURN(mp, lastfree == 0); XFS_WANT_CORRUPTED_RETURN(mp, be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) == (char *)dup - (char *)hdr); dfp = xfs_dir2_data_freefind(hdr, bf, dup); if (dfp) { i = (int)(dfp - bf); XFS_WANT_CORRUPTED_RETURN(mp, (freeseen & (1 << i)) == 0); freeseen |= 1 << i; } else { XFS_WANT_CORRUPTED_RETURN(mp, be16_to_cpu(dup->length) <= be16_to_cpu(bf[2].length)); } p += be16_to_cpu(dup->length); lastfree = 1; continue; } /* * It's a real entry. Validate the fields. * If this is a block directory then make sure it's * in the leaf section of the block. * The linear search is crude but this is DEBUG code. */ dep = (xfs_dir2_data_entry_t *)p; XFS_WANT_CORRUPTED_RETURN(mp, dep->namelen != 0); XFS_WANT_CORRUPTED_RETURN(mp, !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber))); XFS_WANT_CORRUPTED_RETURN(mp, be16_to_cpu(*ops->data_entry_tag_p(dep)) == (char *)dep - (char *)hdr); XFS_WANT_CORRUPTED_RETURN(mp, ops->data_get_ftype(dep) < XFS_DIR3_FT_MAX); count++; lastfree = 0; if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, (xfs_dir2_data_aoff_t) ((char *)dep - (char *)hdr)); name.name = dep->name; name.len = dep->namelen; hash = mp->m_dirnameops->hashname(&name); for (i = 0; i < be32_to_cpu(btp->count); i++) { if (be32_to_cpu(lep[i].address) == addr && be32_to_cpu(lep[i].hashval) == hash) break; } XFS_WANT_CORRUPTED_RETURN(mp, i < be32_to_cpu(btp->count)); } p += ops->data_entsize(dep->namelen); } /* * Need to have seen all the entries and all the bestfree slots. */ XFS_WANT_CORRUPTED_RETURN(mp, freeseen == 7); if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { for (i = stale = 0; i < be32_to_cpu(btp->count); i++) { if (lep[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) stale++; if (i > 0) XFS_WANT_CORRUPTED_RETURN(mp, be32_to_cpu(lep[i].hashval) >= be32_to_cpu(lep[i - 1].hashval)); } XFS_WANT_CORRUPTED_RETURN(mp, count == be32_to_cpu(btp->count) - be32_to_cpu(btp->stale)); XFS_WANT_CORRUPTED_RETURN(mp, stale == be32_to_cpu(btp->stale)); } return 0; } static bool xfs_dir3_data_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; if (xfs_sb_version_hascrc(&mp->m_sb)) { if (hdr3->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC)) return false; if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(hdr3->blkno) != bp->b_bn) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn))) return false; } else { if (hdr3->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC)) return false; } if (__xfs_dir3_data_check(NULL, bp)) return false; return true; } /* * Readahead of the first block of the directory when it is opened is completely * oblivious to the format of the directory. Hence we can either get a block * format buffer or a data format buffer on readahead. */ static void xfs_dir3_data_reada_verify( struct xfs_buf *bp) { struct xfs_dir2_data_hdr *hdr = bp->b_addr; switch (hdr->magic) { case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): bp->b_ops = &xfs_dir3_block_buf_ops; bp->b_ops->verify_read(bp); return; case cpu_to_be32(XFS_DIR2_DATA_MAGIC): case cpu_to_be32(XFS_DIR3_DATA_MAGIC): bp->b_ops = &xfs_dir3_data_buf_ops; bp->b_ops->verify_read(bp); return; default: xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); break; } } static void xfs_dir3_data_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&mp->m_sb) && !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_dir3_data_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void xfs_dir3_data_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; if (!xfs_dir3_data_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF); } const struct xfs_buf_ops xfs_dir3_data_buf_ops = { .name = "xfs_dir3_data", .verify_read = xfs_dir3_data_read_verify, .verify_write = xfs_dir3_data_write_verify, }; static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = { .name = "xfs_dir3_data_reada", .verify_read = xfs_dir3_data_reada_verify, .verify_write = xfs_dir3_data_write_verify, }; int xfs_dir3_data_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp) { int err; err = xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp, XFS_DATA_FORK, &xfs_dir3_data_buf_ops); if (!err && tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF); return err; } int xfs_dir3_data_readahead( struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mapped_bno) { return xfs_da_reada_buf(dp, bno, mapped_bno, XFS_DATA_FORK, &xfs_dir3_data_reada_buf_ops); } /* * Given a data block and an unused entry from that block, * return the bestfree entry if any that corresponds to it. */ xfs_dir2_data_free_t * xfs_dir2_data_freefind( struct xfs_dir2_data_hdr *hdr, /* data block header */ struct xfs_dir2_data_free *bf, /* bestfree table pointer */ struct xfs_dir2_data_unused *dup) /* unused space */ { xfs_dir2_data_free_t *dfp; /* bestfree entry */ xfs_dir2_data_aoff_t off; /* offset value needed */ #ifdef DEBUG int matched; /* matched the value */ int seenzero; /* saw a 0 bestfree entry */ #endif off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); #ifdef DEBUG /* * Validate some consistency in the bestfree table. * Check order, non-overlapping entries, and if we find the * one we're looking for it has to be exact. */ ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); for (dfp = &bf[0], seenzero = matched = 0; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) { if (!dfp->offset) { ASSERT(!dfp->length); seenzero = 1; continue; } ASSERT(seenzero == 0); if (be16_to_cpu(dfp->offset) == off) { matched = 1; ASSERT(dfp->length == dup->length); } else if (off < be16_to_cpu(dfp->offset)) ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset)); else ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off); ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length)); if (dfp > &bf[0]) ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length)); } #endif /* * If this is smaller than the smallest bestfree entry, * it can't be there since they're sorted. */ if (be16_to_cpu(dup->length) < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length)) return NULL; /* * Look at the three bestfree entries for our guy. */ for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) { if (!dfp->offset) return NULL; if (be16_to_cpu(dfp->offset) == off) return dfp; } /* * Didn't find it. This only happens if there are duplicate lengths. */ return NULL; } /* * Insert an unused-space entry into the bestfree table. */ xfs_dir2_data_free_t * /* entry inserted */ xfs_dir2_data_freeinsert( struct xfs_dir2_data_hdr *hdr, /* data block pointer */ struct xfs_dir2_data_free *dfp, /* bestfree table pointer */ struct xfs_dir2_data_unused *dup, /* unused space */ int *loghead) /* log the data header (out) */ { xfs_dir2_data_free_t new; /* new bestfree entry */ ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); new.length = dup->length; new.offset = cpu_to_be16((char *)dup - (char *)hdr); /* * Insert at position 0, 1, or 2; or not at all. */ if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) { dfp[2] = dfp[1]; dfp[1] = dfp[0]; dfp[0] = new; *loghead = 1; return &dfp[0]; } if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) { dfp[2] = dfp[1]; dfp[1] = new; *loghead = 1; return &dfp[1]; } if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) { dfp[2] = new; *loghead = 1; return &dfp[2]; } return NULL; } /* * Remove a bestfree entry from the table. */ STATIC void xfs_dir2_data_freeremove( struct xfs_dir2_data_hdr *hdr, /* data block header */ struct xfs_dir2_data_free *bf, /* bestfree table pointer */ struct xfs_dir2_data_free *dfp, /* bestfree entry pointer */ int *loghead) /* out: log data header */ { ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); /* * It's the first entry, slide the next 2 up. */ if (dfp == &bf[0]) { bf[0] = bf[1]; bf[1] = bf[2]; } /* * It's the second entry, slide the 3rd entry up. */ else if (dfp == &bf[1]) bf[1] = bf[2]; /* * Must be the last entry. */ else ASSERT(dfp == &bf[2]); /* * Clear the 3rd entry, must be zero now. */ bf[2].length = 0; bf[2].offset = 0; *loghead = 1; } /* * Given a data block, reconstruct its bestfree map. */ void __xfs_dir2_data_freescan( struct xfs_da_geometry *geo, const struct xfs_dir_ops *ops, struct xfs_dir2_data_hdr *hdr, int *loghead) { xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* active data entry */ xfs_dir2_data_unused_t *dup; /* unused data entry */ struct xfs_dir2_data_free *bf; char *endp; /* end of block's data */ char *p; /* current entry pointer */ ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); /* * Start by clearing the table. */ bf = ops->data_bestfree_p(hdr); memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT); *loghead = 1; /* * Set up pointers. */ p = (char *)ops->data_entry_p(hdr); if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { btp = xfs_dir2_block_tail_p(geo, hdr); endp = (char *)xfs_dir2_block_leaf_p(btp); } else endp = (char *)hdr + geo->blksize; /* * Loop over the block's entries. */ while (p < endp) { dup = (xfs_dir2_data_unused_t *)p; /* * If it's a free entry, insert it. */ if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { ASSERT((char *)dup - (char *)hdr == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup))); xfs_dir2_data_freeinsert(hdr, bf, dup, loghead); p += be16_to_cpu(dup->length); } /* * For active entries, check their tags and skip them. */ else { dep = (xfs_dir2_data_entry_t *)p; ASSERT((char *)dep - (char *)hdr == be16_to_cpu(*ops->data_entry_tag_p(dep))); p += ops->data_entsize(dep->namelen); } } } /* * Initialize a data block at the given block number in the directory. * Give back the buffer for the created block. */ int /* error */ xfs_dir3_data_init( xfs_da_args_t *args, /* directory operation args */ xfs_dir2_db_t blkno, /* logical dir block number */ struct xfs_buf **bpp) /* output block buffer */ { struct xfs_buf *bp; /* block buffer */ xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* unused entry pointer */ struct xfs_dir2_data_free *bf; int error; /* error return value */ int i; /* bestfree index */ xfs_mount_t *mp; /* filesystem mount point */ xfs_trans_t *tp; /* transaction pointer */ int t; /* temp */ dp = args->dp; mp = dp->i_mount; tp = args->trans; /* * Get the buffer set up for the block. */ error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno), -1, &bp, XFS_DATA_FORK); if (error) return error; bp->b_ops = &xfs_dir3_data_buf_ops; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_DATA_BUF); /* * Initialize the header. */ hdr = bp->b_addr; if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; memset(hdr3, 0, sizeof(*hdr3)); hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); hdr3->blkno = cpu_to_be64(bp->b_bn); hdr3->owner = cpu_to_be64(dp->i_ino); uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); } else hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); bf = dp->d_ops->data_bestfree_p(hdr); bf[0].offset = cpu_to_be16(dp->d_ops->data_entry_offset); for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { bf[i].length = 0; bf[i].offset = 0; } /* * Set up an unused entry for the block's body. */ dup = dp->d_ops->data_unused_p(hdr); dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); t = args->geo->blksize - (uint)dp->d_ops->data_entry_offset; bf[0].length = cpu_to_be16(t); dup->length = cpu_to_be16(t); *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); /* * Log it and return it. */ xfs_dir2_data_log_header(args, bp); xfs_dir2_data_log_unused(args, bp, dup); *bpp = bp; return 0; } /* * Log an active data entry from the block. */ void xfs_dir2_data_log_entry( struct xfs_da_args *args, struct xfs_buf *bp, xfs_dir2_data_entry_t *dep) /* data entry pointer */ { struct xfs_dir2_data_hdr *hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr), (uint)((char *)(args->dp->d_ops->data_entry_tag_p(dep) + 1) - (char *)hdr - 1)); } /* * Log a data block header. */ void xfs_dir2_data_log_header( struct xfs_da_args *args, struct xfs_buf *bp) { #ifdef DEBUG struct xfs_dir2_data_hdr *hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); #endif xfs_trans_log_buf(args->trans, bp, 0, args->dp->d_ops->data_entry_offset - 1); } /* * Log a data unused entry. */ void xfs_dir2_data_log_unused( struct xfs_da_args *args, struct xfs_buf *bp, xfs_dir2_data_unused_t *dup) /* data unused pointer */ { xfs_dir2_data_hdr_t *hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); /* * Log the first part of the unused entry. */ xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr), (uint)((char *)&dup->length + sizeof(dup->length) - 1 - (char *)hdr)); /* * Log the end (tag) of the unused entry. */ xfs_trans_log_buf(args->trans, bp, (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr), (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr + sizeof(xfs_dir2_data_off_t) - 1)); } /* * Make a byte range in the data block unused. * Its current contents are unimportant. */ void xfs_dir2_data_make_free( struct xfs_da_args *args, struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, /* starting byte offset */ xfs_dir2_data_aoff_t len, /* length in bytes */ int *needlogp, /* out: log header */ int *needscanp) /* out: regen bestfree */ { xfs_dir2_data_hdr_t *hdr; /* data block pointer */ xfs_dir2_data_free_t *dfp; /* bestfree pointer */ char *endptr; /* end of data area */ int needscan; /* need to regen bestfree */ xfs_dir2_data_unused_t *newdup; /* new unused entry */ xfs_dir2_data_unused_t *postdup; /* unused entry after us */ xfs_dir2_data_unused_t *prevdup; /* unused entry before us */ struct xfs_dir2_data_free *bf; hdr = bp->b_addr; /* * Figure out where the end of the data area is. */ if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)) endptr = (char *)hdr + args->geo->blksize; else { xfs_dir2_block_tail_t *btp; /* block tail */ ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); btp = xfs_dir2_block_tail_p(args->geo, hdr); endptr = (char *)xfs_dir2_block_leaf_p(btp); } /* * If this isn't the start of the block, then back up to * the previous entry and see if it's free. */ if (offset > args->dp->d_ops->data_entry_offset) { __be16 *tagp; /* tag just before us */ tagp = (__be16 *)((char *)hdr + offset) - 1; prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG) prevdup = NULL; } else prevdup = NULL; /* * If this isn't the end of the block, see if the entry after * us is free. */ if ((char *)hdr + offset + len < endptr) { postdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG) postdup = NULL; } else postdup = NULL; ASSERT(*needscanp == 0); needscan = 0; /* * Previous and following entries are both free, * merge everything into a single free entry. */ bf = args->dp->d_ops->data_bestfree_p(hdr); if (prevdup && postdup) { xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */ /* * See if prevdup and/or postdup are in bestfree table. */ dfp = xfs_dir2_data_freefind(hdr, bf, prevdup); dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup); /* * We need a rescan unless there are exactly 2 free entries * namely our two. Then we know what's happening, otherwise * since the third bestfree is there, there might be more * entries. */ needscan = (bf[2].length != 0); /* * Fix up the new big freespace. */ be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length)); *xfs_dir2_data_unused_tag_p(prevdup) = cpu_to_be16((char *)prevdup - (char *)hdr); xfs_dir2_data_log_unused(args, bp, prevdup); if (!needscan) { /* * Has to be the case that entries 0 and 1 are * dfp and dfp2 (don't know which is which), and * entry 2 is empty. * Remove entry 1 first then entry 0. */ ASSERT(dfp && dfp2); if (dfp == &bf[1]) { dfp = &bf[0]; ASSERT(dfp2 == dfp); dfp2 = &bf[1]; } xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp); xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); /* * Now insert the new entry. */ dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp); ASSERT(dfp == &bf[0]); ASSERT(dfp->length == prevdup->length); ASSERT(!dfp[1].length); ASSERT(!dfp[2].length); } } /* * The entry before us is free, merge with it. */ else if (prevdup) { dfp = xfs_dir2_data_freefind(hdr, bf, prevdup); be16_add_cpu(&prevdup->length, len); *xfs_dir2_data_unused_tag_p(prevdup) = cpu_to_be16((char *)prevdup - (char *)hdr); xfs_dir2_data_log_unused(args, bp, prevdup); /* * If the previous entry was in the table, the new entry * is longer, so it will be in the table too. Remove * the old one and add the new one. */ if (dfp) { xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp); } /* * Otherwise we need a scan if the new entry is big enough. */ else { needscan = be16_to_cpu(prevdup->length) > be16_to_cpu(bf[2].length); } } /* * The following entry is free, merge with it. */ else if (postdup) { dfp = xfs_dir2_data_freefind(hdr, bf, postdup); newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length)); *xfs_dir2_data_unused_tag_p(newdup) = cpu_to_be16((char *)newdup - (char *)hdr); xfs_dir2_data_log_unused(args, bp, newdup); /* * If the following entry was in the table, the new entry * is longer, so it will be in the table too. Remove * the old one and add the new one. */ if (dfp) { xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); } /* * Otherwise we need a scan if the new entry is big enough. */ else { needscan = be16_to_cpu(newdup->length) > be16_to_cpu(bf[2].length); } } /* * Neither neighbor is free. Make a new entry. */ else { newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); newdup->length = cpu_to_be16(len); *xfs_dir2_data_unused_tag_p(newdup) = cpu_to_be16((char *)newdup - (char *)hdr); xfs_dir2_data_log_unused(args, bp, newdup); xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); } *needscanp = needscan; } /* * Take a byte range out of an existing unused space and make it un-free. */ void xfs_dir2_data_use_free( struct xfs_da_args *args, struct xfs_buf *bp, xfs_dir2_data_unused_t *dup, /* unused entry */ xfs_dir2_data_aoff_t offset, /* starting offset to use */ xfs_dir2_data_aoff_t len, /* length to use */ int *needlogp, /* out: need to log header */ int *needscanp) /* out: need regen bestfree */ { xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_data_free_t *dfp; /* bestfree pointer */ int matchback; /* matches end of freespace */ int matchfront; /* matches start of freespace */ int needscan; /* need to regen bestfree */ xfs_dir2_data_unused_t *newdup; /* new unused entry */ xfs_dir2_data_unused_t *newdup2; /* another new unused entry */ int oldlen; /* old unused entry's length */ struct xfs_dir2_data_free *bf; hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG); ASSERT(offset >= (char *)dup - (char *)hdr); ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)hdr); ASSERT((char *)dup - (char *)hdr == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup))); /* * Look up the entry in the bestfree table. */ oldlen = be16_to_cpu(dup->length); bf = args->dp->d_ops->data_bestfree_p(hdr); dfp = xfs_dir2_data_freefind(hdr, bf, dup); ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length)); /* * Check for alignment with front and back of the entry. */ matchfront = (char *)dup - (char *)hdr == offset; matchback = (char *)dup + oldlen - (char *)hdr == offset + len; ASSERT(*needscanp == 0); needscan = 0; /* * If we matched it exactly we just need to get rid of it from * the bestfree table. */ if (matchfront && matchback) { if (dfp) { needscan = (bf[2].offset != 0); if (!needscan) xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); } } /* * We match the first part of the entry. * Make a new entry with the remaining freespace. */ else if (matchfront) { newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); newdup->length = cpu_to_be16(oldlen - len); *xfs_dir2_data_unused_tag_p(newdup) = cpu_to_be16((char *)newdup - (char *)hdr); xfs_dir2_data_log_unused(args, bp, newdup); /* * If it was in the table, remove it and add the new one. */ if (dfp) { xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); ASSERT(dfp != NULL); ASSERT(dfp->length == newdup->length); ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr); /* * If we got inserted at the last slot, * that means we don't know if there was a better * choice for the last slot, or not. Rescan. */ needscan = dfp == &bf[2]; } } /* * We match the last part of the entry. * Trim the allocated space off the tail of the entry. */ else if (matchback) { newdup = dup; newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); *xfs_dir2_data_unused_tag_p(newdup) = cpu_to_be16((char *)newdup - (char *)hdr); xfs_dir2_data_log_unused(args, bp, newdup); /* * If it was in the table, remove it and add the new one. */ if (dfp) { xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); ASSERT(dfp != NULL); ASSERT(dfp->length == newdup->length); ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr); /* * If we got inserted at the last slot, * that means we don't know if there was a better * choice for the last slot, or not. Rescan. */ needscan = dfp == &bf[2]; } } /* * Poking out the middle of an entry. * Make two new entries. */ else { newdup = dup; newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); *xfs_dir2_data_unused_tag_p(newdup) = cpu_to_be16((char *)newdup - (char *)hdr); xfs_dir2_data_log_unused(args, bp, newdup); newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length)); *xfs_dir2_data_unused_tag_p(newdup2) = cpu_to_be16((char *)newdup2 - (char *)hdr); xfs_dir2_data_log_unused(args, bp, newdup2); /* * If the old entry was in the table, we need to scan * if the 3rd entry was valid, since these entries * are smaller than the old one. * If we don't need to scan that means there were 1 or 2 * entries in the table, and removing the old and adding * the 2 new will work. */ if (dfp) { needscan = (bf[2].length != 0); if (!needscan) { xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); xfs_dir2_data_freeinsert(hdr, bf, newdup2, needlogp); } } } *needscanp = needscan; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2_leaf.c0000644000000000000000000014342613063067171016646 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trace.h" #include "xfs_trans.h" #include "xfs_cksum.h" /* * Local function declarations. */ static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, int *indexp, struct xfs_buf **dbpp); static void xfs_dir3_leaf_log_bests(struct xfs_da_args *args, struct xfs_buf *bp, int first, int last); static void xfs_dir3_leaf_log_tail(struct xfs_da_args *args, struct xfs_buf *bp); /* * Check the internal consistency of a leaf1 block. * Pop an assert if something is wrong. */ #ifdef DEBUG #define xfs_dir3_leaf_check(dp, bp) \ do { \ if (!xfs_dir3_leaf1_check((dp), (bp))) \ ASSERT(0); \ } while (0); STATIC bool xfs_dir3_leaf1_check( struct xfs_inode *dp, struct xfs_buf *bp) { struct xfs_dir2_leaf *leaf = bp->b_addr; struct xfs_dir3_icleaf_hdr leafhdr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) { struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) return false; } else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC) return false; return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf); } #else #define xfs_dir3_leaf_check(dp, bp) #endif bool xfs_dir3_leaf_check_int( struct xfs_mount *mp, struct xfs_inode *dp, struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf) { struct xfs_dir2_leaf_entry *ents; xfs_dir2_leaf_tail_t *ltp; int stale; int i; const struct xfs_dir_ops *ops; struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_da_geometry *geo = mp->m_dir_geo; /* * we can be passed a null dp here from a verifier, so we need to go the * hard way to get them. */ ops = xfs_dir_get_ops(mp, dp); if (!hdr) { ops->leaf_hdr_from_disk(&leafhdr, leaf); hdr = &leafhdr; } ents = ops->leaf_ents_p(leaf); ltp = xfs_dir2_leaf_tail_p(geo, leaf); /* * XXX (dgc): This value is not restrictive enough. * Should factor in the size of the bests table as well. * We can deduce a value for that from di_size. */ if (hdr->count > ops->leaf_max_ents(geo)) return false; /* Leaves and bests don't overlap in leaf format. */ if ((hdr->magic == XFS_DIR2_LEAF1_MAGIC || hdr->magic == XFS_DIR3_LEAF1_MAGIC) && (char *)&ents[hdr->count] > (char *)xfs_dir2_leaf_bests_p(ltp)) return false; /* Check hash value order, count stale entries. */ for (i = stale = 0; i < hdr->count; i++) { if (i + 1 < hdr->count) { if (be32_to_cpu(ents[i].hashval) > be32_to_cpu(ents[i + 1].hashval)) return false; } if (ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) stale++; } if (hdr->stale != stale) return false; return true; } /* * We verify the magic numbers before decoding the leaf header so that on debug * kernels we don't get assertion failures in xfs_dir3_leaf_hdr_from_disk() due * to incorrect magic numbers. */ static bool xfs_dir3_leaf_verify( struct xfs_buf *bp, __uint16_t magic) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_dir2_leaf *leaf = bp->b_addr; ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; __uint16_t magic3; magic3 = (magic == XFS_DIR2_LEAF1_MAGIC) ? XFS_DIR3_LEAF1_MAGIC : XFS_DIR3_LEAFN_MAGIC; if (leaf3->info.hdr.magic != cpu_to_be16(magic3)) return false; if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(leaf3->info.lsn))) return false; } else { if (leaf->hdr.info.magic != cpu_to_be16(magic)) return false; } return xfs_dir3_leaf_check_int(mp, NULL, NULL, leaf); } static void __read_verify( struct xfs_buf *bp, __uint16_t magic) { struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&mp->m_sb) && !xfs_buf_verify_cksum(bp, XFS_DIR3_LEAF_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_dir3_leaf_verify(bp, magic)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void __write_verify( struct xfs_buf *bp, __uint16_t magic) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr; if (!xfs_dir3_leaf_verify(bp, magic)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_DIR3_LEAF_CRC_OFF); } static void xfs_dir3_leaf1_read_verify( struct xfs_buf *bp) { __read_verify(bp, XFS_DIR2_LEAF1_MAGIC); } static void xfs_dir3_leaf1_write_verify( struct xfs_buf *bp) { __write_verify(bp, XFS_DIR2_LEAF1_MAGIC); } static void xfs_dir3_leafn_read_verify( struct xfs_buf *bp) { __read_verify(bp, XFS_DIR2_LEAFN_MAGIC); } static void xfs_dir3_leafn_write_verify( struct xfs_buf *bp) { __write_verify(bp, XFS_DIR2_LEAFN_MAGIC); } const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = { .name = "xfs_dir3_leaf1", .verify_read = xfs_dir3_leaf1_read_verify, .verify_write = xfs_dir3_leaf1_write_verify, }; const struct xfs_buf_ops xfs_dir3_leafn_buf_ops = { .name = "xfs_dir3_leafn", .verify_read = xfs_dir3_leafn_read_verify, .verify_write = xfs_dir3_leafn_write_verify, }; static int xfs_dir3_leaf_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, xfs_daddr_t mappedbno, struct xfs_buf **bpp) { int err; err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops); if (!err && tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_LEAF1_BUF); return err; } int xfs_dir3_leafn_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, xfs_daddr_t mappedbno, struct xfs_buf **bpp) { int err; err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops); if (!err && tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_LEAFN_BUF); return err; } /* * Initialize a new leaf block, leaf1 or leafn magic accepted. */ static void xfs_dir3_leaf_init( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *bp, xfs_ino_t owner, __uint16_t type) { struct xfs_dir2_leaf *leaf = bp->b_addr; ASSERT(type == XFS_DIR2_LEAF1_MAGIC || type == XFS_DIR2_LEAFN_MAGIC); if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; memset(leaf3, 0, sizeof(*leaf3)); leaf3->info.hdr.magic = (type == XFS_DIR2_LEAF1_MAGIC) ? cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) : cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); leaf3->info.blkno = cpu_to_be64(bp->b_bn); leaf3->info.owner = cpu_to_be64(owner); uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid); } else { memset(leaf, 0, sizeof(*leaf)); leaf->hdr.info.magic = cpu_to_be16(type); } /* * If it's a leaf-format directory initialize the tail. * Caller is responsible for initialising the bests table. */ if (type == XFS_DIR2_LEAF1_MAGIC) { struct xfs_dir2_leaf_tail *ltp; ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); ltp->bestcount = 0; bp->b_ops = &xfs_dir3_leaf1_buf_ops; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAF1_BUF); } else { bp->b_ops = &xfs_dir3_leafn_buf_ops; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAFN_BUF); } } int xfs_dir3_leaf_get_buf( xfs_da_args_t *args, xfs_dir2_db_t bno, struct xfs_buf **bpp, __uint16_t magic) { struct xfs_inode *dp = args->dp; struct xfs_trans *tp = args->trans; struct xfs_mount *mp = dp->i_mount; struct xfs_buf *bp; int error; ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); ASSERT(bno >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET) && bno < xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)); error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, bno), -1, &bp, XFS_DATA_FORK); if (error) return error; xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic); xfs_dir3_leaf_log_header(args, bp); if (magic == XFS_DIR2_LEAF1_MAGIC) xfs_dir3_leaf_log_tail(args, bp); *bpp = bp; return 0; } /* * Convert a block form directory to a leaf form directory. */ int /* error */ xfs_dir2_block_to_leaf( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *dbp) /* input block's buffer */ { __be16 *bestsp; /* leaf's bestsp entries */ xfs_dablk_t blkno; /* leaf block's bno */ xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block's leaf entries */ xfs_dir2_block_tail_t *btp; /* block's tail */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ struct xfs_buf *lbp; /* leaf block's buffer */ xfs_dir2_db_t ldb; /* leaf block's bno */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf's tail */ int needlog; /* need to log block header */ int needscan; /* need to rescan bestfree */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir2_data_free *bf; struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; trace_xfs_dir2_block_to_leaf(args); dp = args->dp; tp = args->trans; /* * Add the leaf block to the inode. * This interface will only put blocks in the leaf/node range. * Since that's empty now, we'll get the root (block 0 in range). */ if ((error = xfs_da_grow_inode(args, &blkno))) { return error; } ldb = xfs_dir2_da_to_db(args->geo, blkno); ASSERT(ldb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET)); /* * Initialize the leaf block, get a buffer for it. */ error = xfs_dir3_leaf_get_buf(args, ldb, &lbp, XFS_DIR2_LEAF1_MAGIC); if (error) return error; leaf = lbp->b_addr; hdr = dbp->b_addr; xfs_dir3_data_check(dp, dbp); btp = xfs_dir2_block_tail_p(args->geo, hdr); blp = xfs_dir2_block_leaf_p(btp); bf = dp->d_ops->data_bestfree_p(hdr); ents = dp->d_ops->leaf_ents_p(leaf); /* * Set the counts in the leaf header. */ dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); leafhdr.count = be32_to_cpu(btp->count); leafhdr.stale = be32_to_cpu(btp->stale); dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(args, lbp); /* * Could compact these but I think we always do the conversion * after squeezing out stale entries. */ memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); xfs_dir3_leaf_log_ents(args, lbp, 0, leafhdr.count - 1); needscan = 0; needlog = 1; /* * Make the space formerly occupied by the leaf entries and block * tail be free. */ xfs_dir2_data_make_free(args, dbp, (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), (xfs_dir2_data_aoff_t)((char *)hdr + args->geo->blksize - (char *)blp), &needlog, &needscan); /* * Fix up the block header, make it a data block. */ dbp->b_ops = &xfs_dir3_data_buf_ops; xfs_trans_buf_set_type(tp, dbp, XFS_BLFT_DIR_DATA_BUF); if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); else hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); /* * Set up leaf tail and bests table. */ ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); ltp->bestcount = cpu_to_be32(1); bestsp = xfs_dir2_leaf_bests_p(ltp); bestsp[0] = bf[0].length; /* * Log the data header and leaf bests table. */ if (needlog) xfs_dir2_data_log_header(args, dbp); xfs_dir3_leaf_check(dp, lbp); xfs_dir3_data_check(dp, dbp); xfs_dir3_leaf_log_bests(args, lbp, 0, 0); return 0; } STATIC void xfs_dir3_leaf_find_stale( struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_dir2_leaf_entry *ents, int index, int *lowstale, int *highstale) { /* * Find the first stale entry before our index, if any. */ for (*lowstale = index - 1; *lowstale >= 0; --*lowstale) { if (ents[*lowstale].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) break; } /* * Find the first stale entry at or after our index, if any. * Stop if the result would require moving more entries than using * lowstale. */ for (*highstale = index; *highstale < leafhdr->count; ++*highstale) { if (ents[*highstale].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) break; if (*lowstale >= 0 && index - *lowstale <= *highstale - index) break; } } struct xfs_dir2_leaf_entry * xfs_dir3_leaf_find_entry( struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_dir2_leaf_entry *ents, int index, /* leaf table position */ int compact, /* need to compact leaves */ int lowstale, /* index of prev stale leaf */ int highstale, /* index of next stale leaf */ int *lfloglow, /* low leaf logging index */ int *lfloghigh) /* high leaf logging index */ { if (!leafhdr->stale) { xfs_dir2_leaf_entry_t *lep; /* leaf entry table pointer */ /* * Now we need to make room to insert the leaf entry. * * If there are no stale entries, just insert a hole at index. */ lep = &ents[index]; if (index < leafhdr->count) memmove(lep + 1, lep, (leafhdr->count - index) * sizeof(*lep)); /* * Record low and high logging indices for the leaf. */ *lfloglow = index; *lfloghigh = leafhdr->count++; return lep; } /* * There are stale entries. * * We will use one of them for the new entry. It's probably not at * the right location, so we'll have to shift some up or down first. * * If we didn't compact before, we need to find the nearest stale * entries before and after our insertion point. */ if (compact == 0) xfs_dir3_leaf_find_stale(leafhdr, ents, index, &lowstale, &highstale); /* * If the low one is better, use it. */ if (lowstale >= 0 && (highstale == leafhdr->count || index - lowstale - 1 < highstale - index)) { ASSERT(index - lowstale - 1 >= 0); ASSERT(ents[lowstale].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); /* * Copy entries up to cover the stale entry and make room * for the new entry. */ if (index - lowstale - 1 > 0) { memmove(&ents[lowstale], &ents[lowstale + 1], (index - lowstale - 1) * sizeof(xfs_dir2_leaf_entry_t)); } *lfloglow = MIN(lowstale, *lfloglow); *lfloghigh = MAX(index - 1, *lfloghigh); leafhdr->stale--; return &ents[index - 1]; } /* * The high one is better, so use that one. */ ASSERT(highstale - index >= 0); ASSERT(ents[highstale].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); /* * Copy entries down to cover the stale entry and make room for the * new entry. */ if (highstale - index > 0) { memmove(&ents[index + 1], &ents[index], (highstale - index) * sizeof(xfs_dir2_leaf_entry_t)); } *lfloglow = MIN(index, *lfloglow); *lfloghigh = MAX(highstale, *lfloghigh); leafhdr->stale--; return &ents[index]; } /* * Add an entry to a leaf form directory. */ int /* error */ xfs_dir2_leaf_addname( xfs_da_args_t *args) /* operation arguments */ { __be16 *bestsp; /* freespace table in leaf */ int compact; /* need to compact leaves */ xfs_dir2_data_hdr_t *hdr; /* data block header */ struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* data unused entry */ int error; /* error return value */ int grown; /* allocated new data block */ int highstale; /* index of next stale leaf */ int i; /* temporary, index */ int index; /* leaf table position */ struct xfs_buf *lbp; /* leaf's buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ int length; /* length of new entry */ xfs_dir2_leaf_entry_t *lep; /* leaf entry table pointer */ int lfloglow; /* low leaf logging index */ int lfloghigh; /* high leaf logging index */ int lowstale; /* index of prev stale leaf */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail pointer */ int needbytes; /* leaf block bytes needed */ int needlog; /* need to log data header */ int needscan; /* need to rescan data free */ __be16 *tagp; /* end of data entry */ xfs_trans_t *tp; /* transaction pointer */ xfs_dir2_db_t use_block; /* data block number */ struct xfs_dir2_data_free *bf; /* bestfree table */ struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; trace_xfs_dir2_leaf_addname(args); dp = args->dp; tp = args->trans; error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, -1, &lbp); if (error) return error; /* * Look up the entry by hash value and name. * We know it's not there, our caller has already done a lookup. * So the index is of the entry to insert in front of. * But if there are dup hash values the index is of the first of those. */ index = xfs_dir2_leaf_search_hash(args, lbp); leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); ents = dp->d_ops->leaf_ents_p(leaf); dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); length = dp->d_ops->data_entsize(args->namelen); /* * See if there are any entries with the same hash value * and space in their block for the new entry. * This is good because it puts multiple same-hash value entries * in a data block, improving the lookup of those entries. */ for (use_block = -1, lep = &ents[index]; index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; index++, lep++) { if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; i = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); ASSERT(i < be32_to_cpu(ltp->bestcount)); ASSERT(bestsp[i] != cpu_to_be16(NULLDATAOFF)); if (be16_to_cpu(bestsp[i]) >= length) { use_block = i; break; } } /* * Didn't find a block yet, linear search all the data blocks. */ if (use_block == -1) { for (i = 0; i < be32_to_cpu(ltp->bestcount); i++) { /* * Remember a block we see that's missing. */ if (bestsp[i] == cpu_to_be16(NULLDATAOFF) && use_block == -1) use_block = i; else if (be16_to_cpu(bestsp[i]) >= length) { use_block = i; break; } } } /* * How many bytes do we need in the leaf block? */ needbytes = 0; if (!leafhdr.stale) needbytes += sizeof(xfs_dir2_leaf_entry_t); if (use_block == -1) needbytes += sizeof(xfs_dir2_data_off_t); /* * Now kill use_block if it refers to a missing block, so we * can use it as an indication of allocation needed. */ if (use_block != -1 && bestsp[use_block] == cpu_to_be16(NULLDATAOFF)) use_block = -1; /* * If we don't have enough free bytes but we can make enough * by compacting out stale entries, we'll do that. */ if ((char *)bestsp - (char *)&ents[leafhdr.count] < needbytes && leafhdr.stale > 1) compact = 1; /* * Otherwise if we don't have enough free bytes we need to * convert to node form. */ else if ((char *)bestsp - (char *)&ents[leafhdr.count] < needbytes) { /* * Just checking or no space reservation, give up. */ if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) { xfs_trans_brelse(tp, lbp); return -ENOSPC; } /* * Convert to node form. */ error = xfs_dir2_leaf_to_node(args, lbp); if (error) return error; /* * Then add the new entry. */ return xfs_dir2_node_addname(args); } /* * Otherwise it will fit without compaction. */ else compact = 0; /* * If just checking, then it will fit unless we needed to allocate * a new data block. */ if (args->op_flags & XFS_DA_OP_JUSTCHECK) { xfs_trans_brelse(tp, lbp); return use_block == -1 ? -ENOSPC : 0; } /* * If no allocations are allowed, return now before we've * changed anything. */ if (args->total == 0 && use_block == -1) { xfs_trans_brelse(tp, lbp); return -ENOSPC; } /* * Need to compact the leaf entries, removing stale ones. * Leave one stale entry behind - the one closest to our * insertion index - and we'll shift that one to our insertion * point later. */ if (compact) { xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale, &highstale, &lfloglow, &lfloghigh); } /* * There are stale entries, so we'll need log-low and log-high * impossibly bad values later. */ else if (leafhdr.stale) { lfloglow = leafhdr.count; lfloghigh = -1; } /* * If there was no data block space found, we need to allocate * a new one. */ if (use_block == -1) { /* * Add the new data block. */ if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &use_block))) { xfs_trans_brelse(tp, lbp); return error; } /* * Initialize the block. */ if ((error = xfs_dir3_data_init(args, use_block, &dbp))) { xfs_trans_brelse(tp, lbp); return error; } /* * If we're adding a new data block on the end we need to * extend the bests table. Copy it up one entry. */ if (use_block >= be32_to_cpu(ltp->bestcount)) { bestsp--; memmove(&bestsp[0], &bestsp[1], be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); be32_add_cpu(<p->bestcount, 1); xfs_dir3_leaf_log_tail(args, lbp); xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); } /* * If we're filling in a previously empty block just log it. */ else xfs_dir3_leaf_log_bests(args, lbp, use_block, use_block); hdr = dbp->b_addr; bf = dp->d_ops->data_bestfree_p(hdr); bestsp[use_block] = bf[0].length; grown = 1; } else { /* * Already had space in some data block. * Just read that one in. */ error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, use_block), -1, &dbp); if (error) { xfs_trans_brelse(tp, lbp); return error; } hdr = dbp->b_addr; bf = dp->d_ops->data_bestfree_p(hdr); grown = 0; } /* * Point to the biggest freespace in our data block. */ dup = (xfs_dir2_data_unused_t *) ((char *)hdr + be16_to_cpu(bf[0].offset)); ASSERT(be16_to_cpu(dup->length) >= length); needscan = needlog = 0; /* * Mark the initial part of our freespace in use for the new entry. */ xfs_dir2_data_use_free(args, dbp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, &needlog, &needscan); /* * Initialize our new entry (at last). */ dep = (xfs_dir2_data_entry_t *)dup; dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); dp->d_ops->data_put_ftype(dep, args->filetype); tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); /* * Need to scan fix up the bestfree table. */ if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); /* * Need to log the data block's header. */ if (needlog) xfs_dir2_data_log_header(args, dbp); xfs_dir2_data_log_entry(args, dbp, dep); /* * If the bests table needs to be changed, do it. * Log the change unless we've already done that. */ if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { bestsp[use_block] = bf[0].length; if (!grown) xfs_dir3_leaf_log_bests(args, lbp, use_block, use_block); } lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, highstale, &lfloglow, &lfloghigh); /* * Fill in the new leaf entry. */ lep->hashval = cpu_to_be32(args->hashval); lep->address = cpu_to_be32( xfs_dir2_db_off_to_dataptr(args->geo, use_block, be16_to_cpu(*tagp))); /* * Log the leaf fields and give up the buffers. */ dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(args, lbp); xfs_dir3_leaf_log_ents(args, lbp, lfloglow, lfloghigh); xfs_dir3_leaf_check(dp, lbp); xfs_dir3_data_check(dp, dbp); return 0; } /* * Compact out any stale entries in the leaf. * Log the header and changed leaf entries, if any. */ void xfs_dir3_leaf_compact( xfs_da_args_t *args, /* operation arguments */ struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_buf *bp) /* leaf buffer */ { int from; /* source leaf index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ int loglow; /* first leaf entry to log */ int to; /* target leaf index */ struct xfs_dir2_leaf_entry *ents; struct xfs_inode *dp = args->dp; leaf = bp->b_addr; if (!leafhdr->stale) return; /* * Compress out the stale entries in place. */ ents = dp->d_ops->leaf_ents_p(leaf); for (from = to = 0, loglow = -1; from < leafhdr->count; from++) { if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) continue; /* * Only actually copy the entries that are different. */ if (from > to) { if (loglow == -1) loglow = to; ents[to] = ents[from]; } to++; } /* * Update and log the header, log the leaf entries. */ ASSERT(leafhdr->stale == from - to); leafhdr->count -= leafhdr->stale; leafhdr->stale = 0; dp->d_ops->leaf_hdr_to_disk(leaf, leafhdr); xfs_dir3_leaf_log_header(args, bp); if (loglow != -1) xfs_dir3_leaf_log_ents(args, bp, loglow, to - 1); } /* * Compact the leaf entries, removing stale ones. * Leave one stale entry behind - the one closest to our * insertion index - and the caller will shift that one to our insertion * point later. * Return new insertion index, where the remaining stale entry is, * and leaf logging indices. */ void xfs_dir3_leaf_compact_x1( struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_dir2_leaf_entry *ents, int *indexp, /* insertion index */ int *lowstalep, /* out: stale entry before us */ int *highstalep, /* out: stale entry after us */ int *lowlogp, /* out: low log index */ int *highlogp) /* out: high log index */ { int from; /* source copy index */ int highstale; /* stale entry at/after index */ int index; /* insertion index */ int keepstale; /* source index of kept stale */ int lowstale; /* stale entry before index */ int newindex=0; /* new insertion index */ int to; /* destination copy index */ ASSERT(leafhdr->stale > 1); index = *indexp; xfs_dir3_leaf_find_stale(leafhdr, ents, index, &lowstale, &highstale); /* * Pick the better of lowstale and highstale. */ if (lowstale >= 0 && (highstale == leafhdr->count || index - lowstale <= highstale - index)) keepstale = lowstale; else keepstale = highstale; /* * Copy the entries in place, removing all the stale entries * except keepstale. */ for (from = to = 0; from < leafhdr->count; from++) { /* * Notice the new value of index. */ if (index == from) newindex = to; if (from != keepstale && ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) { if (from == to) *lowlogp = to; continue; } /* * Record the new keepstale value for the insertion. */ if (from == keepstale) lowstale = highstale = to; /* * Copy only the entries that have moved. */ if (from > to) ents[to] = ents[from]; to++; } ASSERT(from > to); /* * If the insertion point was past the last entry, * set the new insertion point accordingly. */ if (index == from) newindex = to; *indexp = newindex; /* * Adjust the leaf header values. */ leafhdr->count -= from - to; leafhdr->stale = 1; /* * Remember the low/high stale value only in the "right" * direction. */ if (lowstale >= newindex) lowstale = -1; else highstale = leafhdr->count; *highlogp = leafhdr->count - 1; *lowstalep = lowstale; *highstalep = highstale; } /* * Log the bests entries indicated from a leaf1 block. */ static void xfs_dir3_leaf_log_bests( struct xfs_da_args *args, struct xfs_buf *bp, /* leaf buffer */ int first, /* first entry to log */ int last) /* last entry to log */ { __be16 *firstb; /* pointer to first entry */ __be16 *lastb; /* pointer to last entry */ struct xfs_dir2_leaf *leaf = bp->b_addr; xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC)); ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); firstb = xfs_dir2_leaf_bests_p(ltp) + first; lastb = xfs_dir2_leaf_bests_p(ltp) + last; xfs_trans_log_buf(args->trans, bp, (uint)((char *)firstb - (char *)leaf), (uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1)); } /* * Log the leaf entries indicated from a leaf1 or leafn block. */ void xfs_dir3_leaf_log_ents( struct xfs_da_args *args, struct xfs_buf *bp, int first, int last) { xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */ xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ struct xfs_dir2_leaf *leaf = bp->b_addr; struct xfs_dir2_leaf_entry *ents; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); ents = args->dp->d_ops->leaf_ents_p(leaf); firstlep = &ents[first]; lastlep = &ents[last]; xfs_trans_log_buf(args->trans, bp, (uint)((char *)firstlep - (char *)leaf), (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); } /* * Log the header of the leaf1 or leafn block. */ void xfs_dir3_leaf_log_header( struct xfs_da_args *args, struct xfs_buf *bp) { struct xfs_dir2_leaf *leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); xfs_trans_log_buf(args->trans, bp, (uint)((char *)&leaf->hdr - (char *)leaf), args->dp->d_ops->leaf_hdr_size - 1); } /* * Log the tail of the leaf1 block. */ STATIC void xfs_dir3_leaf_log_tail( struct xfs_da_args *args, struct xfs_buf *bp) { struct xfs_dir2_leaf *leaf = bp->b_addr; xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); xfs_trans_log_buf(args->trans, bp, (uint)((char *)ltp - (char *)leaf), (uint)(args->geo->blksize - 1)); } /* * Look up the entry referred to by args in the leaf format directory. * Most of the work is done by the xfs_dir2_leaf_lookup_int routine which * is also used by the node-format code. */ int xfs_dir2_leaf_lookup( xfs_da_args_t *args) /* operation arguments */ { struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ int index; /* found entry index */ struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir2_leaf_entry *ents; trace_xfs_dir2_leaf_lookup(args); /* * Look up name in the leaf block, returning both buffers and index. */ if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) { return error; } tp = args->trans; dp = args->dp; xfs_dir3_leaf_check(dp, lbp); leaf = lbp->b_addr; ents = dp->d_ops->leaf_ents_p(leaf); /* * Get to the leaf entry and contained data entry address. */ lep = &ents[index]; /* * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *) ((char *)dbp->b_addr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); /* * Return the found inode number & CI name if appropriate */ args->inumber = be64_to_cpu(dep->inumber); args->filetype = dp->d_ops->data_get_ftype(dep); error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); xfs_trans_brelse(tp, dbp); xfs_trans_brelse(tp, lbp); return error; } /* * Look up name/hash in the leaf block. * Fill in indexp with the found index, and dbpp with the data buffer. * If not found dbpp will be NULL, and ENOENT comes back. * lbpp will always be filled in with the leaf buffer unless there's an error. */ static int /* error */ xfs_dir2_leaf_lookup_int( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf **lbpp, /* out: leaf buffer */ int *indexp, /* out: index in leaf block */ struct xfs_buf **dbpp) /* out: data buffer */ { xfs_dir2_db_t curdb = -1; /* current data block number */ struct xfs_buf *dbp = NULL; /* data buffer */ xfs_dir2_data_entry_t *dep; /* data entry */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ int index; /* index in leaf block */ struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_mount_t *mp; /* filesystem mount point */ xfs_dir2_db_t newdb; /* new data block number */ xfs_trans_t *tp; /* transaction pointer */ xfs_dir2_db_t cidb = -1; /* case match data block no. */ enum xfs_dacmp cmp; /* name compare result */ struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; dp = args->dp; tp = args->trans; mp = dp->i_mount; error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, -1, &lbp); if (error) return error; *lbpp = lbp; leaf = lbp->b_addr; xfs_dir3_leaf_check(dp, lbp); ents = dp->d_ops->leaf_ents_p(leaf); dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); /* * Look for the first leaf entry with our hash value. */ index = xfs_dir2_leaf_search_hash(args, lbp); /* * Loop over all the entries with the right hash value * looking to match the name. */ for (lep = &ents[index]; index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) { /* * Skip over stale leaf entries. */ if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; /* * Get the new data block number. */ newdb = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); /* * If it's not the same as the old data block number, * need to pitch the old one and read the new one. */ if (newdb != curdb) { if (dbp) xfs_trans_brelse(tp, dbp); error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, newdb), -1, &dbp); if (error) { xfs_trans_brelse(tp, lbp); return error; } curdb = newdb; } /* * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *)((char *)dbp->b_addr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); /* * Compare name and if it's an exact match, return the index * and buffer. If it's the first case-insensitive match, store * the index and buffer and continue looking for an exact match. */ cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { args->cmpresult = cmp; *indexp = index; /* case exact match: return the current buffer. */ if (cmp == XFS_CMP_EXACT) { *dbpp = dbp; return 0; } cidb = curdb; } } ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); /* * Here, we can only be doing a lookup (not a rename or remove). * If a case-insensitive match was found earlier, re-read the * appropriate data block if required and return it. */ if (args->cmpresult == XFS_CMP_CASE) { ASSERT(cidb != -1); if (cidb != curdb) { xfs_trans_brelse(tp, dbp); error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, cidb), -1, &dbp); if (error) { xfs_trans_brelse(tp, lbp); return error; } } *dbpp = dbp; return 0; } /* * No match found, return -ENOENT. */ ASSERT(cidb == -1); if (dbp) xfs_trans_brelse(tp, dbp); xfs_trans_brelse(tp, lbp); return -ENOENT; } /* * Remove an entry from a leaf format directory. */ int /* error */ xfs_dir2_leaf_removename( xfs_da_args_t *args) /* operation arguments */ { __be16 *bestsp; /* leaf block best freespace */ xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_db_t db; /* data block number */ struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data entry structure */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ xfs_dir2_db_t i; /* temporary data block # */ int index; /* index into leaf entries */ struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ int needlog; /* need to log data header */ int needscan; /* need to rescan data frees */ xfs_dir2_data_off_t oldbest; /* old value of best free */ struct xfs_dir2_data_free *bf; /* bestfree table */ struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; trace_xfs_dir2_leaf_removename(args); /* * Lookup the leaf entry, get the leaf and data blocks read in. */ if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) { return error; } dp = args->dp; leaf = lbp->b_addr; hdr = dbp->b_addr; xfs_dir3_data_check(dp, dbp); bf = dp->d_ops->data_bestfree_p(hdr); dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the leaf entry, use that to point to the data entry. */ lep = &ents[index]; db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); dep = (xfs_dir2_data_entry_t *)((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); needscan = needlog = 0; oldbest = be16_to_cpu(bf[0].length); ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); ASSERT(be16_to_cpu(bestsp[db]) == oldbest); /* * Mark the former data entry unused. */ xfs_dir2_data_make_free(args, dbp, (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* * We just mark the leaf entry stale by putting a null in it. */ leafhdr.stale++; dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(args, lbp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); xfs_dir3_leaf_log_ents(args, lbp, index, index); /* * Scan the freespace in the data block again if necessary, * log the data block header if necessary. */ if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(args, dbp); /* * If the longest freespace in the data block has changed, * put the new value in the bests table and log that. */ if (be16_to_cpu(bf[0].length) != oldbest) { bestsp[db] = bf[0].length; xfs_dir3_leaf_log_bests(args, lbp, db, db); } xfs_dir3_data_check(dp, dbp); /* * If the data block is now empty then get rid of the data block. */ if (be16_to_cpu(bf[0].length) == args->geo->blksize - dp->d_ops->data_entry_offset) { ASSERT(db != args->geo->datablk); if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { /* * Nope, can't get rid of it because it caused * allocation of a bmap btree block to do so. * Just go on, returning success, leaving the * empty block in place. */ if (error == -ENOSPC && args->total == 0) error = 0; xfs_dir3_leaf_check(dp, lbp); return error; } dbp = NULL; /* * If this is the last data block then compact the * bests table by getting rid of entries. */ if (db == be32_to_cpu(ltp->bestcount) - 1) { /* * Look for the last active entry (i). */ for (i = db - 1; i > 0; i--) { if (bestsp[i] != cpu_to_be16(NULLDATAOFF)) break; } /* * Copy the table down so inactive entries at the * end are removed. */ memmove(&bestsp[db - i], bestsp, (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); be32_add_cpu(<p->bestcount, -(db - i)); xfs_dir3_leaf_log_tail(args, lbp); xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); } else bestsp[db] = cpu_to_be16(NULLDATAOFF); } /* * If the data block was not the first one, drop it. */ else if (db != args->geo->datablk) dbp = NULL; xfs_dir3_leaf_check(dp, lbp); /* * See if we can convert to block form. */ return xfs_dir2_leaf_to_block(args, lbp, dbp); } /* * Replace the inode number in a leaf format directory entry. */ int /* error */ xfs_dir2_leaf_replace( xfs_da_args_t *args) /* operation arguments */ { struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ int index; /* index of leaf entry */ struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir2_leaf_entry *ents; trace_xfs_dir2_leaf_replace(args); /* * Look up the entry. */ if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) { return error; } dp = args->dp; leaf = lbp->b_addr; ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the leaf entry, get data address from it. */ lep = &ents[index]; /* * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *) ((char *)dbp->b_addr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); ASSERT(args->inumber != be64_to_cpu(dep->inumber)); /* * Put the new inode number in, log it. */ dep->inumber = cpu_to_be64(args->inumber); dp->d_ops->data_put_ftype(dep, args->filetype); tp = args->trans; xfs_dir2_data_log_entry(args, dbp, dep); xfs_dir3_leaf_check(dp, lbp); xfs_trans_brelse(tp, lbp); return 0; } /* * Return index in the leaf block (lbp) which is either the first * one with this hash value, or if there are none, the insert point * for that hash value. */ int /* index value */ xfs_dir2_leaf_search_hash( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *lbp) /* leaf buffer */ { xfs_dahash_t hash=0; /* hash from this entry */ xfs_dahash_t hashwant; /* hash value looking for */ int high; /* high leaf index */ int low; /* low leaf index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ int mid=0; /* current leaf index */ struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; leaf = lbp->b_addr; ents = args->dp->d_ops->leaf_ents_p(leaf); args->dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); /* * Note, the table cannot be empty, so we have to go through the loop. * Binary search the leaf entries looking for our hash value. */ for (lep = ents, low = 0, high = leafhdr.count - 1, hashwant = args->hashval; low <= high; ) { mid = (low + high) >> 1; if ((hash = be32_to_cpu(lep[mid].hashval)) == hashwant) break; if (hash < hashwant) low = mid + 1; else high = mid - 1; } /* * Found one, back up through all the equal hash values. */ if (hash == hashwant) { while (mid > 0 && be32_to_cpu(lep[mid - 1].hashval) == hashwant) { mid--; } } /* * Need to point to an entry higher than ours. */ else if (hash < hashwant) mid++; return mid; } /* * Trim off a trailing data block. We know it's empty since the leaf * freespace table says so. */ int /* error */ xfs_dir2_leaf_trim_data( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *lbp, /* leaf buffer */ xfs_dir2_db_t db) /* data block number */ { __be16 *bestsp; /* leaf bests table */ struct xfs_buf *dbp; /* data block buffer */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return value */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ xfs_trans_t *tp; /* transaction pointer */ dp = args->dp; tp = args->trans; /* * Read the offending data block. We need its buffer. */ error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, db), -1, &dbp); if (error) return error; leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); #ifdef DEBUG { struct xfs_dir2_data_hdr *hdr = dbp->b_addr; struct xfs_dir2_data_free *bf = dp->d_ops->data_bestfree_p(hdr); ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); ASSERT(be16_to_cpu(bf[0].length) == args->geo->blksize - dp->d_ops->data_entry_offset); ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); } #endif /* * Get rid of the data block. */ if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { ASSERT(error != -ENOSPC); xfs_trans_brelse(tp, dbp); return error; } /* * Eliminate the last bests entry from the table. */ bestsp = xfs_dir2_leaf_bests_p(ltp); be32_add_cpu(<p->bestcount, -1); memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); xfs_dir3_leaf_log_tail(args, lbp); xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); return 0; } static inline size_t xfs_dir3_leaf_size( struct xfs_dir3_icleaf_hdr *hdr, int counts) { int entries; int hdrsize; entries = hdr->count - hdr->stale; if (hdr->magic == XFS_DIR2_LEAF1_MAGIC || hdr->magic == XFS_DIR2_LEAFN_MAGIC) hdrsize = sizeof(struct xfs_dir2_leaf_hdr); else hdrsize = sizeof(struct xfs_dir3_leaf_hdr); return hdrsize + entries * sizeof(xfs_dir2_leaf_entry_t) + counts * sizeof(xfs_dir2_data_off_t) + sizeof(xfs_dir2_leaf_tail_t); } /* * Convert node form directory to leaf form directory. * The root of the node form dir needs to already be a LEAFN block. * Just return if we can't do anything. */ int /* error */ xfs_dir2_node_to_leaf( xfs_da_state_t *state) /* directory operation state */ { xfs_da_args_t *args; /* operation arguments */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ struct xfs_buf *fbp; /* buffer for freespace block */ xfs_fileoff_t fo; /* freespace file offset */ xfs_dir2_free_t *free; /* freespace structure */ struct xfs_buf *lbp; /* buffer for leaf block */ xfs_dir2_leaf_tail_t *ltp; /* tail of leaf structure */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_mount_t *mp; /* filesystem mount point */ int rval; /* successful free trim? */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir3_icfree_hdr freehdr; /* * There's more than a leaf level in the btree, so there must * be multiple leafn blocks. Give up. */ if (state->path.active > 1) return 0; args = state->args; trace_xfs_dir2_node_to_leaf(args); mp = state->mp; dp = args->dp; tp = args->trans; /* * Get the last offset in the file. */ if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK))) { return error; } fo -= args->geo->fsbcount; /* * If there are freespace blocks other than the first one, * take this opportunity to remove trailing empty freespace blocks * that may have been left behind during no-space-reservation * operations. */ while (fo > args->geo->freeblk) { if ((error = xfs_dir2_node_trim_free(args, fo, &rval))) { return error; } if (rval) fo -= args->geo->fsbcount; else return 0; } /* * Now find the block just before the freespace block. */ if ((error = xfs_bmap_last_before(tp, dp, &fo, XFS_DATA_FORK))) { return error; } /* * If it's not the single leaf block, give up. */ if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + args->geo->blksize) return 0; lbp = state->path.blk[0].bp; leaf = lbp->b_addr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); /* * Read the freespace block. */ error = xfs_dir2_free_read(tp, dp, args->geo->freeblk, &fbp); if (error) return error; free = fbp->b_addr; dp->d_ops->free_hdr_from_disk(&freehdr, free); ASSERT(!freehdr.firstdb); /* * Now see if the leafn and free data will fit in a leaf1. * If not, release the buffer and give up. */ if (xfs_dir3_leaf_size(&leafhdr, freehdr.nvalid) > args->geo->blksize) { xfs_trans_brelse(tp, fbp); return 0; } /* * If the leaf has any stale entries in it, compress them out. */ if (leafhdr.stale) xfs_dir3_leaf_compact(args, &leafhdr, lbp); lbp->b_ops = &xfs_dir3_leaf1_buf_ops; xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAF1_BUF); leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC) ? XFS_DIR2_LEAF1_MAGIC : XFS_DIR3_LEAF1_MAGIC; /* * Set up the leaf tail from the freespace block. */ ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); ltp->bestcount = cpu_to_be32(freehdr.nvalid); /* * Set up the leaf bests table. */ memcpy(xfs_dir2_leaf_bests_p(ltp), dp->d_ops->free_bests_p(free), freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(args, lbp); xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); xfs_dir3_leaf_log_tail(args, lbp); xfs_dir3_leaf_check(dp, lbp); /* * Get rid of the freespace block. */ error = xfs_dir2_shrink_inode(args, xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET), fbp); if (error) { /* * This can't fail here because it can only happen when * punching out the middle of an extent, and this is an * isolated block. */ ASSERT(error != -ENOSPC); return error; } fbp = NULL; /* * Now see if we can convert the single-leaf directory * down to a block form directory. * This routine always kills the dabuf for the leaf, so * eliminate it from the path. */ error = xfs_dir2_leaf_to_block(args, lbp, NULL); state->path.blk[0].bp = NULL; return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2_node.c0000644000000000000000000017360113063067171016662 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trace.h" #include "xfs_trans.h" #include "xfs_cksum.h" /* * Function declarations. */ static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args, int index); static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_da_state_blk_t *blk2); static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, int index, xfs_da_state_blk_t *dblk, int *rval); static int xfs_dir2_node_addname_int(xfs_da_args_t *args, xfs_da_state_blk_t *fblk); /* * Check internal consistency of a leafn block. */ #ifdef DEBUG #define xfs_dir3_leaf_check(dp, bp) \ do { \ if (!xfs_dir3_leafn_check((dp), (bp))) \ ASSERT(0); \ } while (0); static bool xfs_dir3_leafn_check( struct xfs_inode *dp, struct xfs_buf *bp) { struct xfs_dir2_leaf *leaf = bp->b_addr; struct xfs_dir3_icleaf_hdr leafhdr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) { struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) return false; } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC) return false; return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf); } #else #define xfs_dir3_leaf_check(dp, bp) #endif static bool xfs_dir3_free_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_dir2_free_hdr *hdr = bp->b_addr; if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)) return false; if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) return false; if (be64_to_cpu(hdr3->blkno) != bp->b_bn) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn))) return false; } else { if (hdr->magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)) return false; } /* XXX: should bounds check the xfs_dir3_icfree_hdr here */ return true; } static void xfs_dir3_free_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&mp->m_sb) && !xfs_buf_verify_cksum(bp, XFS_DIR3_FREE_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_dir3_free_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void xfs_dir3_free_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; if (!xfs_dir3_free_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_DIR3_FREE_CRC_OFF); } const struct xfs_buf_ops xfs_dir3_free_buf_ops = { .name = "xfs_dir3_free", .verify_read = xfs_dir3_free_read_verify, .verify_write = xfs_dir3_free_write_verify, }; static int __xfs_dir3_free_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, xfs_daddr_t mappedbno, struct xfs_buf **bpp) { int err; err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, XFS_DATA_FORK, &xfs_dir3_free_buf_ops); /* try read returns without an error or *bpp if it lands in a hole */ if (!err && tp && *bpp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_FREE_BUF); return err; } int xfs_dir2_free_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, struct xfs_buf **bpp) { return __xfs_dir3_free_read(tp, dp, fbno, -1, bpp); } static int xfs_dir2_free_try_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, struct xfs_buf **bpp) { return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp); } static int xfs_dir3_free_get_buf( xfs_da_args_t *args, xfs_dir2_db_t fbno, struct xfs_buf **bpp) { struct xfs_trans *tp = args->trans; struct xfs_inode *dp = args->dp; struct xfs_mount *mp = dp->i_mount; struct xfs_buf *bp; int error; struct xfs_dir3_icfree_hdr hdr; error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, fbno), -1, &bp, XFS_DATA_FORK); if (error) return error; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_FREE_BUF); bp->b_ops = &xfs_dir3_free_buf_ops; /* * Initialize the new block to be empty, and remember * its first slot as our empty slot. */ memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr)); memset(&hdr, 0, sizeof(hdr)); if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; hdr.magic = XFS_DIR3_FREE_MAGIC; hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); hdr3->hdr.owner = cpu_to_be64(dp->i_ino); uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid); } else hdr.magic = XFS_DIR2_FREE_MAGIC; dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr); *bpp = bp; return 0; } /* * Log entries from a freespace block. */ STATIC void xfs_dir2_free_log_bests( struct xfs_da_args *args, struct xfs_buf *bp, int first, /* first entry to log */ int last) /* last entry to log */ { xfs_dir2_free_t *free; /* freespace structure */ __be16 *bests; free = bp->b_addr; bests = args->dp->d_ops->free_bests_p(free); ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); xfs_trans_log_buf(args->trans, bp, (uint)((char *)&bests[first] - (char *)free), (uint)((char *)&bests[last] - (char *)free + sizeof(bests[0]) - 1)); } /* * Log header from a freespace block. */ static void xfs_dir2_free_log_header( struct xfs_da_args *args, struct xfs_buf *bp) { #ifdef DEBUG xfs_dir2_free_t *free; /* freespace structure */ free = bp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); #endif xfs_trans_log_buf(args->trans, bp, 0, args->dp->d_ops->free_hdr_size - 1); } /* * Convert a leaf-format directory to a node-format directory. * We need to change the magic number of the leaf block, and copy * the freespace table out of the leaf block into its own block. */ int /* error */ xfs_dir2_leaf_to_node( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *lbp) /* leaf buffer */ { xfs_inode_t *dp; /* incore directory inode */ int error; /* error return value */ struct xfs_buf *fbp; /* freespace buffer */ xfs_dir2_db_t fdb; /* freespace block number */ xfs_dir2_free_t *free; /* freespace structure */ __be16 *from; /* pointer to freespace entry */ int i; /* leaf freespace index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ int n; /* count of live freespc ents */ xfs_dir2_data_off_t off; /* freespace entry value */ __be16 *to; /* pointer to freespace entry */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir3_icfree_hdr freehdr; trace_xfs_dir2_leaf_to_node(args); dp = args->dp; tp = args->trans; /* * Add a freespace block to the directory. */ if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) { return error; } ASSERT(fdb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)); /* * Get the buffer for the new freespace block. */ error = xfs_dir3_free_get_buf(args, fdb, &fbp); if (error) return error; free = fbp->b_addr; dp->d_ops->free_hdr_from_disk(&freehdr, free); leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); ASSERT(be32_to_cpu(ltp->bestcount) <= (uint)dp->i_d.di_size / args->geo->blksize); /* * Copy freespace entries from the leaf block to the new block. * Count active entries. */ from = xfs_dir2_leaf_bests_p(ltp); to = dp->d_ops->free_bests_p(free); for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { if ((off = be16_to_cpu(*from)) != NULLDATAOFF) n++; *to = cpu_to_be16(off); } /* * Now initialize the freespace block header. */ freehdr.nused = n; freehdr.nvalid = be32_to_cpu(ltp->bestcount); dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1); xfs_dir2_free_log_header(args, fbp); /* * Converting the leaf to a leafnode is just a matter of changing the * magic number and the ops. Do the change directly to the buffer as * it's less work (and less code) than decoding the header to host * format and back again. */ if (leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)) leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); else leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); lbp->b_ops = &xfs_dir3_leafn_buf_ops; xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF); xfs_dir3_leaf_log_header(args, lbp); xfs_dir3_leaf_check(dp, lbp); return 0; } /* * Add a leaf entry to a leaf block in a node-form directory. * The other work necessary is done from the caller. */ static int /* error */ xfs_dir2_leafn_add( struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int index) /* insertion pt for new entry */ { int compact; /* compacting stale leaves */ xfs_inode_t *dp; /* incore directory inode */ int highstale; /* next stale entry */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ int lfloghigh; /* high leaf entry logging */ int lfloglow; /* low leaf entry logging */ int lowstale; /* previous stale entry */ struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir2_leaf_entry *ents; trace_xfs_dir2_leafn_add(args, index); dp = args->dp; leaf = bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* * Quick check just to make sure we are not going to index * into other peoples memory */ if (index < 0) return -EFSCORRUPTED; /* * If there are already the maximum number of leaf entries in * the block, if there are no stale entries it won't fit. * Caller will do a split. If there are stale entries we'll do * a compact. */ if (leafhdr.count == dp->d_ops->leaf_max_ents(args->geo)) { if (!leafhdr.stale) return -ENOSPC; compact = leafhdr.stale > 1; } else compact = 0; ASSERT(index == 0 || be32_to_cpu(ents[index - 1].hashval) <= args->hashval); ASSERT(index == leafhdr.count || be32_to_cpu(ents[index].hashval) >= args->hashval); if (args->op_flags & XFS_DA_OP_JUSTCHECK) return 0; /* * Compact out all but one stale leaf entry. Leaves behind * the entry closest to index. */ if (compact) xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale, &highstale, &lfloglow, &lfloghigh); else if (leafhdr.stale) { /* * Set impossible logging indices for this case. */ lfloglow = leafhdr.count; lfloghigh = -1; } /* * Insert the new entry, log everything. */ lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, highstale, &lfloglow, &lfloghigh); lep->hashval = cpu_to_be32(args->hashval); lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(args->geo, args->blkno, args->index)); dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(args, bp); xfs_dir3_leaf_log_ents(args, bp, lfloglow, lfloghigh); xfs_dir3_leaf_check(dp, bp); return 0; } #ifdef DEBUG static void xfs_dir2_free_hdr_check( struct xfs_inode *dp, struct xfs_buf *bp, xfs_dir2_db_t db) { struct xfs_dir3_icfree_hdr hdr; dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr); ASSERT((hdr.firstdb % dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0); ASSERT(hdr.firstdb <= db); ASSERT(db < hdr.firstdb + hdr.nvalid); } #else #define xfs_dir2_free_hdr_check(dp, bp, db) #endif /* DEBUG */ /* * Return the last hash value in the leaf. * Stale entries are ok. */ xfs_dahash_t /* hash value */ xfs_dir2_leafn_lasthash( struct xfs_inode *dp, struct xfs_buf *bp, /* leaf buffer */ int *count) /* count of entries in leaf */ { struct xfs_dir2_leaf *leaf = bp->b_addr; struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); if (count) *count = leafhdr.count; if (!leafhdr.count) return 0; ents = dp->d_ops->leaf_ents_p(leaf); return be32_to_cpu(ents[leafhdr.count - 1].hashval); } /* * Look up a leaf entry for space to add a name in a node-format leaf block. * The extrablk in state is a freespace block. */ STATIC int xfs_dir2_leafn_lookup_for_addname( struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int *indexp, /* out: leaf entry index */ xfs_da_state_t *state) /* state to fill in */ { struct xfs_buf *curbp = NULL; /* current data/free buffer */ xfs_dir2_db_t curdb = -1; /* current data block number */ xfs_dir2_db_t curfdb = -1; /* current free block number */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return value */ int fi; /* free entry index */ xfs_dir2_free_t *free = NULL; /* free block structure */ int index; /* leaf entry index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ int length; /* length of new data entry */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_mount_t *mp; /* filesystem mount point */ xfs_dir2_db_t newdb; /* new data block number */ xfs_dir2_db_t newfdb; /* new free block number */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; dp = args->dp; tp = args->trans; mp = dp->i_mount; leaf = bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); ASSERT(leafhdr.count > 0); /* * Look up the hash value in the leaf entries. */ index = xfs_dir2_leaf_search_hash(args, bp); /* * Do we have a buffer coming in? */ if (state->extravalid) { /* If so, it's a free block buffer, get the block number. */ curbp = state->extrablk.bp; curfdb = state->extrablk.blkno; free = curbp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); } length = dp->d_ops->data_entsize(args->namelen); /* * Loop over leaf entries with the right hash value. */ for (lep = &ents[index]; index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) { /* * Skip stale leaf entries. */ if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; /* * Pull the data block number from the entry. */ newdb = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); /* * For addname, we're looking for a place to put the new entry. * We want to use a data block with an entry of equal * hash value to ours if there is one with room. * * If this block isn't the data block we already have * in hand, take a look at it. */ if (newdb != curdb) { __be16 *bests; curdb = newdb; /* * Convert the data block to the free block * holding its freespace information. */ newfdb = dp->d_ops->db_to_fdb(args->geo, newdb); /* * If it's not the one we have in hand, read it in. */ if (newfdb != curfdb) { /* * If we had one before, drop it. */ if (curbp) xfs_trans_brelse(tp, curbp); error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(args->geo, newfdb), &curbp); if (error) return error; free = curbp->b_addr; xfs_dir2_free_hdr_check(dp, curbp, curdb); } /* * Get the index for our entry. */ fi = dp->d_ops->db_to_fdindex(args->geo, curdb); /* * If it has room, return it. */ bests = dp->d_ops->free_bests_p(free); if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) { XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", XFS_ERRLEVEL_LOW, mp); if (curfdb != newfdb) xfs_trans_brelse(tp, curbp); return -EFSCORRUPTED; } curfdb = newfdb; if (be16_to_cpu(bests[fi]) >= length) goto out; } } /* Didn't find any space */ fi = -1; out: ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); if (curbp) { /* Giving back a free block. */ state->extravalid = 1; state->extrablk.bp = curbp; state->extrablk.index = fi; state->extrablk.blkno = curfdb; /* * Important: this magic number is not in the buffer - it's for * buffer type information and therefore only the free/data type * matters here, not whether CRCs are enabled or not. */ state->extrablk.magic = XFS_DIR2_FREE_MAGIC; } else { state->extravalid = 0; } /* * Return the index, that will be the insertion point. */ *indexp = index; return -ENOENT; } /* * Look up a leaf entry in a node-format leaf block. * The extrablk in state a data block. */ STATIC int xfs_dir2_leafn_lookup_for_entry( struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int *indexp, /* out: leaf entry index */ xfs_da_state_t *state) /* state to fill in */ { struct xfs_buf *curbp = NULL; /* current data/free buffer */ xfs_dir2_db_t curdb = -1; /* current data block number */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return value */ int index; /* leaf entry index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_mount_t *mp; /* filesystem mount point */ xfs_dir2_db_t newdb; /* new data block number */ xfs_trans_t *tp; /* transaction pointer */ enum xfs_dacmp cmp; /* comparison result */ struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; dp = args->dp; tp = args->trans; mp = dp->i_mount; leaf = bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); ASSERT(leafhdr.count > 0); /* * Look up the hash value in the leaf entries. */ index = xfs_dir2_leaf_search_hash(args, bp); /* * Do we have a buffer coming in? */ if (state->extravalid) { curbp = state->extrablk.bp; curdb = state->extrablk.blkno; } /* * Loop over leaf entries with the right hash value. */ for (lep = &ents[index]; index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) { /* * Skip stale leaf entries. */ if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; /* * Pull the data block number from the entry. */ newdb = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); /* * Not adding a new entry, so we really want to find * the name given to us. * * If it's a different data block, go get it. */ if (newdb != curdb) { /* * If we had a block before that we aren't saving * for a CI name, drop it */ if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT || curdb != state->extrablk.blkno)) xfs_trans_brelse(tp, curbp); /* * If needing the block that is saved with a CI match, * use it otherwise read in the new data block. */ if (args->cmpresult != XFS_CMP_DIFFERENT && newdb == state->extrablk.blkno) { ASSERT(state->extravalid); curbp = state->extrablk.bp; } else { error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, newdb), -1, &curbp); if (error) return error; } xfs_dir3_data_check(dp, curbp); curdb = newdb; } /* * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); /* * Compare the entry and if it's an exact match, return * EEXIST immediately. If it's the first case-insensitive * match, store the block & inode number and continue looking. */ cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { /* If there is a CI match block, drop it */ if (args->cmpresult != XFS_CMP_DIFFERENT && curdb != state->extrablk.blkno) xfs_trans_brelse(tp, state->extrablk.bp); args->cmpresult = cmp; args->inumber = be64_to_cpu(dep->inumber); args->filetype = dp->d_ops->data_get_ftype(dep); *indexp = index; state->extravalid = 1; state->extrablk.bp = curbp; state->extrablk.blkno = curdb; state->extrablk.index = (int)((char *)dep - (char *)curbp->b_addr); state->extrablk.magic = XFS_DIR2_DATA_MAGIC; curbp->b_ops = &xfs_dir3_data_buf_ops; xfs_trans_buf_set_type(tp, curbp, XFS_BLFT_DIR_DATA_BUF); if (cmp == XFS_CMP_EXACT) return -EEXIST; } } ASSERT(index == leafhdr.count || (args->op_flags & XFS_DA_OP_OKNOENT)); if (curbp) { if (args->cmpresult == XFS_CMP_DIFFERENT) { /* Giving back last used data block. */ state->extravalid = 1; state->extrablk.bp = curbp; state->extrablk.index = -1; state->extrablk.blkno = curdb; state->extrablk.magic = XFS_DIR2_DATA_MAGIC; curbp->b_ops = &xfs_dir3_data_buf_ops; xfs_trans_buf_set_type(tp, curbp, XFS_BLFT_DIR_DATA_BUF); } else { /* If the curbp is not the CI match block, drop it */ if (state->extrablk.bp != curbp) xfs_trans_brelse(tp, curbp); } } else { state->extravalid = 0; } *indexp = index; return -ENOENT; } /* * Look up a leaf entry in a node-format leaf block. * If this is an addname then the extrablk in state is a freespace block, * otherwise it's a data block. */ int xfs_dir2_leafn_lookup_int( struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int *indexp, /* out: leaf entry index */ xfs_da_state_t *state) /* state to fill in */ { if (args->op_flags & XFS_DA_OP_ADDNAME) return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp, state); return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state); } /* * Move count leaf entries from source to destination leaf. * Log entries and headers. Stale entries are preserved. */ static void xfs_dir3_leafn_moveents( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *bp_s, /* source */ struct xfs_dir3_icleaf_hdr *shdr, struct xfs_dir2_leaf_entry *sents, int start_s,/* source leaf index */ struct xfs_buf *bp_d, /* destination */ struct xfs_dir3_icleaf_hdr *dhdr, struct xfs_dir2_leaf_entry *dents, int start_d,/* destination leaf index */ int count) /* count of leaves to copy */ { int stale; /* count stale leaves copied */ trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count); /* * Silently return if nothing to do. */ if (count == 0) return; /* * If the destination index is not the end of the current * destination leaf entries, open up a hole in the destination * to hold the new entries. */ if (start_d < dhdr->count) { memmove(&dents[start_d + count], &dents[start_d], (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); xfs_dir3_leaf_log_ents(args, bp_d, start_d + count, count + dhdr->count - 1); } /* * If the source has stale leaves, count the ones in the copy range * so we can update the header correctly. */ if (shdr->stale) { int i; /* temp leaf index */ for (i = start_s, stale = 0; i < start_s + count; i++) { if (sents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) stale++; } } else stale = 0; /* * Copy the leaf entries from source to destination. */ memcpy(&dents[start_d], &sents[start_s], count * sizeof(xfs_dir2_leaf_entry_t)); xfs_dir3_leaf_log_ents(args, bp_d, start_d, start_d + count - 1); /* * If there are source entries after the ones we copied, * delete the ones we copied by sliding the next ones down. */ if (start_s + count < shdr->count) { memmove(&sents[start_s], &sents[start_s + count], count * sizeof(xfs_dir2_leaf_entry_t)); xfs_dir3_leaf_log_ents(args, bp_s, start_s, start_s + count - 1); } /* * Update the headers and log them. */ shdr->count -= count; shdr->stale -= stale; dhdr->count += count; dhdr->stale += stale; } /* * Determine the sort order of two leaf blocks. * Returns 1 if both are valid and leaf2 should be before leaf1, else 0. */ int /* sort order */ xfs_dir2_leafn_order( struct xfs_inode *dp, struct xfs_buf *leaf1_bp, /* leaf1 buffer */ struct xfs_buf *leaf2_bp) /* leaf2 buffer */ { struct xfs_dir2_leaf *leaf1 = leaf1_bp->b_addr; struct xfs_dir2_leaf *leaf2 = leaf2_bp->b_addr; struct xfs_dir2_leaf_entry *ents1; struct xfs_dir2_leaf_entry *ents2; struct xfs_dir3_icleaf_hdr hdr1; struct xfs_dir3_icleaf_hdr hdr2; dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); ents1 = dp->d_ops->leaf_ents_p(leaf1); ents2 = dp->d_ops->leaf_ents_p(leaf2); if (hdr1.count > 0 && hdr2.count > 0 && (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) || be32_to_cpu(ents2[hdr2.count - 1].hashval) < be32_to_cpu(ents1[hdr1.count - 1].hashval))) return 1; return 0; } /* * Rebalance leaf entries between two leaf blocks. * This is actually only called when the second block is new, * though the code deals with the general case. * A new entry will be inserted in one of the blocks, and that * entry is taken into account when balancing. */ static void xfs_dir2_leafn_rebalance( xfs_da_state_t *state, /* btree cursor */ xfs_da_state_blk_t *blk1, /* first btree block */ xfs_da_state_blk_t *blk2) /* second btree block */ { xfs_da_args_t *args; /* operation arguments */ int count; /* count (& direction) leaves */ int isleft; /* new goes in left leaf */ xfs_dir2_leaf_t *leaf1; /* first leaf structure */ xfs_dir2_leaf_t *leaf2; /* second leaf structure */ int mid; /* midpoint leaf index */ #if defined(DEBUG) || defined(XFS_WARN) int oldstale; /* old count of stale leaves */ #endif int oldsum; /* old total leaf count */ int swap; /* swapped leaf blocks */ struct xfs_dir2_leaf_entry *ents1; struct xfs_dir2_leaf_entry *ents2; struct xfs_dir3_icleaf_hdr hdr1; struct xfs_dir3_icleaf_hdr hdr2; struct xfs_inode *dp = state->args->dp; args = state->args; /* * If the block order is wrong, swap the arguments. */ if ((swap = xfs_dir2_leafn_order(dp, blk1->bp, blk2->bp))) { xfs_da_state_blk_t *tmp; /* temp for block swap */ tmp = blk1; blk1 = blk2; blk2 = tmp; } leaf1 = blk1->bp->b_addr; leaf2 = blk2->bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); ents1 = dp->d_ops->leaf_ents_p(leaf1); ents2 = dp->d_ops->leaf_ents_p(leaf2); oldsum = hdr1.count + hdr2.count; #if defined(DEBUG) || defined(XFS_WARN) oldstale = hdr1.stale + hdr2.stale; #endif mid = oldsum >> 1; /* * If the old leaf count was odd then the new one will be even, * so we need to divide the new count evenly. */ if (oldsum & 1) { xfs_dahash_t midhash; /* middle entry hash value */ if (mid >= hdr1.count) midhash = be32_to_cpu(ents2[mid - hdr1.count].hashval); else midhash = be32_to_cpu(ents1[mid].hashval); isleft = args->hashval <= midhash; } /* * If the old count is even then the new count is odd, so there's * no preferred side for the new entry. * Pick the left one. */ else isleft = 1; /* * Calculate moved entry count. Positive means left-to-right, * negative means right-to-left. Then move the entries. */ count = hdr1.count - mid + (isleft == 0); if (count > 0) xfs_dir3_leafn_moveents(args, blk1->bp, &hdr1, ents1, hdr1.count - count, blk2->bp, &hdr2, ents2, 0, count); else if (count < 0) xfs_dir3_leafn_moveents(args, blk2->bp, &hdr2, ents2, 0, blk1->bp, &hdr1, ents1, hdr1.count, count); ASSERT(hdr1.count + hdr2.count == oldsum); ASSERT(hdr1.stale + hdr2.stale == oldstale); /* log the changes made when moving the entries */ dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1); dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2); xfs_dir3_leaf_log_header(args, blk1->bp); xfs_dir3_leaf_log_header(args, blk2->bp); xfs_dir3_leaf_check(dp, blk1->bp); xfs_dir3_leaf_check(dp, blk2->bp); /* * Mark whether we're inserting into the old or new leaf. */ if (hdr1.count < hdr2.count) state->inleaf = swap; else if (hdr1.count > hdr2.count) state->inleaf = !swap; else state->inleaf = swap ^ (blk1->index <= hdr1.count); /* * Adjust the expected index for insertion. */ if (!state->inleaf) blk2->index = blk1->index - hdr1.count; /* * Finally sanity check just to make sure we are not returning a * negative index */ if (blk2->index < 0) { state->inleaf = 1; blk2->index = 0; xfs_alert(dp->i_mount, "%s: picked the wrong leaf? reverting original leaf: blk1->index %d", __func__, blk1->index); } } static int xfs_dir3_data_block_free( xfs_da_args_t *args, struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_free *free, xfs_dir2_db_t fdb, int findex, struct xfs_buf *fbp, int longest) { int logfree = 0; __be16 *bests; struct xfs_dir3_icfree_hdr freehdr; struct xfs_inode *dp = args->dp; dp->d_ops->free_hdr_from_disk(&freehdr, free); bests = dp->d_ops->free_bests_p(free); if (hdr) { /* * Data block is not empty, just set the free entry to the new * value. */ bests[findex] = cpu_to_be16(longest); xfs_dir2_free_log_bests(args, fbp, findex, findex); return 0; } /* One less used entry in the free table. */ freehdr.nused--; /* * If this was the last entry in the table, we can trim the table size * back. There might be other entries at the end referring to * non-existent data blocks, get those too. */ if (findex == freehdr.nvalid - 1) { int i; /* free entry index */ for (i = findex - 1; i >= 0; i--) { if (bests[i] != cpu_to_be16(NULLDATAOFF)) break; } freehdr.nvalid = i + 1; logfree = 0; } else { /* Not the last entry, just punch it out. */ bests[findex] = cpu_to_be16(NULLDATAOFF); logfree = 1; } dp->d_ops->free_hdr_to_disk(free, &freehdr); xfs_dir2_free_log_header(args, fbp); /* * If there are no useful entries left in the block, get rid of the * block if we can. */ if (!freehdr.nused) { int error; error = xfs_dir2_shrink_inode(args, fdb, fbp); if (error == 0) { fbp = NULL; logfree = 0; } else if (error != -ENOSPC || args->total != 0) return error; /* * It's possible to get ENOSPC if there is no * space reservation. In this case some one * else will eventually get rid of this block. */ } /* Log the free entry that changed, unless we got rid of it. */ if (logfree) xfs_dir2_free_log_bests(args, fbp, findex, findex); return 0; } /* * Remove an entry from a node directory. * This removes the leaf entry and the data entry, * and updates the free block if necessary. */ static int /* error */ xfs_dir2_leafn_remove( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *bp, /* leaf buffer */ int index, /* leaf entry index */ xfs_da_state_blk_t *dblk, /* data block */ int *rval) /* resulting block needs join */ { xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_db_t db; /* data block number */ struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ int longest; /* longest data free entry */ int off; /* data block entry offset */ int needlog; /* need to log data header */ int needscan; /* need to rescan data frees */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir2_data_free *bf; /* bestfree table */ struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir2_leaf_entry *ents; trace_xfs_dir2_leafn_remove(args, index); dp = args->dp; tp = args->trans; leaf = bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the entry we're removing. */ lep = &ents[index]; /* * Extract the data block and offset from the entry. */ db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); ASSERT(dblk->blkno == db); off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)); ASSERT(dblk->index == off); /* * Kill the leaf entry by marking it stale. * Log the leaf block changes. */ leafhdr.stale++; dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(args, bp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); xfs_dir3_leaf_log_ents(args, bp, index, index); /* * Make the data entry free. Keep track of the longest freespace * in the data block in case it changes. */ dbp = dblk->bp; hdr = dbp->b_addr; dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); bf = dp->d_ops->data_bestfree_p(hdr); longest = be16_to_cpu(bf[0].length); needlog = needscan = 0; xfs_dir2_data_make_free(args, dbp, off, dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* * Rescan the data block freespaces for bestfree. * Log the data block header if needed. */ if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(args, dbp); xfs_dir3_data_check(dp, dbp); /* * If the longest data block freespace changes, need to update * the corresponding freeblock entry. */ if (longest < be16_to_cpu(bf[0].length)) { int error; /* error return value */ struct xfs_buf *fbp; /* freeblock buffer */ xfs_dir2_db_t fdb; /* freeblock block number */ int findex; /* index in freeblock entries */ xfs_dir2_free_t *free; /* freeblock structure */ /* * Convert the data block number to a free block, * read in the free block. */ fdb = dp->d_ops->db_to_fdb(args->geo, db); error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(args->geo, fdb), &fbp); if (error) return error; free = fbp->b_addr; #ifdef DEBUG { struct xfs_dir3_icfree_hdr freehdr; dp->d_ops->free_hdr_from_disk(&freehdr, free); ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) * (fdb - xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET))); } #endif /* * Calculate which entry we need to fix. */ findex = dp->d_ops->db_to_fdindex(args->geo, db); longest = be16_to_cpu(bf[0].length); /* * If the data block is now empty we can get rid of it * (usually). */ if (longest == args->geo->blksize - dp->d_ops->data_entry_offset) { /* * Try to punch out the data block. */ error = xfs_dir2_shrink_inode(args, db, dbp); if (error == 0) { dblk->bp = NULL; hdr = NULL; } /* * We can get ENOSPC if there's no space reservation. * In this case just drop the buffer and some one else * will eventually get rid of the empty block. */ else if (!(error == -ENOSPC && args->total == 0)) return error; } /* * If we got rid of the data block, we can eliminate that entry * in the free block. */ error = xfs_dir3_data_block_free(args, hdr, free, fdb, findex, fbp, longest); if (error) return error; } xfs_dir3_leaf_check(dp, bp); /* * Return indication of whether this leaf block is empty enough * to justify trying to join it with a neighbor. */ *rval = (dp->d_ops->leaf_hdr_size + (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < args->geo->magicpct; return 0; } /* * Split the leaf entries in the old block into old and new blocks. */ int /* error */ xfs_dir2_leafn_split( xfs_da_state_t *state, /* btree cursor */ xfs_da_state_blk_t *oldblk, /* original block */ xfs_da_state_blk_t *newblk) /* newly created block */ { xfs_da_args_t *args; /* operation arguments */ xfs_dablk_t blkno; /* new leaf block number */ int error; /* error return value */ struct xfs_inode *dp; /* * Allocate space for a new leaf node. */ args = state->args; dp = args->dp; ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC); error = xfs_da_grow_inode(args, &blkno); if (error) { return error; } /* * Initialize the new leaf block. */ error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(args->geo, blkno), &newblk->bp, XFS_DIR2_LEAFN_MAGIC); if (error) return error; newblk->blkno = blkno; newblk->magic = XFS_DIR2_LEAFN_MAGIC; /* * Rebalance the entries across the two leaves, link the new * block into the leaves. */ xfs_dir2_leafn_rebalance(state, oldblk, newblk); error = xfs_da3_blk_link(state, oldblk, newblk); if (error) { return error; } /* * Insert the new entry in the correct block. */ if (state->inleaf) error = xfs_dir2_leafn_add(oldblk->bp, args, oldblk->index); else error = xfs_dir2_leafn_add(newblk->bp, args, newblk->index); /* * Update last hashval in each block since we added the name. */ oldblk->hashval = xfs_dir2_leafn_lasthash(dp, oldblk->bp, NULL); newblk->hashval = xfs_dir2_leafn_lasthash(dp, newblk->bp, NULL); xfs_dir3_leaf_check(dp, oldblk->bp); xfs_dir3_leaf_check(dp, newblk->bp); return error; } /* * Check a leaf block and its neighbors to see if the block should be * collapsed into one or the other neighbor. Always keep the block * with the smaller block number. * If the current block is over 50% full, don't try to join it, return 0. * If the block is empty, fill in the state structure and return 2. * If it can be collapsed, fill in the state structure and return 1. * If nothing can be done, return 0. */ int /* error */ xfs_dir2_leafn_toosmall( xfs_da_state_t *state, /* btree cursor */ int *action) /* resulting action to take */ { xfs_da_state_blk_t *blk; /* leaf block */ xfs_dablk_t blkno; /* leaf block number */ struct xfs_buf *bp; /* leaf buffer */ int bytes; /* bytes in use */ int count; /* leaf live entry count */ int error; /* error return value */ int forward; /* sibling block direction */ int i; /* sibling counter */ xfs_dir2_leaf_t *leaf; /* leaf structure */ int rval; /* result from path_shift */ struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir2_leaf_entry *ents; struct xfs_inode *dp = state->args->dp; /* * Check for the degenerate case of the block being over 50% full. * If so, it's not worth even looking to see if we might be able * to coalesce with a sibling. */ blk = &state->path.blk[state->path.active - 1]; leaf = blk->bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, blk->bp); count = leafhdr.count - leafhdr.stale; bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]); if (bytes > (state->args->geo->blksize >> 1)) { /* * Blk over 50%, don't try to join. */ *action = 0; return 0; } /* * Check for the degenerate case of the block being empty. * If the block is empty, we'll simply delete it, no need to * coalesce it with a sibling block. We choose (arbitrarily) * to merge with the forward block unless it is NULL. */ if (count == 0) { /* * Make altpath point to the block we want to keep and * path point to the block we want to drop (this one). */ forward = (leafhdr.forw != 0); memcpy(&state->altpath, &state->path, sizeof(state->path)); error = xfs_da3_path_shift(state, &state->altpath, forward, 0, &rval); if (error) return error; *action = rval ? 2 : 0; return 0; } /* * Examine each sibling block to see if we can coalesce with * at least 25% free space to spare. We need to figure out * whether to merge with the forward or the backward block. * We prefer coalescing with the lower numbered sibling so as * to shrink a directory over time. */ forward = leafhdr.forw < leafhdr.back; for (i = 0, bp = NULL; i < 2; forward = !forward, i++) { struct xfs_dir3_icleaf_hdr hdr2; blkno = forward ? leafhdr.forw : leafhdr.back; if (blkno == 0) continue; /* * Read the sibling leaf block. */ error = xfs_dir3_leafn_read(state->args->trans, dp, blkno, -1, &bp); if (error) return error; /* * Count bytes in the two blocks combined. */ count = leafhdr.count - leafhdr.stale; bytes = state->args->geo->blksize - (state->args->geo->blksize >> 2); leaf = bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf); ents = dp->d_ops->leaf_ents_p(leaf); count += hdr2.count - hdr2.stale; bytes -= count * sizeof(ents[0]); /* * Fits with at least 25% to spare. */ if (bytes >= 0) break; xfs_trans_brelse(state->args->trans, bp); } /* * Didn't like either block, give up. */ if (i >= 2) { *action = 0; return 0; } /* * Make altpath point to the block we want to keep (the lower * numbered block) and path point to the block we want to drop. */ memcpy(&state->altpath, &state->path, sizeof(state->path)); if (blkno < blk->blkno) error = xfs_da3_path_shift(state, &state->altpath, forward, 0, &rval); else error = xfs_da3_path_shift(state, &state->path, forward, 0, &rval); if (error) { return error; } *action = rval ? 0 : 1; return 0; } /* * Move all the leaf entries from drop_blk to save_blk. * This is done as part of a join operation. */ void xfs_dir2_leafn_unbalance( xfs_da_state_t *state, /* cursor */ xfs_da_state_blk_t *drop_blk, /* dead block */ xfs_da_state_blk_t *save_blk) /* surviving block */ { xfs_da_args_t *args; /* operation arguments */ xfs_dir2_leaf_t *drop_leaf; /* dead leaf structure */ xfs_dir2_leaf_t *save_leaf; /* surviving leaf structure */ struct xfs_dir3_icleaf_hdr savehdr; struct xfs_dir3_icleaf_hdr drophdr; struct xfs_dir2_leaf_entry *sents; struct xfs_dir2_leaf_entry *dents; struct xfs_inode *dp = state->args->dp; args = state->args; ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC); drop_leaf = drop_blk->bp->b_addr; save_leaf = save_blk->bp->b_addr; dp->d_ops->leaf_hdr_from_disk(&savehdr, save_leaf); dp->d_ops->leaf_hdr_from_disk(&drophdr, drop_leaf); sents = dp->d_ops->leaf_ents_p(save_leaf); dents = dp->d_ops->leaf_ents_p(drop_leaf); /* * If there are any stale leaf entries, take this opportunity * to purge them. */ if (drophdr.stale) xfs_dir3_leaf_compact(args, &drophdr, drop_blk->bp); if (savehdr.stale) xfs_dir3_leaf_compact(args, &savehdr, save_blk->bp); /* * Move the entries from drop to the appropriate end of save. */ drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval); if (xfs_dir2_leafn_order(dp, save_blk->bp, drop_blk->bp)) xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, save_blk->bp, &savehdr, sents, 0, drophdr.count); else xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, save_blk->bp, &savehdr, sents, savehdr.count, drophdr.count); save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval); /* log the changes made when moving the entries */ dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr); dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr); xfs_dir3_leaf_log_header(args, save_blk->bp); xfs_dir3_leaf_log_header(args, drop_blk->bp); xfs_dir3_leaf_check(dp, save_blk->bp); xfs_dir3_leaf_check(dp, drop_blk->bp); } /* * Top-level node form directory addname routine. */ int /* error */ xfs_dir2_node_addname( xfs_da_args_t *args) /* operation arguments */ { xfs_da_state_blk_t *blk; /* leaf block for insert */ int error; /* error return value */ int rval; /* sub-return value */ xfs_da_state_t *state; /* btree cursor */ trace_xfs_dir2_node_addname(args); /* * Allocate and initialize the state (btree cursor). */ state = xfs_da_state_alloc(); state->args = args; state->mp = args->dp->i_mount; /* * Look up the name. We're not supposed to find it, but * this gives us the insertion point. */ error = xfs_da3_node_lookup_int(state, &rval); if (error) rval = error; if (rval != -ENOENT) { goto done; } /* * Add the data entry to a data block. * Extravalid is set to a freeblock found by lookup. */ rval = xfs_dir2_node_addname_int(args, state->extravalid ? &state->extrablk : NULL); if (rval) { goto done; } blk = &state->path.blk[state->path.active - 1]; ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); /* * Add the new leaf entry. */ rval = xfs_dir2_leafn_add(blk->bp, args, blk->index); if (rval == 0) { /* * It worked, fix the hash values up the btree. */ if (!(args->op_flags & XFS_DA_OP_JUSTCHECK)) xfs_da3_fixhashpath(state, &state->path); } else { /* * It didn't work, we need to split the leaf block. */ if (args->total == 0) { ASSERT(rval == -ENOSPC); goto done; } /* * Split the leaf block and insert the new entry. */ rval = xfs_da3_split(state); } done: xfs_da_state_free(state); return rval; } /* * Add the data entry for a node-format directory name addition. * The leaf entry is added in xfs_dir2_leafn_add. * We may enter with a freespace block that the lookup found. */ static int /* error */ xfs_dir2_node_addname_int( xfs_da_args_t *args, /* operation arguments */ xfs_da_state_blk_t *fblk) /* optional freespace block */ { xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_db_t dbno; /* data block number */ struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data entry pointer */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* data unused entry pointer */ int error; /* error return value */ xfs_dir2_db_t fbno; /* freespace block number */ struct xfs_buf *fbp; /* freespace buffer */ int findex; /* freespace entry index */ xfs_dir2_free_t *free=NULL; /* freespace block structure */ xfs_dir2_db_t ifbno; /* initial freespace block no */ xfs_dir2_db_t lastfbno=0; /* highest freespace block no */ int length; /* length of the new entry */ int logfree; /* need to log free entry */ xfs_mount_t *mp; /* filesystem mount point */ int needlog; /* need to log data header */ int needscan; /* need to rescan data frees */ __be16 *tagp; /* data entry tag pointer */ xfs_trans_t *tp; /* transaction pointer */ __be16 *bests; struct xfs_dir3_icfree_hdr freehdr; struct xfs_dir2_data_free *bf; dp = args->dp; mp = dp->i_mount; tp = args->trans; length = dp->d_ops->data_entsize(args->namelen); /* * If we came in with a freespace block that means that lookup * found an entry with our hash value. This is the freespace * block for that data entry. */ if (fblk) { fbp = fblk->bp; /* * Remember initial freespace block number. */ ifbno = fblk->blkno; free = fbp->b_addr; findex = fblk->index; bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); /* * This means the free entry showed that the data block had * space for our entry, so we remembered it. * Use that data block. */ if (findex >= 0) { ASSERT(findex < freehdr.nvalid); ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF); ASSERT(be16_to_cpu(bests[findex]) >= length); dbno = freehdr.firstdb + findex; } else { /* * The data block looked at didn't have enough room. * We'll start at the beginning of the freespace entries. */ dbno = -1; findex = 0; } } else { /* * Didn't come in with a freespace block, so no data block. */ ifbno = dbno = -1; fbp = NULL; findex = 0; } /* * If we don't have a data block yet, we're going to scan the * freespace blocks looking for one. Figure out what the * highest freespace block number is. */ if (dbno == -1) { xfs_fileoff_t fo; /* freespace block number */ if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK))) return error; lastfbno = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo); fbno = ifbno; } /* * While we haven't identified a data block, search the freeblock * data for a good data block. If we find a null freeblock entry, * indicating a hole in the data blocks, remember that. */ while (dbno == -1) { /* * If we don't have a freeblock in hand, get the next one. */ if (fbp == NULL) { /* * Happens the first time through unless lookup gave * us a freespace block to start with. */ if (++fbno == 0) fbno = xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET); /* * If it's ifbno we already looked at it. */ if (fbno == ifbno) fbno++; /* * If it's off the end we're done. */ if (fbno >= lastfbno) break; /* * Read the block. There can be holes in the * freespace blocks, so this might not succeed. * This should be really rare, so there's no reason * to avoid it. */ error = xfs_dir2_free_try_read(tp, dp, xfs_dir2_db_to_da(args->geo, fbno), &fbp); if (error) return error; if (!fbp) continue; free = fbp->b_addr; findex = 0; } /* * Look at the current free entry. Is it good enough? * * The bests initialisation should be where the bufer is read in * the above branch. But gcc is too stupid to realise that bests * and the freehdr are actually initialised if they are placed * there, so we have to do it here to avoid warnings. Blech. */ bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); if (be16_to_cpu(bests[findex]) != NULLDATAOFF && be16_to_cpu(bests[findex]) >= length) dbno = freehdr.firstdb + findex; else { /* * Are we done with the freeblock? */ if (++findex == freehdr.nvalid) { /* * Drop the block. */ xfs_trans_brelse(tp, fbp); fbp = NULL; if (fblk && fblk->bp) fblk->bp = NULL; } } } /* * If we don't have a data block, we need to allocate one and make * the freespace entries refer to it. */ if (unlikely(dbno == -1)) { /* * Not allowed to allocate, return failure. */ if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) return -ENOSPC; /* * Allocate and initialize the new data block. */ if (unlikely((error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &dbno)) || (error = xfs_dir3_data_init(args, dbno, &dbp)))) return error; /* * If (somehow) we have a freespace block, get rid of it. */ if (fbp) xfs_trans_brelse(tp, fbp); if (fblk && fblk->bp) fblk->bp = NULL; /* * Get the freespace block corresponding to the data block * that was just allocated. */ fbno = dp->d_ops->db_to_fdb(args->geo, dbno); error = xfs_dir2_free_try_read(tp, dp, xfs_dir2_db_to_da(args->geo, fbno), &fbp); if (error) return error; /* * If there wasn't a freespace block, the read will * return a NULL fbp. Allocate and initialize a new one. */ if (!fbp) { error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fbno); if (error) return error; if (dp->d_ops->db_to_fdb(args->geo, dbno) != fbno) { xfs_alert(mp, "%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld ifbno %llu lastfbno %d", __func__, (unsigned long long)dp->i_ino, (long long)dp->d_ops->db_to_fdb( args->geo, dbno), (long long)dbno, (long long)fbno, (unsigned long long)ifbno, lastfbno); if (fblk) { xfs_alert(mp, " fblk 0x%p blkno %llu index %d magic 0x%x", fblk, (unsigned long long)fblk->blkno, fblk->index, fblk->magic); } else { xfs_alert(mp, " ... fblk is NULL"); } XFS_ERROR_REPORT("xfs_dir2_node_addname_int", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } /* * Get a buffer for the new block. */ error = xfs_dir3_free_get_buf(args, fbno, &fbp); if (error) return error; free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); /* * Remember the first slot as our empty slot. */ freehdr.firstdb = (fbno - xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)) * dp->d_ops->free_max_bests(args->geo); } else { free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); } /* * Set the freespace block index from the data block number. */ findex = dp->d_ops->db_to_fdindex(args->geo, dbno); /* * If it's after the end of the current entries in the * freespace block, extend that table. */ if (findex >= freehdr.nvalid) { ASSERT(findex < dp->d_ops->free_max_bests(args->geo)); freehdr.nvalid = findex + 1; /* * Tag new entry so nused will go up. */ bests[findex] = cpu_to_be16(NULLDATAOFF); } /* * If this entry was for an empty data block * (this should always be true) then update the header. */ if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { freehdr.nused++; dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); xfs_dir2_free_log_header(args, fbp); } /* * Update the real value in the table. * We haven't allocated the data entry yet so this will * change again. */ hdr = dbp->b_addr; bf = dp->d_ops->data_bestfree_p(hdr); bests[findex] = bf[0].length; logfree = 1; } /* * We had a data block so we don't have to make a new one. */ else { /* * If just checking, we succeeded. */ if (args->op_flags & XFS_DA_OP_JUSTCHECK) return 0; /* * Read the data block in. */ error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, dbno), -1, &dbp); if (error) return error; hdr = dbp->b_addr; bf = dp->d_ops->data_bestfree_p(hdr); logfree = 0; } ASSERT(be16_to_cpu(bf[0].length) >= length); /* * Point to the existing unused space. */ dup = (xfs_dir2_data_unused_t *) ((char *)hdr + be16_to_cpu(bf[0].offset)); needscan = needlog = 0; /* * Mark the first part of the unused space, inuse for us. */ xfs_dir2_data_use_free(args, dbp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, &needlog, &needscan); /* * Fill in the new entry and log it. */ dep = (xfs_dir2_data_entry_t *)dup; dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); dp->d_ops->data_put_ftype(dep, args->filetype); tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); xfs_dir2_data_log_entry(args, dbp, dep); /* * Rescan the block for bestfree if needed. */ if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); /* * Log the data block header if needed. */ if (needlog) xfs_dir2_data_log_header(args, dbp); /* * If the freespace entry is now wrong, update it. */ bests = dp->d_ops->free_bests_p(free); /* gcc is so stupid */ if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) { bests[findex] = bf[0].length; logfree = 1; } /* * Log the freespace entry if needed. */ if (logfree) xfs_dir2_free_log_bests(args, fbp, findex, findex); /* * Return the data block and offset in args, then drop the data block. */ args->blkno = (xfs_dablk_t)dbno; args->index = be16_to_cpu(*tagp); return 0; } /* * Lookup an entry in a node-format directory. * All the real work happens in xfs_da3_node_lookup_int. * The only real output is the inode number of the entry. */ int /* error */ xfs_dir2_node_lookup( xfs_da_args_t *args) /* operation arguments */ { int error; /* error return value */ int i; /* btree level */ int rval; /* operation return value */ xfs_da_state_t *state; /* btree cursor */ trace_xfs_dir2_node_lookup(args); /* * Allocate and initialize the btree cursor. */ state = xfs_da_state_alloc(); state->args = args; state->mp = args->dp->i_mount; /* * Fill in the path to the entry in the cursor. */ error = xfs_da3_node_lookup_int(state, &rval); if (error) rval = error; else if (rval == -ENOENT && args->cmpresult == XFS_CMP_CASE) { /* If a CI match, dup the actual name and return -EEXIST */ xfs_dir2_data_entry_t *dep; dep = (xfs_dir2_data_entry_t *) ((char *)state->extrablk.bp->b_addr + state->extrablk.index); rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen); } /* * Release the btree blocks and leaf block. */ for (i = 0; i < state->path.active; i++) { xfs_trans_brelse(args->trans, state->path.blk[i].bp); state->path.blk[i].bp = NULL; } /* * Release the data block if we have it. */ if (state->extravalid && state->extrablk.bp) { xfs_trans_brelse(args->trans, state->extrablk.bp); state->extrablk.bp = NULL; } xfs_da_state_free(state); return rval; } /* * Remove an entry from a node-format directory. */ int /* error */ xfs_dir2_node_removename( struct xfs_da_args *args) /* operation arguments */ { struct xfs_da_state_blk *blk; /* leaf block */ int error; /* error return value */ int rval; /* operation return value */ struct xfs_da_state *state; /* btree cursor */ trace_xfs_dir2_node_removename(args); /* * Allocate and initialize the btree cursor. */ state = xfs_da_state_alloc(); state->args = args; state->mp = args->dp->i_mount; /* Look up the entry we're deleting, set up the cursor. */ error = xfs_da3_node_lookup_int(state, &rval); if (error) goto out_free; /* Didn't find it, upper layer screwed up. */ if (rval != -EEXIST) { error = rval; goto out_free; } blk = &state->path.blk[state->path.active - 1]; ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); ASSERT(state->extravalid); /* * Remove the leaf and data entries. * Extrablk refers to the data block. */ error = xfs_dir2_leafn_remove(args, blk->bp, blk->index, &state->extrablk, &rval); if (error) goto out_free; /* * Fix the hash values up the btree. */ xfs_da3_fixhashpath(state, &state->path); /* * If we need to join leaf blocks, do it. */ if (rval && state->path.active > 1) error = xfs_da3_join(state); /* * If no errors so far, try conversion to leaf format. */ if (!error) error = xfs_dir2_node_to_leaf(state); out_free: xfs_da_state_free(state); return error; } /* * Replace an entry's inode number in a node-format directory. */ int /* error */ xfs_dir2_node_replace( xfs_da_args_t *args) /* operation arguments */ { xfs_da_state_blk_t *blk; /* leaf block */ xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_data_entry_t *dep; /* data entry changed */ int error; /* error return value */ int i; /* btree level */ xfs_ino_t inum; /* new inode number */ int ftype; /* new file type */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry being changed */ int rval; /* internal return value */ xfs_da_state_t *state; /* btree cursor */ trace_xfs_dir2_node_replace(args); /* * Allocate and initialize the btree cursor. */ state = xfs_da_state_alloc(); state->args = args; state->mp = args->dp->i_mount; /* * We have to save new inode number and ftype since * xfs_da3_node_lookup_int() is going to overwrite them */ inum = args->inumber; ftype = args->filetype; /* * Lookup the entry to change in the btree. */ error = xfs_da3_node_lookup_int(state, &rval); if (error) { rval = error; } /* * It should be found, since the vnodeops layer has looked it up * and locked it. But paranoia is good. */ if (rval == -EEXIST) { struct xfs_dir2_leaf_entry *ents; /* * Find the leaf entry. */ blk = &state->path.blk[state->path.active - 1]; ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); leaf = blk->bp->b_addr; ents = args->dp->d_ops->leaf_ents_p(leaf); lep = &ents[blk->index]; ASSERT(state->extravalid); /* * Point to the data entry. */ hdr = state->extrablk.bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); dep = (xfs_dir2_data_entry_t *) ((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); ASSERT(inum != be64_to_cpu(dep->inumber)); /* * Fill in the new inode number and log the entry. */ dep->inumber = cpu_to_be64(inum); args->dp->d_ops->data_put_ftype(dep, ftype); xfs_dir2_data_log_entry(args, state->extrablk.bp, dep); rval = 0; } /* * Didn't find it, and we're holding a data block. Drop it. */ else if (state->extravalid) { xfs_trans_brelse(args->trans, state->extrablk.bp); state->extrablk.bp = NULL; } /* * Release all the buffers in the cursor. */ for (i = 0; i < state->path.active; i++) { xfs_trans_brelse(args->trans, state->path.blk[i].bp); state->path.blk[i].bp = NULL; } xfs_da_state_free(state); return rval; } /* * Trim off a trailing empty freespace block. * Return (in rvalp) 1 if we did it, 0 if not. */ int /* error */ xfs_dir2_node_trim_free( xfs_da_args_t *args, /* operation arguments */ xfs_fileoff_t fo, /* free block number */ int *rvalp) /* out: did something */ { struct xfs_buf *bp; /* freespace buffer */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ xfs_dir2_free_t *free; /* freespace structure */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir3_icfree_hdr freehdr; dp = args->dp; tp = args->trans; *rvalp = 0; /* * Read the freespace block. */ error = xfs_dir2_free_try_read(tp, dp, fo, &bp); if (error) return error; /* * There can be holes in freespace. If fo is a hole, there's * nothing to do. */ if (!bp) return 0; free = bp->b_addr; dp->d_ops->free_hdr_from_disk(&freehdr, free); /* * If there are used entries, there's nothing to do. */ if (freehdr.nused > 0) { xfs_trans_brelse(tp, bp); return 0; } /* * Blow the block away. */ error = xfs_dir2_shrink_inode(args, xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo), bp); if (error) { /* * Can't fail with ENOSPC since that only happens with no * space reservation, when breaking up an extent into two * pieces. This is the last block of an extent. */ ASSERT(error != -ENOSPC); xfs_trans_brelse(tp, bp); return error; } /* * Return that we succeeded. */ *rvalp = 1; return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2_priv.h0000644000000000000000000001346313063067170016720 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_DIR2_PRIV_H__ #define __XFS_DIR2_PRIV_H__ struct dir_context; /* xfs_dir2.c */ extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, xfs_dir2_db_t *dbp); extern int xfs_dir_cilookup_result(struct xfs_da_args *args, const unsigned char *name, int len); /* xfs_dir2_block.c */ extern int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf **bpp); extern int xfs_dir2_block_addname(struct xfs_da_args *args); extern int xfs_dir2_block_lookup(struct xfs_da_args *args); extern int xfs_dir2_block_removename(struct xfs_da_args *args); extern int xfs_dir2_block_replace(struct xfs_da_args *args); extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args, struct xfs_buf *lbp, struct xfs_buf *dbp); /* xfs_dir2_data.c */ #ifdef DEBUG #define xfs_dir3_data_check(dp,bp) __xfs_dir3_data_check(dp, bp); #else #define xfs_dir3_data_check(dp,bp) #endif extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp); extern int xfs_dir3_data_readahead(struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mapped_bno); extern struct xfs_dir2_data_free * xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf, struct xfs_dir2_data_unused *dup, int *loghead); extern int xfs_dir3_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno, struct xfs_buf **bpp); /* xfs_dir2_leaf.c */ extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, xfs_daddr_t mappedbno, struct xfs_buf **bpp); extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args, struct xfs_buf *dbp); extern int xfs_dir2_leaf_addname(struct xfs_da_args *args); extern void xfs_dir3_leaf_compact(struct xfs_da_args *args, struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_buf *bp); extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_dir2_leaf_entry *ents, int *indexp, int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, struct xfs_buf **bpp, __uint16_t magic); extern void xfs_dir3_leaf_log_ents(struct xfs_da_args *args, struct xfs_buf *bp, int first, int last); extern void xfs_dir3_leaf_log_header(struct xfs_da_args *args, struct xfs_buf *bp); extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); extern int xfs_dir2_leaf_replace(struct xfs_da_args *args); extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args, struct xfs_buf *lbp); extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args, struct xfs_buf *lbp, xfs_dir2_db_t db); extern struct xfs_dir2_leaf_entry * xfs_dir3_leaf_find_entry(struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_dir2_leaf_entry *ents, int index, int compact, int lowstale, int highstale, int *lfloglow, int *lfloghigh); extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, struct xfs_inode *dp, struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf); /* xfs_dir2_node.c */ extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, struct xfs_buf *lbp); extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_inode *dp, struct xfs_buf *bp, int *count); extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp, struct xfs_da_args *args, int *indexp, struct xfs_da_state *state); extern int xfs_dir2_leafn_order(struct xfs_inode *dp, struct xfs_buf *leaf1_bp, struct xfs_buf *leaf2_bp); extern int xfs_dir2_leafn_split(struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk); extern int xfs_dir2_leafn_toosmall(struct xfs_da_state *state, int *action); extern void xfs_dir2_leafn_unbalance(struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, struct xfs_da_state_blk *save_blk); extern int xfs_dir2_node_addname(struct xfs_da_args *args); extern int xfs_dir2_node_lookup(struct xfs_da_args *args); extern int xfs_dir2_node_removename(struct xfs_da_args *args); extern int xfs_dir2_node_replace(struct xfs_da_args *args); extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo, int *rvalp); extern int xfs_dir2_free_read(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, struct xfs_buf **bpp); /* xfs_dir2_sf.c */ extern int xfs_dir2_block_sfsize(struct xfs_inode *dp, struct xfs_dir2_data_hdr *block, struct xfs_dir2_sf_hdr *sfhp); extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_buf *bp, int size, xfs_dir2_sf_hdr_t *sfhp); extern int xfs_dir2_sf_addname(struct xfs_da_args *args); extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); extern int xfs_dir2_sf_removename(struct xfs_da_args *args); extern int xfs_dir2_sf_replace(struct xfs_da_args *args); /* xfs_dir2_readdir.c */ extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx, size_t bufsize); #endif /* __XFS_DIR2_PRIV_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dir2_sf.c0000644000000000000000000010210213063067171016331 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trace.h" /* * Prototypes for internal functions. */ static void xfs_dir2_sf_addname_easy(xfs_da_args_t *args, xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t offset, int new_isize); static void xfs_dir2_sf_addname_hard(xfs_da_args_t *args, int objchange, int new_isize); static int xfs_dir2_sf_addname_pick(xfs_da_args_t *args, int objchange, xfs_dir2_sf_entry_t **sfepp, xfs_dir2_data_aoff_t *offsetp); #ifdef DEBUG static void xfs_dir2_sf_check(xfs_da_args_t *args); #else #define xfs_dir2_sf_check(args) #endif /* DEBUG */ static void xfs_dir2_sf_toino4(xfs_da_args_t *args); static void xfs_dir2_sf_toino8(xfs_da_args_t *args); /* * Given a block directory (dp/block), calculate its size as a shortform (sf) * directory and a header for the sf directory, if it will fit it the * space currently present in the inode. If it won't fit, the output * size is too big (but not accurate). */ int /* size for sf form */ xfs_dir2_block_sfsize( xfs_inode_t *dp, /* incore inode pointer */ xfs_dir2_data_hdr_t *hdr, /* block directory data */ xfs_dir2_sf_hdr_t *sfhp) /* output: header for sf form */ { xfs_dir2_dataptr_t addr; /* data entry address */ xfs_dir2_leaf_entry_t *blp; /* leaf area of the block */ xfs_dir2_block_tail_t *btp; /* tail area of the block */ int count; /* shortform entry count */ xfs_dir2_data_entry_t *dep; /* data entry in the block */ int i; /* block entry index */ int i8count; /* count of big-inode entries */ int isdot; /* entry is "." */ int isdotdot; /* entry is ".." */ xfs_mount_t *mp; /* mount structure pointer */ int namelen; /* total name bytes */ xfs_ino_t parent = 0; /* parent inode number */ int size=0; /* total computed size */ int has_ftype; struct xfs_da_geometry *geo; mp = dp->i_mount; geo = mp->m_dir_geo; /* * if there is a filetype field, add the extra byte to the namelen * for each entry that we see. */ has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0; count = i8count = namelen = 0; btp = xfs_dir2_block_tail_p(geo, hdr); blp = xfs_dir2_block_leaf_p(btp); /* * Iterate over the block's data entries by using the leaf pointers. */ for (i = 0; i < be32_to_cpu(btp->count); i++) { if ((addr = be32_to_cpu(blp[i].address)) == XFS_DIR2_NULL_DATAPTR) continue; /* * Calculate the pointer to the entry at hand. */ dep = (xfs_dir2_data_entry_t *)((char *)hdr + xfs_dir2_dataptr_to_off(geo, addr)); /* * Detect . and .., so we can special-case them. * . is not included in sf directories. * .. is included by just the parent inode number. */ isdot = dep->namelen == 1 && dep->name[0] == '.'; isdotdot = dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.'; if (!isdot) i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM; /* take into account the file type field */ if (!isdot && !isdotdot) { count++; namelen += dep->namelen + has_ftype; } else if (isdotdot) parent = be64_to_cpu(dep->inumber); /* * Calculate the new size, see if we should give up yet. */ size = xfs_dir2_sf_hdr_size(i8count) + /* header */ count * 3 * sizeof(__u8) + /* namelen + offset */ namelen + /* name */ (i8count ? /* inumber */ count * XFS_INO64_SIZE : count * XFS_INO32_SIZE); if (size > XFS_IFORK_DSIZE(dp)) return size; /* size value is a failure */ } /* * Create the output header, if it worked. */ sfhp->count = count; sfhp->i8count = i8count; dp->d_ops->sf_put_parent_ino(sfhp, parent); return size; } /* * Convert a block format directory to shortform. * Caller has already checked that it will fit, and built us a header. */ int /* error */ xfs_dir2_block_to_sf( xfs_da_args_t *args, /* operation arguments */ struct xfs_buf *bp, int size, /* shortform directory size */ xfs_dir2_sf_hdr_t *sfhp) /* shortform directory hdr */ { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_block_tail_t *btp; /* block tail pointer */ xfs_dir2_data_entry_t *dep; /* data entry pointer */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* unused data pointer */ char *endptr; /* end of data entries */ int error; /* error return value */ int logflags; /* inode logging flags */ xfs_mount_t *mp; /* filesystem mount point */ char *ptr; /* current data pointer */ xfs_dir2_sf_entry_t *sfep; /* shortform entry */ xfs_dir2_sf_hdr_t *sfp; /* shortform directory header */ xfs_dir2_sf_hdr_t *dst; /* temporary data buffer */ trace_xfs_dir2_block_to_sf(args); dp = args->dp; mp = dp->i_mount; /* * allocate a temporary destination buffer the size of the inode * to format the data into. Once we have formatted the data, we * can free the block and copy the formatted data into the inode literal * area. */ dst = kmem_alloc(mp->m_sb.sb_inodesize, KM_SLEEP); hdr = bp->b_addr; /* * Copy the header into the newly allocate local space. */ sfp = (xfs_dir2_sf_hdr_t *)dst; memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count)); /* * Set up to loop over the block's entries. */ btp = xfs_dir2_block_tail_p(args->geo, hdr); ptr = (char *)dp->d_ops->data_entry_p(hdr); endptr = (char *)xfs_dir2_block_leaf_p(btp); sfep = xfs_dir2_sf_firstentry(sfp); /* * Loop over the active and unused entries. * Stop when we reach the leaf/tail portion of the block. */ while (ptr < endptr) { /* * If it's unused, just skip over it. */ dup = (xfs_dir2_data_unused_t *)ptr; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { ptr += be16_to_cpu(dup->length); continue; } dep = (xfs_dir2_data_entry_t *)ptr; /* * Skip . */ if (dep->namelen == 1 && dep->name[0] == '.') ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino); /* * Skip .., but make sure the inode number is right. */ else if (dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.') ASSERT(be64_to_cpu(dep->inumber) == dp->d_ops->sf_get_parent_ino(sfp)); /* * Normal entry, copy it into shortform. */ else { sfep->namelen = dep->namelen; xfs_dir2_sf_put_offset(sfep, (xfs_dir2_data_aoff_t) ((char *)dep - (char *)hdr)); memcpy(sfep->name, dep->name, dep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, be64_to_cpu(dep->inumber)); dp->d_ops->sf_put_ftype(sfep, dp->d_ops->data_get_ftype(dep)); sfep = dp->d_ops->sf_nextentry(sfp, sfep); } ptr += dp->d_ops->data_entsize(dep->namelen); } ASSERT((char *)sfep - (char *)sfp == size); /* now we are done with the block, we can shrink the inode */ logflags = XFS_ILOG_CORE; error = xfs_dir2_shrink_inode(args, args->geo->datablk, bp); if (error) { ASSERT(error != -ENOSPC); goto out; } /* * The buffer is now unconditionally gone, whether * xfs_dir2_shrink_inode worked or not. * * Convert the inode to local format and copy the data in. */ ASSERT(dp->i_df.if_bytes == 0); xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size); dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; dp->i_d.di_size = size; logflags |= XFS_ILOG_DDATA; xfs_dir2_sf_check(args); out: xfs_trans_log_inode(args->trans, dp, logflags); kmem_free(dst); return error; } /* * Add a name to a shortform directory. * There are two algorithms, "easy" and "hard" which we decide on * before changing anything. * Convert to block form if necessary, if the new entry won't fit. */ int /* error */ xfs_dir2_sf_addname( xfs_da_args_t *args) /* operation arguments */ { xfs_inode_t *dp; /* incore directory inode */ int error; /* error return value */ int incr_isize; /* total change in size */ int new_isize; /* di_size after adding name */ int objchange; /* changing to 8-byte inodes */ xfs_dir2_data_aoff_t offset = 0; /* offset for new entry */ int pick; /* which algorithm to use */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ xfs_dir2_sf_entry_t *sfep = NULL; /* shortform entry */ trace_xfs_dir2_sf_addname(args); ASSERT(xfs_dir2_sf_lookup(args) == -ENOENT); dp = args->dp; ASSERT(dp->i_df.if_flags & XFS_IFINLINE); /* * Make sure the shortform value has some of its header. */ if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); return -EIO; } ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); ASSERT(dp->i_df.if_u1.if_data != NULL); sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); /* * Compute entry (and change in) size. */ incr_isize = dp->d_ops->sf_entsize(sfp, args->namelen); objchange = 0; /* * Do we have to change to 8 byte inodes? */ if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) { /* * Yes, adjust the inode size. old count + (parent + new) */ incr_isize += (sfp->count + 2) * XFS_INO64_DIFF; objchange = 1; } new_isize = (int)dp->i_d.di_size + incr_isize; /* * Won't fit as shortform any more (due to size), * or the pick routine says it won't (due to offset values). */ if (new_isize > XFS_IFORK_DSIZE(dp) || (pick = xfs_dir2_sf_addname_pick(args, objchange, &sfep, &offset)) == 0) { /* * Just checking or no space reservation, it doesn't fit. */ if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) return -ENOSPC; /* * Convert to block form then add the name. */ error = xfs_dir2_sf_to_block(args); if (error) return error; return xfs_dir2_block_addname(args); } /* * Just checking, it fits. */ if (args->op_flags & XFS_DA_OP_JUSTCHECK) return 0; /* * Do it the easy way - just add it at the end. */ if (pick == 1) xfs_dir2_sf_addname_easy(args, sfep, offset, new_isize); /* * Do it the hard way - look for a place to insert the new entry. * Convert to 8 byte inode numbers first if necessary. */ else { ASSERT(pick == 2); if (objchange) xfs_dir2_sf_toino8(args); xfs_dir2_sf_addname_hard(args, objchange, new_isize); } xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); return 0; } /* * Add the new entry the "easy" way. * This is copying the old directory and adding the new entry at the end. * Since it's sorted by "offset" we need room after the last offset * that's already there, and then room to convert to a block directory. * This is already checked by the pick routine. */ static void xfs_dir2_sf_addname_easy( xfs_da_args_t *args, /* operation arguments */ xfs_dir2_sf_entry_t *sfep, /* pointer to new entry */ xfs_dir2_data_aoff_t offset, /* offset to use for new ent */ int new_isize) /* new directory size */ { int byteoff; /* byte offset in sf dir */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ dp = args->dp; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; byteoff = (int)((char *)sfep - (char *)sfp); /* * Grow the in-inode space. */ xfs_idata_realloc(dp, dp->d_ops->sf_entsize(sfp, args->namelen), XFS_DATA_FORK); /* * Need to set up again due to realloc of the inode data. */ sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + byteoff); /* * Fill in the new entry. */ sfep->namelen = args->namelen; xfs_dir2_sf_put_offset(sfep, offset); memcpy(sfep->name, args->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); dp->d_ops->sf_put_ftype(sfep, args->filetype); /* * Update the header and inode. */ sfp->count++; if (args->inumber > XFS_DIR2_MAX_SHORT_INUM) sfp->i8count++; dp->i_d.di_size = new_isize; xfs_dir2_sf_check(args); } /* * Add the new entry the "hard" way. * The caller has already converted to 8 byte inode numbers if necessary, * in which case we need to leave the i8count at 1. * Find a hole that the new entry will fit into, and copy * the first part of the entries, the new entry, and the last part of * the entries. */ /* ARGSUSED */ static void xfs_dir2_sf_addname_hard( xfs_da_args_t *args, /* operation arguments */ int objchange, /* changing inode number size */ int new_isize) /* new directory size */ { int add_datasize; /* data size need for new ent */ char *buf; /* buffer for old */ xfs_inode_t *dp; /* incore directory inode */ int eof; /* reached end of old dir */ int nbytes; /* temp for byte copies */ xfs_dir2_data_aoff_t new_offset; /* next offset value */ xfs_dir2_data_aoff_t offset; /* current offset value */ int old_isize; /* previous di_size */ xfs_dir2_sf_entry_t *oldsfep; /* entry in original dir */ xfs_dir2_sf_hdr_t *oldsfp; /* original shortform dir */ xfs_dir2_sf_entry_t *sfep; /* entry in new dir */ xfs_dir2_sf_hdr_t *sfp; /* new shortform dir */ /* * Copy the old directory to the stack buffer. */ dp = args->dp; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; old_isize = (int)dp->i_d.di_size; buf = kmem_alloc(old_isize, KM_SLEEP); oldsfp = (xfs_dir2_sf_hdr_t *)buf; memcpy(oldsfp, sfp, old_isize); /* * Loop over the old directory finding the place we're going * to insert the new entry. * If it's going to end up at the end then oldsfep will point there. */ for (offset = dp->d_ops->data_first_offset, oldsfep = xfs_dir2_sf_firstentry(oldsfp), add_datasize = dp->d_ops->data_entsize(args->namelen), eof = (char *)oldsfep == &buf[old_isize]; !eof; offset = new_offset + dp->d_ops->data_entsize(oldsfep->namelen), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep), eof = (char *)oldsfep == &buf[old_isize]) { new_offset = xfs_dir2_sf_get_offset(oldsfep); if (offset + add_datasize <= new_offset) break; } /* * Get rid of the old directory, then allocate space for * the new one. We do this so xfs_idata_realloc won't copy * the data. */ xfs_idata_realloc(dp, -old_isize, XFS_DATA_FORK); xfs_idata_realloc(dp, new_isize, XFS_DATA_FORK); /* * Reset the pointer since the buffer was reallocated. */ sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; /* * Copy the first part of the directory, including the header. */ nbytes = (int)((char *)oldsfep - (char *)oldsfp); memcpy(sfp, oldsfp, nbytes); sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + nbytes); /* * Fill in the new entry, and update the header counts. */ sfep->namelen = args->namelen; xfs_dir2_sf_put_offset(sfep, offset); memcpy(sfep->name, args->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); dp->d_ops->sf_put_ftype(sfep, args->filetype); sfp->count++; if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange) sfp->i8count++; /* * If there's more left to copy, do that. */ if (!eof) { sfep = dp->d_ops->sf_nextentry(sfp, sfep); memcpy(sfep, oldsfep, old_isize - nbytes); } kmem_free(buf); dp->i_d.di_size = new_isize; xfs_dir2_sf_check(args); } /* * Decide if the new entry will fit at all. * If it will fit, pick between adding the new entry to the end (easy) * or somewhere else (hard). * Return 0 (won't fit), 1 (easy), 2 (hard). */ /*ARGSUSED*/ static int /* pick result */ xfs_dir2_sf_addname_pick( xfs_da_args_t *args, /* operation arguments */ int objchange, /* inode # size changes */ xfs_dir2_sf_entry_t **sfepp, /* out(1): new entry ptr */ xfs_dir2_data_aoff_t *offsetp) /* out(1): new offset */ { xfs_inode_t *dp; /* incore directory inode */ int holefit; /* found hole it will fit in */ int i; /* entry number */ xfs_dir2_data_aoff_t offset; /* data block offset */ xfs_dir2_sf_entry_t *sfep; /* shortform entry */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ int size; /* entry's data size */ int used; /* data bytes used */ dp = args->dp; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; size = dp->d_ops->data_entsize(args->namelen); offset = dp->d_ops->data_first_offset; sfep = xfs_dir2_sf_firstentry(sfp); holefit = 0; /* * Loop over sf entries. * Keep track of data offset and whether we've seen a place * to insert the new entry. */ for (i = 0; i < sfp->count; i++) { if (!holefit) holefit = offset + size <= xfs_dir2_sf_get_offset(sfep); offset = xfs_dir2_sf_get_offset(sfep) + dp->d_ops->data_entsize(sfep->namelen); sfep = dp->d_ops->sf_nextentry(sfp, sfep); } /* * Calculate data bytes used excluding the new entry, if this * was a data block (block form directory). */ used = offset + (sfp->count + 3) * (uint)sizeof(xfs_dir2_leaf_entry_t) + (uint)sizeof(xfs_dir2_block_tail_t); /* * If it won't fit in a block form then we can't insert it, * we'll go back, convert to block, then try the insert and convert * to leaf. */ if (used + (holefit ? 0 : size) > args->geo->blksize) return 0; /* * If changing the inode number size, do it the hard way. */ if (objchange) return 2; /* * If it won't fit at the end then do it the hard way (use the hole). */ if (used + size > args->geo->blksize) return 2; /* * Do it the easy way. */ *sfepp = sfep; *offsetp = offset; return 1; } #ifdef DEBUG /* * Check consistency of shortform directory, assert if bad. */ static void xfs_dir2_sf_check( xfs_da_args_t *args) /* operation arguments */ { xfs_inode_t *dp; /* incore directory inode */ int i; /* entry number */ int i8count; /* number of big inode#s */ xfs_ino_t ino; /* entry inode number */ int offset; /* data offset */ xfs_dir2_sf_entry_t *sfep; /* shortform dir entry */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ dp = args->dp; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; offset = dp->d_ops->data_first_offset; ino = dp->d_ops->sf_get_parent_ino(sfp); i8count = ino > XFS_DIR2_MAX_SHORT_INUM; for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset); ino = dp->d_ops->sf_get_ino(sfp, sfep); i8count += ino > XFS_DIR2_MAX_SHORT_INUM; offset = xfs_dir2_sf_get_offset(sfep) + dp->d_ops->data_entsize(sfep->namelen); ASSERT(dp->d_ops->sf_get_ftype(sfep) < XFS_DIR3_FT_MAX); } ASSERT(i8count == sfp->i8count); ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size); ASSERT(offset + (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + (uint)sizeof(xfs_dir2_block_tail_t) <= args->geo->blksize); } #endif /* DEBUG */ /* * Create a new (shortform) directory. */ int /* error, always 0 */ xfs_dir2_sf_create( xfs_da_args_t *args, /* operation arguments */ xfs_ino_t pino) /* parent inode number */ { xfs_inode_t *dp; /* incore directory inode */ int i8count; /* parent inode is an 8-byte number */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ int size; /* directory size */ trace_xfs_dir2_sf_create(args); dp = args->dp; ASSERT(dp != NULL); ASSERT(dp->i_d.di_size == 0); /* * If it's currently a zero-length extent file, * convert it to local format. */ if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) { dp->i_df.if_flags &= ~XFS_IFEXTENTS; /* just in case */ dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); dp->i_df.if_flags |= XFS_IFINLINE; } ASSERT(dp->i_df.if_flags & XFS_IFINLINE); ASSERT(dp->i_df.if_bytes == 0); i8count = pino > XFS_DIR2_MAX_SHORT_INUM; size = xfs_dir2_sf_hdr_size(i8count); /* * Make a buffer for the data. */ xfs_idata_realloc(dp, size, XFS_DATA_FORK); /* * Fill in the header, */ sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; sfp->i8count = i8count; /* * Now can put in the inode number, since i8count is set. */ dp->d_ops->sf_put_parent_ino(sfp, pino); sfp->count = 0; dp->i_d.di_size = size; xfs_dir2_sf_check(args); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); return 0; } /* * Lookup an entry in a shortform directory. * Returns EEXIST if found, ENOENT if not found. */ int /* error */ xfs_dir2_sf_lookup( xfs_da_args_t *args) /* operation arguments */ { xfs_inode_t *dp; /* incore directory inode */ int i; /* entry index */ int error; xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ enum xfs_dacmp cmp; /* comparison result */ xfs_dir2_sf_entry_t *ci_sfep; /* case-insens. entry */ trace_xfs_dir2_sf_lookup(args); xfs_dir2_sf_check(args); dp = args->dp; ASSERT(dp->i_df.if_flags & XFS_IFINLINE); /* * Bail out if the directory is way too short. */ if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); return -EIO; } ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); ASSERT(dp->i_df.if_u1.if_data != NULL); sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); /* * Special case for . */ if (args->namelen == 1 && args->name[0] == '.') { args->inumber = dp->i_ino; args->cmpresult = XFS_CMP_EXACT; args->filetype = XFS_DIR3_FT_DIR; return -EEXIST; } /* * Special case for .. */ if (args->namelen == 2 && args->name[0] == '.' && args->name[1] == '.') { args->inumber = dp->d_ops->sf_get_parent_ino(sfp); args->cmpresult = XFS_CMP_EXACT; args->filetype = XFS_DIR3_FT_DIR; return -EEXIST; } /* * Loop over all the entries trying to match ours. */ ci_sfep = NULL; for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { /* * Compare name and if it's an exact match, return the inode * number. If it's the first case-insensitive match, store the * inode number and continue looking for an exact match. */ cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name, sfep->namelen); if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { args->cmpresult = cmp; args->inumber = dp->d_ops->sf_get_ino(sfp, sfep); args->filetype = dp->d_ops->sf_get_ftype(sfep); if (cmp == XFS_CMP_EXACT) return -EEXIST; ci_sfep = sfep; } } ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); /* * Here, we can only be doing a lookup (not a rename or replace). * If a case-insensitive match was not found, return -ENOENT. */ if (!ci_sfep) return -ENOENT; /* otherwise process the CI match as required by the caller */ error = xfs_dir_cilookup_result(args, ci_sfep->name, ci_sfep->namelen); return error; } /* * Remove an entry from a shortform directory. */ int /* error */ xfs_dir2_sf_removename( xfs_da_args_t *args) { int byteoff; /* offset of removed entry */ xfs_inode_t *dp; /* incore directory inode */ int entsize; /* this entry's size */ int i; /* shortform entry index */ int newsize; /* new inode size */ int oldsize; /* old inode size */ xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ trace_xfs_dir2_sf_removename(args); dp = args->dp; ASSERT(dp->i_df.if_flags & XFS_IFINLINE); oldsize = (int)dp->i_d.di_size; /* * Bail out if the directory is way too short. */ if (oldsize < offsetof(xfs_dir2_sf_hdr_t, parent)) { ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); return -EIO; } ASSERT(dp->i_df.if_bytes == oldsize); ASSERT(dp->i_df.if_u1.if_data != NULL); sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->i8count)); /* * Loop over the old directory entries. * Find the one we're deleting. */ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { if (xfs_da_compname(args, sfep->name, sfep->namelen) == XFS_CMP_EXACT) { ASSERT(dp->d_ops->sf_get_ino(sfp, sfep) == args->inumber); break; } } /* * Didn't find it. */ if (i == sfp->count) return -ENOENT; /* * Calculate sizes. */ byteoff = (int)((char *)sfep - (char *)sfp); entsize = dp->d_ops->sf_entsize(sfp, args->namelen); newsize = oldsize - entsize; /* * Copy the part if any after the removed entry, sliding it down. */ if (byteoff + entsize < oldsize) memmove((char *)sfp + byteoff, (char *)sfp + byteoff + entsize, oldsize - (byteoff + entsize)); /* * Fix up the header and file size. */ sfp->count--; dp->i_d.di_size = newsize; /* * Reallocate, making it smaller. */ xfs_idata_realloc(dp, newsize - oldsize, XFS_DATA_FORK); sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; /* * Are we changing inode number size? */ if (args->inumber > XFS_DIR2_MAX_SHORT_INUM) { if (sfp->i8count == 1) xfs_dir2_sf_toino4(args); else sfp->i8count--; } xfs_dir2_sf_check(args); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); return 0; } /* * Replace the inode number of an entry in a shortform directory. */ int /* error */ xfs_dir2_sf_replace( xfs_da_args_t *args) /* operation arguments */ { xfs_inode_t *dp; /* incore directory inode */ int i; /* entry index */ xfs_ino_t ino=0; /* entry old inode number */ int i8elevated; /* sf_toino8 set i8count=1 */ xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ trace_xfs_dir2_sf_replace(args); dp = args->dp; ASSERT(dp->i_df.if_flags & XFS_IFINLINE); /* * Bail out if the shortform directory is way too small. */ if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); return -EIO; } ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); ASSERT(dp->i_df.if_u1.if_data != NULL); sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); /* * New inode number is large, and need to convert to 8-byte inodes. */ if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) { int error; /* error return value */ int newsize; /* new inode size */ newsize = dp->i_df.if_bytes + (sfp->count + 1) * XFS_INO64_DIFF; /* * Won't fit as shortform, convert to block then do replace. */ if (newsize > XFS_IFORK_DSIZE(dp)) { error = xfs_dir2_sf_to_block(args); if (error) { return error; } return xfs_dir2_block_replace(args); } /* * Still fits, convert to 8-byte now. */ xfs_dir2_sf_toino8(args); i8elevated = 1; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; } else i8elevated = 0; ASSERT(args->namelen != 1 || args->name[0] != '.'); /* * Replace ..'s entry. */ if (args->namelen == 2 && args->name[0] == '.' && args->name[1] == '.') { ino = dp->d_ops->sf_get_parent_ino(sfp); ASSERT(args->inumber != ino); dp->d_ops->sf_put_parent_ino(sfp, args->inumber); } /* * Normal entry, look for the name. */ else { for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { if (xfs_da_compname(args, sfep->name, sfep->namelen) == XFS_CMP_EXACT) { ino = dp->d_ops->sf_get_ino(sfp, sfep); ASSERT(args->inumber != ino); dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); dp->d_ops->sf_put_ftype(sfep, args->filetype); break; } } /* * Didn't find it. */ if (i == sfp->count) { ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); if (i8elevated) xfs_dir2_sf_toino4(args); return -ENOENT; } } /* * See if the old number was large, the new number is small. */ if (ino > XFS_DIR2_MAX_SHORT_INUM && args->inumber <= XFS_DIR2_MAX_SHORT_INUM) { /* * And the old count was one, so need to convert to small. */ if (sfp->i8count == 1) xfs_dir2_sf_toino4(args); else sfp->i8count--; } /* * See if the old number was small, the new number is large. */ if (ino <= XFS_DIR2_MAX_SHORT_INUM && args->inumber > XFS_DIR2_MAX_SHORT_INUM) { /* * add to the i8count unless we just converted to 8-byte * inodes (which does an implied i8count = 1) */ ASSERT(sfp->i8count != 0); if (!i8elevated) sfp->i8count++; } xfs_dir2_sf_check(args); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); return 0; } /* * Convert from 8-byte inode numbers to 4-byte inode numbers. * The last 8-byte inode number is gone, but the count is still 1. */ static void xfs_dir2_sf_toino4( xfs_da_args_t *args) /* operation arguments */ { char *buf; /* old dir's buffer */ xfs_inode_t *dp; /* incore directory inode */ int i; /* entry index */ int newsize; /* new inode size */ xfs_dir2_sf_entry_t *oldsfep; /* old sf entry */ xfs_dir2_sf_hdr_t *oldsfp; /* old sf directory */ int oldsize; /* old inode size */ xfs_dir2_sf_entry_t *sfep; /* new sf entry */ xfs_dir2_sf_hdr_t *sfp; /* new sf directory */ trace_xfs_dir2_sf_toino4(args); dp = args->dp; /* * Copy the old directory to the buffer. * Then nuke it from the inode, and add the new buffer to the inode. * Don't want xfs_idata_realloc copying the data here. */ oldsize = dp->i_df.if_bytes; buf = kmem_alloc(oldsize, KM_SLEEP); oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; ASSERT(oldsfp->i8count == 1); memcpy(buf, oldsfp, oldsize); /* * Compute the new inode size. */ newsize = oldsize - (oldsfp->count + 1) * XFS_INO64_DIFF; xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK); xfs_idata_realloc(dp, newsize, XFS_DATA_FORK); /* * Reset our pointers, the data has moved. */ oldsfp = (xfs_dir2_sf_hdr_t *)buf; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; /* * Fill in the new header. */ sfp->count = oldsfp->count; sfp->i8count = 0; dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp)); /* * Copy the entries field by field. */ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), oldsfep = xfs_dir2_sf_firstentry(oldsfp); i < sfp->count; i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; memcpy(sfep->offset, oldsfep->offset, sizeof(sfep->offset)); memcpy(sfep->name, oldsfep->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, dp->d_ops->sf_get_ino(oldsfp, oldsfep)); dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep)); } /* * Clean up the inode. */ kmem_free(buf); dp->i_d.di_size = newsize; xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); } /* * Convert existing entries from 4-byte inode numbers to 8-byte inode numbers. * The new entry w/ an 8-byte inode number is not there yet; we leave with * i8count set to 1, but no corresponding 8-byte entry. */ static void xfs_dir2_sf_toino8( xfs_da_args_t *args) /* operation arguments */ { char *buf; /* old dir's buffer */ xfs_inode_t *dp; /* incore directory inode */ int i; /* entry index */ int newsize; /* new inode size */ xfs_dir2_sf_entry_t *oldsfep; /* old sf entry */ xfs_dir2_sf_hdr_t *oldsfp; /* old sf directory */ int oldsize; /* old inode size */ xfs_dir2_sf_entry_t *sfep; /* new sf entry */ xfs_dir2_sf_hdr_t *sfp; /* new sf directory */ trace_xfs_dir2_sf_toino8(args); dp = args->dp; /* * Copy the old directory to the buffer. * Then nuke it from the inode, and add the new buffer to the inode. * Don't want xfs_idata_realloc copying the data here. */ oldsize = dp->i_df.if_bytes; buf = kmem_alloc(oldsize, KM_SLEEP); oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; ASSERT(oldsfp->i8count == 0); memcpy(buf, oldsfp, oldsize); /* * Compute the new inode size (nb: entry count + 1 for parent) */ newsize = oldsize + (oldsfp->count + 1) * XFS_INO64_DIFF; xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK); xfs_idata_realloc(dp, newsize, XFS_DATA_FORK); /* * Reset our pointers, the data has moved. */ oldsfp = (xfs_dir2_sf_hdr_t *)buf; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; /* * Fill in the new header. */ sfp->count = oldsfp->count; sfp->i8count = 1; dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp)); /* * Copy the entries field by field. */ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), oldsfep = xfs_dir2_sf_firstentry(oldsfp); i < sfp->count; i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; memcpy(sfep->offset, oldsfep->offset, sizeof(sfep->offset)); memcpy(sfep->name, oldsfep->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, dp->d_ops->sf_get_ino(oldsfp, oldsfep)); dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep)); } /* * Clean up the inode. */ kmem_free(buf); dp->i_d.di_size = newsize; xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_dquot_buf.c0000644000000000000000000002067613063067171017010 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_quota_defs.h" /* * XXX: kernel implementation causes ndquots calc to go real * bad. Just leaving the existing userspace calc here right now. */ int xfs_calc_dquots_per_chunk( unsigned int nbblks) /* basic block units */ { ASSERT(nbblks > 0); return BBTOB(nbblks) / sizeof(xfs_dqblk_t); #if 0 /* kernel code that goes wrong in userspace! */ unsigned int ndquots; ASSERT(nbblks > 0); ndquots = BBTOB(nbblks); do_div(ndquots, sizeof(xfs_dqblk_t)); return ndquots; #endif } /* * Do some primitive error checking on ondisk dquot data structures. */ int xfs_dqcheck( struct xfs_mount *mp, xfs_disk_dquot_t *ddq, xfs_dqid_t id, uint type, /* used only when IO_dorepair is true */ uint flags, const char *str) { xfs_dqblk_t *d = (xfs_dqblk_t *)ddq; int errs = 0; /* * We can encounter an uninitialized dquot buffer for 2 reasons: * 1. If we crash while deleting the quotainode(s), and those blks got * used for user data. This is because we take the path of regular * file deletion; however, the size field of quotainodes is never * updated, so all the tricks that we play in itruncate_finish * don't quite matter. * * 2. We don't play the quota buffers when there's a quotaoff logitem. * But the allocation will be replayed so we'll end up with an * uninitialized quota block. * * This is all fine; things are still consistent, and we haven't lost * any quota information. Just don't complain about bad dquot blks. */ if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) { if (flags & XFS_QMOPT_DOWARN) xfs_alert(mp, "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC); errs++; } if (ddq->d_version != XFS_DQUOT_VERSION) { if (flags & XFS_QMOPT_DOWARN) xfs_alert(mp, "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", str, id, ddq->d_version, XFS_DQUOT_VERSION); errs++; } if (ddq->d_flags != XFS_DQ_USER && ddq->d_flags != XFS_DQ_PROJ && ddq->d_flags != XFS_DQ_GROUP) { if (flags & XFS_QMOPT_DOWARN) xfs_alert(mp, "%s : XFS dquot ID 0x%x, unknown flags 0x%x", str, id, ddq->d_flags); errs++; } if (id != -1 && id != be32_to_cpu(ddq->d_id)) { if (flags & XFS_QMOPT_DOWARN) xfs_alert(mp, "%s : ondisk-dquot 0x%p, ID mismatch: " "0x%x expected, found id 0x%x", str, ddq, id, be32_to_cpu(ddq->d_id)); errs++; } if (!errs && ddq->d_id) { if (ddq->d_blk_softlimit && be64_to_cpu(ddq->d_bcount) > be64_to_cpu(ddq->d_blk_softlimit)) { if (!ddq->d_btimer) { if (flags & XFS_QMOPT_DOWARN) xfs_alert(mp, "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } } if (ddq->d_ino_softlimit && be64_to_cpu(ddq->d_icount) > be64_to_cpu(ddq->d_ino_softlimit)) { if (!ddq->d_itimer) { if (flags & XFS_QMOPT_DOWARN) xfs_alert(mp, "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } } if (ddq->d_rtb_softlimit && be64_to_cpu(ddq->d_rtbcount) > be64_to_cpu(ddq->d_rtb_softlimit)) { if (!ddq->d_rtbtimer) { if (flags & XFS_QMOPT_DOWARN) xfs_alert(mp, "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } } } if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) return errs; if (flags & XFS_QMOPT_DOWARN) xfs_notice(mp, "Re-initializing dquot ID 0x%x", id); /* * Typically, a repair is only requested by quotacheck. */ ASSERT(id != -1); ASSERT(flags & XFS_QMOPT_DQREPAIR); memset(d, 0, sizeof(xfs_dqblk_t)); d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC); d->dd_diskdq.d_version = XFS_DQUOT_VERSION; d->dd_diskdq.d_flags = type; d->dd_diskdq.d_id = cpu_to_be32(id); if (xfs_sb_version_hascrc(&mp->m_sb)) { uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid); xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), XFS_DQUOT_CRC_OFF); } return errs; } STATIC bool xfs_dquot_buf_verify_crc( struct xfs_mount *mp, struct xfs_buf *bp) { struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; int ndquots; int i; if (!xfs_sb_version_hascrc(&mp->m_sb)) return true; /* * if we are in log recovery, the quota subsystem has not been * initialised so we have no quotainfo structure. In that case, we need * to manually calculate the number of dquots in the buffer. */ if (mp->m_quotainfo) ndquots = mp->m_quotainfo->qi_dqperchunk; else ndquots = xfs_calc_dquots_per_chunk(bp->b_length); for (i = 0; i < ndquots; i++, d++) { if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), XFS_DQUOT_CRC_OFF)) return false; if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_meta_uuid)) return false; } return true; } STATIC bool xfs_dquot_buf_verify( struct xfs_mount *mp, struct xfs_buf *bp, int warn) { struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; xfs_dqid_t id = 0; int ndquots; int i; /* * if we are in log recovery, the quota subsystem has not been * initialised so we have no quotainfo structure. In that case, we need * to manually calculate the number of dquots in the buffer. */ if (mp->m_quotainfo) ndquots = mp->m_quotainfo->qi_dqperchunk; else ndquots = xfs_calc_dquots_per_chunk(bp->b_length); /* * On the first read of the buffer, verify that each dquot is valid. * We don't know what the id of the dquot is supposed to be, just that * they should be increasing monotonically within the buffer. If the * first id is corrupt, then it will fail on the second dquot in the * buffer so corruptions could point to the wrong dquot in this case. */ for (i = 0; i < ndquots; i++) { struct xfs_disk_dquot *ddq; int error; ddq = &d[i].dd_diskdq; if (i == 0) id = be32_to_cpu(ddq->d_id); error = xfs_dqcheck(mp, ddq, id + i, 0, warn, __func__); if (error) return false; } return true; } static void xfs_dquot_buf_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (!xfs_dquot_buf_verify_crc(mp, bp)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_dquot_buf_verify(mp, bp, XFS_QMOPT_DOWARN)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } /* * readahead errors are silent and simply leave the buffer as !done so a real * read will then be run with the xfs_dquot_buf_ops verifier. See * xfs_inode_buf_verify() for why we use EIO and ~XBF_DONE here rather than * reporting the failure. */ static void xfs_dquot_buf_readahead_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp, 0)) { xfs_buf_ioerror(bp, -EIO); bp->b_flags &= ~XBF_DONE; } } /* * we don't calculate the CRC here as that is done when the dquot is flushed to * the buffer after the update is done. This ensures that the dquot in the * buffer always has an up-to-date CRC value. */ static void xfs_dquot_buf_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (!xfs_dquot_buf_verify(mp, bp, XFS_QMOPT_DOWARN)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } } const struct xfs_buf_ops xfs_dquot_buf_ops = { .name = "xfs_dquot", .verify_read = xfs_dquot_buf_read_verify, .verify_write = xfs_dquot_buf_write_verify, }; const struct xfs_buf_ops xfs_dquot_buf_ra_ops = { .name = "xfs_dquot_ra", .verify_read = xfs_dquot_buf_readahead_verify, .verify_write = xfs_dquot_buf_write_verify, }; xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_format.h0000644000000000000000000016247113063067171016315 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_FORMAT_H__ #define __XFS_FORMAT_H__ /* * XFS On Disk Format Definitions * * This header file defines all the on-disk format definitions for * general XFS objects. Directory and attribute related objects are defined in * xfs_da_format.h, which log and log item formats are defined in * xfs_log_format.h. Everything else goes here. */ struct xfs_mount; struct xfs_trans; struct xfs_inode; struct xfs_buf; struct xfs_ifork; /* * Super block * Fits into a sector-sized buffer at address 0 of each allocation group. * Only the first of these is ever updated except during growfs. */ #define XFS_SB_MAGIC 0x58465342 /* 'XFSB' */ #define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */ #define XFS_SB_VERSION_2 2 /* 6.2 - attributes */ #define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */ #define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ #define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ #define XFS_SB_VERSION_NUMBITS 0x000f #define XFS_SB_VERSION_ALLFBITS 0xfff0 #define XFS_SB_VERSION_ATTRBIT 0x0010 #define XFS_SB_VERSION_NLINKBIT 0x0020 #define XFS_SB_VERSION_QUOTABIT 0x0040 #define XFS_SB_VERSION_ALIGNBIT 0x0080 #define XFS_SB_VERSION_DALIGNBIT 0x0100 #define XFS_SB_VERSION_SHAREDBIT 0x0200 #define XFS_SB_VERSION_LOGV2BIT 0x0400 #define XFS_SB_VERSION_SECTORBIT 0x0800 #define XFS_SB_VERSION_EXTFLGBIT 0x1000 #define XFS_SB_VERSION_DIRV2BIT 0x2000 #define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */ #define XFS_SB_VERSION_MOREBITSBIT 0x8000 /* * The size of a single extended attribute on disk is limited by * the size of index values within the attribute entries themselves. * These are be16 fields, so we can only support attribute data * sizes up to 2^16 bytes in length. */ #define XFS_XATTR_SIZE_MAX (1 << 16) /* * Supported feature bit list is just all bits in the versionnum field because * we've used them all up and understand them all. Except, of course, for the * shared superblock bit, which nobody knows what it does and so is unsupported. */ #define XFS_SB_VERSION_OKBITS \ ((XFS_SB_VERSION_NUMBITS | XFS_SB_VERSION_ALLFBITS) & \ ~XFS_SB_VERSION_SHAREDBIT) /* * There are two words to hold XFS "feature" bits: the original * word, sb_versionnum, and sb_features2. Whenever a bit is set in * sb_features2, the feature bit XFS_SB_VERSION_MOREBITSBIT must be set. * * These defines represent bits in sb_features2. */ #define XFS_SB_VERSION2_RESERVED1BIT 0x00000001 #define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */ #define XFS_SB_VERSION2_RESERVED4BIT 0x00000004 #define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */ #define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* parent pointers */ #define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32 bit project id */ #define XFS_SB_VERSION2_CRCBIT 0x00000100 /* metadata CRCs */ #define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ #define XFS_SB_VERSION2_OKBITS \ (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ XFS_SB_VERSION2_ATTR2BIT | \ XFS_SB_VERSION2_PROJID32BIT | \ XFS_SB_VERSION2_FTYPE) /* * Superblock - in core version. Must match the ondisk version below. * Must be padded to 64 bit alignment. */ typedef struct xfs_sb { __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ __uint32_t sb_blocksize; /* logical block size, bytes */ xfs_rfsblock_t sb_dblocks; /* number of data blocks */ xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */ xfs_rtblock_t sb_rextents; /* number of realtime extents */ uuid_t sb_uuid; /* user-visible file system unique id */ xfs_fsblock_t sb_logstart; /* starting block of log if internal */ xfs_ino_t sb_rootino; /* root inode number */ xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */ xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */ xfs_agblock_t sb_agblocks; /* size of an allocation group */ xfs_agnumber_t sb_agcount; /* number of allocation groups */ xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */ xfs_extlen_t sb_logblocks; /* number of log blocks */ __uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ __uint16_t sb_sectsize; /* volume sector size, bytes */ __uint16_t sb_inodesize; /* inode size, bytes */ __uint16_t sb_inopblock; /* inodes per block */ char sb_fname[12]; /* file system name */ __uint8_t sb_blocklog; /* log2 of sb_blocksize */ __uint8_t sb_sectlog; /* log2 of sb_sectsize */ __uint8_t sb_inodelog; /* log2 of sb_inodesize */ __uint8_t sb_inopblog; /* log2 of sb_inopblock */ __uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ __uint8_t sb_rextslog; /* log2 of sb_rextents */ __uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ __uint8_t sb_imax_pct; /* max % of fs for inode space */ /* statistics */ /* * These fields must remain contiguous. If you really * want to change their layout, make sure you fix the * code in xfs_trans_apply_sb_deltas(). */ __uint64_t sb_icount; /* allocated inodes */ __uint64_t sb_ifree; /* free inodes */ __uint64_t sb_fdblocks; /* free data blocks */ __uint64_t sb_frextents; /* free realtime extents */ /* * End contiguous fields. */ xfs_ino_t sb_uquotino; /* user quota inode */ xfs_ino_t sb_gquotino; /* group quota inode */ __uint16_t sb_qflags; /* quota flags */ __uint8_t sb_flags; /* misc. flags */ __uint8_t sb_shared_vn; /* shared version number */ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ __uint32_t sb_unit; /* stripe or raid unit */ __uint32_t sb_width; /* stripe or raid width */ __uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */ __uint8_t sb_logsectlog; /* log2 of the log sector size */ __uint16_t sb_logsectsize; /* sector size for the log, bytes */ __uint32_t sb_logsunit; /* stripe unit size for the log */ __uint32_t sb_features2; /* additional feature bits */ /* * bad features2 field as a result of failing to pad the sb structure to * 64 bits. Some machines will be using this field for features2 bits. * Easiest just to mark it bad and not use it for anything else. * * This is not kept up to date in memory; it is always overwritten by * the value in sb_features2 when formatting the incore superblock to * the disk buffer. */ __uint32_t sb_bad_features2; /* version 5 superblock fields start here */ /* feature masks */ __uint32_t sb_features_compat; __uint32_t sb_features_ro_compat; __uint32_t sb_features_incompat; __uint32_t sb_features_log_incompat; __uint32_t sb_crc; /* superblock crc */ xfs_extlen_t sb_spino_align; /* sparse inode chunk alignment */ xfs_ino_t sb_pquotino; /* project quota inode */ xfs_lsn_t sb_lsn; /* last write sequence */ uuid_t sb_meta_uuid; /* metadata file system unique id */ /* must be padded to 64 bit alignment */ } xfs_sb_t; #define XFS_SB_CRC_OFF offsetof(struct xfs_sb, sb_crc) /* * Superblock - on disk version. Must match the in core version above. * Must be padded to 64 bit alignment. */ typedef struct xfs_dsb { __be32 sb_magicnum; /* magic number == XFS_SB_MAGIC */ __be32 sb_blocksize; /* logical block size, bytes */ __be64 sb_dblocks; /* number of data blocks */ __be64 sb_rblocks; /* number of realtime blocks */ __be64 sb_rextents; /* number of realtime extents */ uuid_t sb_uuid; /* user-visible file system unique id */ __be64 sb_logstart; /* starting block of log if internal */ __be64 sb_rootino; /* root inode number */ __be64 sb_rbmino; /* bitmap inode for realtime extents */ __be64 sb_rsumino; /* summary inode for rt bitmap */ __be32 sb_rextsize; /* realtime extent size, blocks */ __be32 sb_agblocks; /* size of an allocation group */ __be32 sb_agcount; /* number of allocation groups */ __be32 sb_rbmblocks; /* number of rt bitmap blocks */ __be32 sb_logblocks; /* number of log blocks */ __be16 sb_versionnum; /* header version == XFS_SB_VERSION */ __be16 sb_sectsize; /* volume sector size, bytes */ __be16 sb_inodesize; /* inode size, bytes */ __be16 sb_inopblock; /* inodes per block */ char sb_fname[12]; /* file system name */ __u8 sb_blocklog; /* log2 of sb_blocksize */ __u8 sb_sectlog; /* log2 of sb_sectsize */ __u8 sb_inodelog; /* log2 of sb_inodesize */ __u8 sb_inopblog; /* log2 of sb_inopblock */ __u8 sb_agblklog; /* log2 of sb_agblocks (rounded up) */ __u8 sb_rextslog; /* log2 of sb_rextents */ __u8 sb_inprogress; /* mkfs is in progress, don't mount */ __u8 sb_imax_pct; /* max % of fs for inode space */ /* statistics */ /* * These fields must remain contiguous. If you really * want to change their layout, make sure you fix the * code in xfs_trans_apply_sb_deltas(). */ __be64 sb_icount; /* allocated inodes */ __be64 sb_ifree; /* free inodes */ __be64 sb_fdblocks; /* free data blocks */ __be64 sb_frextents; /* free realtime extents */ /* * End contiguous fields. */ __be64 sb_uquotino; /* user quota inode */ __be64 sb_gquotino; /* group quota inode */ __be16 sb_qflags; /* quota flags */ __u8 sb_flags; /* misc. flags */ __u8 sb_shared_vn; /* shared version number */ __be32 sb_inoalignmt; /* inode chunk alignment, fsblocks */ __be32 sb_unit; /* stripe or raid unit */ __be32 sb_width; /* stripe or raid width */ __u8 sb_dirblklog; /* log2 of dir block size (fsbs) */ __u8 sb_logsectlog; /* log2 of the log sector size */ __be16 sb_logsectsize; /* sector size for the log, bytes */ __be32 sb_logsunit; /* stripe unit size for the log */ __be32 sb_features2; /* additional feature bits */ /* * bad features2 field as a result of failing to pad the sb * structure to 64 bits. Some machines will be using this field * for features2 bits. Easiest just to mark it bad and not use * it for anything else. */ __be32 sb_bad_features2; /* version 5 superblock fields start here */ /* feature masks */ __be32 sb_features_compat; __be32 sb_features_ro_compat; __be32 sb_features_incompat; __be32 sb_features_log_incompat; __le32 sb_crc; /* superblock crc */ __be32 sb_spino_align; /* sparse inode chunk alignment */ __be64 sb_pquotino; /* project quota inode */ __be64 sb_lsn; /* last write sequence */ uuid_t sb_meta_uuid; /* metadata file system unique id */ /* must be padded to 64 bit alignment */ } xfs_dsb_t; /* * Misc. Flags - warning - these will be cleared by xfs_repair unless * a feature bit is set when the flag is used. */ #define XFS_SBF_NOFLAGS 0x00 /* no flags set */ #define XFS_SBF_READONLY 0x01 /* only read-only mounts allowed */ /* * define max. shared version we can interoperate with */ #define XFS_SB_MAX_SHARED_VN 0 #define XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS) /* * The first XFS version we support is a v4 superblock with V2 directories. */ static inline bool xfs_sb_good_v4_features(struct xfs_sb *sbp) { if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) return false; /* check for unknown features in the fs */ if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKBITS) || ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && (sbp->sb_features2 & ~XFS_SB_VERSION2_OKBITS))) return false; return true; } static inline bool xfs_sb_good_version(struct xfs_sb *sbp) { if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) return true; if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) return xfs_sb_good_v4_features(sbp); return false; } /* * Detect a mismatched features2 field. Older kernels read/wrote * this into the wrong slot, so to be safe we keep them in sync. */ static inline bool xfs_sb_has_mismatched_features2(struct xfs_sb *sbp) { return sbp->sb_bad_features2 != sbp->sb_features2; } static inline bool xfs_sb_version_hasattr(struct xfs_sb *sbp) { return (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT); } static inline void xfs_sb_version_addattr(struct xfs_sb *sbp) { sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; } static inline bool xfs_sb_version_hasquota(struct xfs_sb *sbp) { return (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT); } static inline void xfs_sb_version_addquota(struct xfs_sb *sbp) { sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT; } static inline bool xfs_sb_version_hasalign(struct xfs_sb *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT)); } static inline bool xfs_sb_version_hasdalign(struct xfs_sb *sbp) { return (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT); } static inline bool xfs_sb_version_haslogv2(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT); } static inline bool xfs_sb_version_hasextflgbit(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT); } static inline bool xfs_sb_version_hassector(struct xfs_sb *sbp) { return (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT); } static inline bool xfs_sb_version_hasasciici(struct xfs_sb *sbp) { return (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT); } static inline bool xfs_sb_version_hasmorebits(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT); } /* * sb_features2 bit version macros. */ static inline bool xfs_sb_version_haslazysbcount(struct xfs_sb *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || (xfs_sb_version_hasmorebits(sbp) && (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT)); } static inline bool xfs_sb_version_hasattr2(struct xfs_sb *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || (xfs_sb_version_hasmorebits(sbp) && (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT)); } static inline void xfs_sb_version_addattr2(struct xfs_sb *sbp) { sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT; } static inline void xfs_sb_version_removeattr2(struct xfs_sb *sbp) { sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT; if (!sbp->sb_features2) sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT; } static inline bool xfs_sb_version_hasprojid32bit(struct xfs_sb *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || (xfs_sb_version_hasmorebits(sbp) && (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT)); } static inline void xfs_sb_version_addprojid32bit(struct xfs_sb *sbp) { sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; } /* * Extended v5 superblock feature masks. These are to be used for new v5 * superblock features only. * * Compat features are new features that old kernels will not notice or affect * and so can mount read-write without issues. * * RO-Compat (read only) are features that old kernels can read but will break * if they write. Hence only read-only mounts of such filesystems are allowed on * kernels that don't support the feature bit. * * InCompat features are features which old kernels will not understand and so * must not mount. * * Log-InCompat features are for changes to log formats or new transactions that * can't be replayed on older kernels. The fields are set when the filesystem is * mounted, and a clean unmount clears the fields. */ #define XFS_SB_FEAT_COMPAT_ALL 0 #define XFS_SB_FEAT_COMPAT_UNKNOWN ~XFS_SB_FEAT_COMPAT_ALL static inline bool xfs_sb_has_compat_feature( struct xfs_sb *sbp, __uint32_t feature) { return (sbp->sb_features_compat & feature) != 0; } #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ XFS_SB_FEAT_RO_COMPAT_REFLINK) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool xfs_sb_has_ro_compat_feature( struct xfs_sb *sbp, __uint32_t feature) { return (sbp->sb_features_ro_compat & feature) != 0; } #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ #define XFS_SB_FEAT_INCOMPAT_ALL \ (XFS_SB_FEAT_INCOMPAT_FTYPE| \ XFS_SB_FEAT_INCOMPAT_SPINODES| \ XFS_SB_FEAT_INCOMPAT_META_UUID) #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL static inline bool xfs_sb_has_incompat_feature( struct xfs_sb *sbp, __uint32_t feature) { return (sbp->sb_features_incompat & feature) != 0; } #define XFS_SB_FEAT_INCOMPAT_LOG_ALL 0 #define XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_LOG_ALL static inline bool xfs_sb_has_incompat_log_feature( struct xfs_sb *sbp, __uint32_t feature) { return (sbp->sb_features_log_incompat & feature) != 0; } /* * V5 superblock specific feature checks */ static inline int xfs_sb_version_hascrc(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; } static inline int xfs_sb_version_has_pquotino(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; } static inline int xfs_sb_version_hasftype(struct xfs_sb *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_FTYPE)) || (xfs_sb_version_hasmorebits(sbp) && (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE)); } static inline int xfs_sb_version_hasfinobt(xfs_sb_t *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); } static inline bool xfs_sb_version_hassparseinodes(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_SPINODES); } /* * XFS_SB_FEAT_INCOMPAT_META_UUID indicates that the metadata UUID * is stored separately from the user-visible UUID; this allows the * user-visible UUID to be changed on V5 filesystems which have a * filesystem UUID stamped into every piece of metadata. */ static inline int xfs_sb_version_hasmetauuid(xfs_sb_t *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID); } static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT); } static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK); } /* * end of superblock version macros */ static inline bool xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino) { return (ino == sbp->sb_uquotino || ino == sbp->sb_gquotino || ino == sbp->sb_pquotino); } #define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */ #define XFS_SB_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_SB_DADDR) #define XFS_BUF_TO_SBP(bp) ((xfs_dsb_t *)((bp)->b_addr)) #define XFS_HDR_BLOCK(mp,d) ((xfs_agblock_t)XFS_BB_TO_FSBT(mp,d)) #define XFS_DADDR_TO_FSB(mp,d) XFS_AGB_TO_FSB(mp, \ xfs_daddr_to_agno(mp,d), xfs_daddr_to_agbno(mp,d)) #define XFS_FSB_TO_DADDR(mp,fsbno) XFS_AGB_TO_DADDR(mp, \ XFS_FSB_TO_AGNO(mp,fsbno), XFS_FSB_TO_AGBNO(mp,fsbno)) /* * File system sector to basic block conversions. */ #define XFS_FSS_TO_BB(mp,sec) ((sec) << (mp)->m_sectbb_log) /* * File system block to basic block conversions. */ #define XFS_FSB_TO_BB(mp,fsbno) ((fsbno) << (mp)->m_blkbb_log) #define XFS_BB_TO_FSB(mp,bb) \ (((bb) + (XFS_FSB_TO_BB(mp,1) - 1)) >> (mp)->m_blkbb_log) #define XFS_BB_TO_FSBT(mp,bb) ((bb) >> (mp)->m_blkbb_log) /* * File system block to byte conversions. */ #define XFS_FSB_TO_B(mp,fsbno) ((xfs_fsize_t)(fsbno) << (mp)->m_sb.sb_blocklog) #define XFS_B_TO_FSB(mp,b) \ ((((__uint64_t)(b)) + (mp)->m_blockmask) >> (mp)->m_sb.sb_blocklog) #define XFS_B_TO_FSBT(mp,b) (((__uint64_t)(b)) >> (mp)->m_sb.sb_blocklog) #define XFS_B_FSB_OFFSET(mp,b) ((b) & (mp)->m_blockmask) /* * Allocation group header * * This is divided into three structures, placed in sequential 512-byte * buffers after a copy of the superblock (also in a 512-byte buffer). */ #define XFS_AGF_MAGIC 0x58414746 /* 'XAGF' */ #define XFS_AGI_MAGIC 0x58414749 /* 'XAGI' */ #define XFS_AGFL_MAGIC 0x5841464c /* 'XAFL' */ #define XFS_AGF_VERSION 1 #define XFS_AGI_VERSION 1 #define XFS_AGF_GOOD_VERSION(v) ((v) == XFS_AGF_VERSION) #define XFS_AGI_GOOD_VERSION(v) ((v) == XFS_AGI_VERSION) /* * Btree number 0 is bno, 1 is cnt, 2 is rmap. This value gives the size of the * arrays below. */ #define XFS_BTNUM_AGF ((int)XFS_BTNUM_RMAPi + 1) /* * The second word of agf_levels in the first a.g. overlaps the EFS * superblock's magic number. Since the magic numbers valid for EFS * are > 64k, our value cannot be confused for an EFS superblock's. */ typedef struct xfs_agf { /* * Common allocation group header information */ __be32 agf_magicnum; /* magic number == XFS_AGF_MAGIC */ __be32 agf_versionnum; /* header version == XFS_AGF_VERSION */ __be32 agf_seqno; /* sequence # starting from 0 */ __be32 agf_length; /* size in blocks of a.g. */ /* * Freespace and rmap information */ __be32 agf_roots[XFS_BTNUM_AGF]; /* root blocks */ __be32 agf_levels[XFS_BTNUM_AGF]; /* btree levels */ __be32 agf_flfirst; /* first freelist block's index */ __be32 agf_fllast; /* last freelist block's index */ __be32 agf_flcount; /* count of blocks in freelist */ __be32 agf_freeblks; /* total free blocks */ __be32 agf_longest; /* longest free space */ __be32 agf_btreeblks; /* # of blocks held in AGF btrees */ uuid_t agf_uuid; /* uuid of filesystem */ __be32 agf_rmap_blocks; /* rmapbt blocks used */ __be32 agf_refcount_blocks; /* refcountbt blocks used */ __be32 agf_refcount_root; /* refcount tree root block */ __be32 agf_refcount_level; /* refcount btree levels */ /* * reserve some contiguous space for future logged fields before we add * the unlogged fields. This makes the range logging via flags and * structure offsets much simpler. */ __be64 agf_spare64[14]; /* unlogged fields, written during buffer writeback. */ __be64 agf_lsn; /* last write sequence */ __be32 agf_crc; /* crc of agf sector */ __be32 agf_spare2; /* structure must be padded to 64 bit alignment */ } xfs_agf_t; #define XFS_AGF_CRC_OFF offsetof(struct xfs_agf, agf_crc) #define XFS_AGF_MAGICNUM 0x00000001 #define XFS_AGF_VERSIONNUM 0x00000002 #define XFS_AGF_SEQNO 0x00000004 #define XFS_AGF_LENGTH 0x00000008 #define XFS_AGF_ROOTS 0x00000010 #define XFS_AGF_LEVELS 0x00000020 #define XFS_AGF_FLFIRST 0x00000040 #define XFS_AGF_FLLAST 0x00000080 #define XFS_AGF_FLCOUNT 0x00000100 #define XFS_AGF_FREEBLKS 0x00000200 #define XFS_AGF_LONGEST 0x00000400 #define XFS_AGF_BTREEBLKS 0x00000800 #define XFS_AGF_UUID 0x00001000 #define XFS_AGF_RMAP_BLOCKS 0x00002000 #define XFS_AGF_REFCOUNT_BLOCKS 0x00004000 #define XFS_AGF_REFCOUNT_ROOT 0x00008000 #define XFS_AGF_REFCOUNT_LEVEL 0x00010000 #define XFS_AGF_SPARE64 0x00020000 #define XFS_AGF_NUM_BITS 18 #define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1) #define XFS_AGF_FLAGS \ { XFS_AGF_MAGICNUM, "MAGICNUM" }, \ { XFS_AGF_VERSIONNUM, "VERSIONNUM" }, \ { XFS_AGF_SEQNO, "SEQNO" }, \ { XFS_AGF_LENGTH, "LENGTH" }, \ { XFS_AGF_ROOTS, "ROOTS" }, \ { XFS_AGF_LEVELS, "LEVELS" }, \ { XFS_AGF_FLFIRST, "FLFIRST" }, \ { XFS_AGF_FLLAST, "FLLAST" }, \ { XFS_AGF_FLCOUNT, "FLCOUNT" }, \ { XFS_AGF_FREEBLKS, "FREEBLKS" }, \ { XFS_AGF_LONGEST, "LONGEST" }, \ { XFS_AGF_BTREEBLKS, "BTREEBLKS" }, \ { XFS_AGF_UUID, "UUID" }, \ { XFS_AGF_RMAP_BLOCKS, "RMAP_BLOCKS" }, \ { XFS_AGF_REFCOUNT_BLOCKS, "REFCOUNT_BLOCKS" }, \ { XFS_AGF_REFCOUNT_ROOT, "REFCOUNT_ROOT" }, \ { XFS_AGF_REFCOUNT_LEVEL, "REFCOUNT_LEVEL" }, \ { XFS_AGF_SPARE64, "SPARE64" } /* disk block (xfs_daddr_t) in the AG */ #define XFS_AGF_DADDR(mp) ((xfs_daddr_t)(1 << (mp)->m_sectbb_log)) #define XFS_AGF_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp)) #define XFS_BUF_TO_AGF(bp) ((xfs_agf_t *)((bp)->b_addr)) /* * Size of the unlinked inode hash table in the agi. */ #define XFS_AGI_UNLINKED_BUCKETS 64 typedef struct xfs_agi { /* * Common allocation group header information */ __be32 agi_magicnum; /* magic number == XFS_AGI_MAGIC */ __be32 agi_versionnum; /* header version == XFS_AGI_VERSION */ __be32 agi_seqno; /* sequence # starting from 0 */ __be32 agi_length; /* size in blocks of a.g. */ /* * Inode information * Inodes are mapped by interpreting the inode number, so no * mapping data is needed here. */ __be32 agi_count; /* count of allocated inodes */ __be32 agi_root; /* root of inode btree */ __be32 agi_level; /* levels in inode btree */ __be32 agi_freecount; /* number of free inodes */ __be32 agi_newino; /* new inode just allocated */ __be32 agi_dirino; /* last directory inode chunk */ /* * Hash table of inodes which have been unlinked but are * still being referenced. */ __be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS]; /* * This marks the end of logging region 1 and start of logging region 2. */ uuid_t agi_uuid; /* uuid of filesystem */ __be32 agi_crc; /* crc of agi sector */ __be32 agi_pad32; __be64 agi_lsn; /* last write sequence */ __be32 agi_free_root; /* root of the free inode btree */ __be32 agi_free_level;/* levels in free inode btree */ /* structure must be padded to 64 bit alignment */ } xfs_agi_t; #define XFS_AGI_CRC_OFF offsetof(struct xfs_agi, agi_crc) #define XFS_AGI_MAGICNUM (1 << 0) #define XFS_AGI_VERSIONNUM (1 << 1) #define XFS_AGI_SEQNO (1 << 2) #define XFS_AGI_LENGTH (1 << 3) #define XFS_AGI_COUNT (1 << 4) #define XFS_AGI_ROOT (1 << 5) #define XFS_AGI_LEVEL (1 << 6) #define XFS_AGI_FREECOUNT (1 << 7) #define XFS_AGI_NEWINO (1 << 8) #define XFS_AGI_DIRINO (1 << 9) #define XFS_AGI_UNLINKED (1 << 10) #define XFS_AGI_NUM_BITS_R1 11 /* end of the 1st agi logging region */ #define XFS_AGI_ALL_BITS_R1 ((1 << XFS_AGI_NUM_BITS_R1) - 1) #define XFS_AGI_FREE_ROOT (1 << 11) #define XFS_AGI_FREE_LEVEL (1 << 12) #define XFS_AGI_NUM_BITS_R2 13 /* disk block (xfs_daddr_t) in the AG */ #define XFS_AGI_DADDR(mp) ((xfs_daddr_t)(2 << (mp)->m_sectbb_log)) #define XFS_AGI_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp)) #define XFS_BUF_TO_AGI(bp) ((xfs_agi_t *)((bp)->b_addr)) /* * The third a.g. block contains the a.g. freelist, an array * of block pointers to blocks owned by the allocation btree code. */ #define XFS_AGFL_DADDR(mp) ((xfs_daddr_t)(3 << (mp)->m_sectbb_log)) #define XFS_AGFL_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp)) #define XFS_BUF_TO_AGFL(bp) ((xfs_agfl_t *)((bp)->b_addr)) #define XFS_BUF_TO_AGFL_BNO(mp, bp) \ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ &(XFS_BUF_TO_AGFL(bp)->agfl_bno[0]) : \ (__be32 *)(bp)->b_addr) /* * Size of the AGFL. For CRC-enabled filesystes we steal a couple of * slots in the beginning of the block for a proper header with the * location information and CRC. */ #define XFS_AGFL_SIZE(mp) \ (((mp)->m_sb.sb_sectsize - \ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ sizeof(struct xfs_agfl) : 0)) / \ sizeof(xfs_agblock_t)) typedef struct xfs_agfl { __be32 agfl_magicnum; __be32 agfl_seqno; uuid_t agfl_uuid; __be64 agfl_lsn; __be32 agfl_crc; __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */ } __attribute__((packed)) xfs_agfl_t; #define XFS_AGFL_CRC_OFF offsetof(struct xfs_agfl, agfl_crc) #define XFS_AGB_TO_FSB(mp,agno,agbno) \ (((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno)) #define XFS_FSB_TO_AGNO(mp,fsbno) \ ((xfs_agnumber_t)((fsbno) >> (mp)->m_sb.sb_agblklog)) #define XFS_FSB_TO_AGBNO(mp,fsbno) \ ((xfs_agblock_t)((fsbno) & xfs_mask32lo((mp)->m_sb.sb_agblklog))) #define XFS_AGB_TO_DADDR(mp,agno,agbno) \ ((xfs_daddr_t)XFS_FSB_TO_BB(mp, \ (xfs_fsblock_t)(agno) * (mp)->m_sb.sb_agblocks + (agbno))) #define XFS_AG_DADDR(mp,agno,d) (XFS_AGB_TO_DADDR(mp, agno, 0) + (d)) /* * For checking for bad ranges of xfs_daddr_t's, covering multiple * allocation groups or a single xfs_daddr_t that's a superblock copy. */ #define XFS_AG_CHECK_DADDR(mp,d,len) \ ((len) == 1 ? \ ASSERT((d) == XFS_SB_DADDR || \ xfs_daddr_to_agbno(mp, d) != XFS_SB_DADDR) : \ ASSERT(xfs_daddr_to_agno(mp, d) == \ xfs_daddr_to_agno(mp, (d) + (len) - 1))) typedef struct xfs_timestamp { __be32 t_sec; /* timestamp seconds */ __be32 t_nsec; /* timestamp nanoseconds */ } xfs_timestamp_t; /* * On-disk inode structure. * * This is just the header or "dinode core", the inode is expanded to fill a * variable size the leftover area split into a data and an attribute fork. * The format of the data and attribute fork depends on the format of the * inode as indicated by di_format and di_aformat. To access the data and * attribute use the XFS_DFORK_DPTR, XFS_DFORK_APTR, and XFS_DFORK_PTR macros * below. * * There is a very similar struct icdinode in xfs_inode which matches the * layout of the first 96 bytes of this structure, but is kept in native * format instead of big endian. * * Note: di_flushiter is only used by v1/2 inodes - it's effectively a zeroed * padding field for v3 inodes. */ #define XFS_DINODE_MAGIC 0x494e /* 'IN' */ typedef struct xfs_dinode { __be16 di_magic; /* inode magic # = XFS_DINODE_MAGIC */ __be16 di_mode; /* mode and type of file */ __u8 di_version; /* inode version */ __u8 di_format; /* format of di_c data */ __be16 di_onlink; /* old number of links to file */ __be32 di_uid; /* owner's user id */ __be32 di_gid; /* owner's group id */ __be32 di_nlink; /* number of links to file */ __be16 di_projid_lo; /* lower part of owner's project id */ __be16 di_projid_hi; /* higher part owner's project id */ __u8 di_pad[6]; /* unused, zeroed space */ __be16 di_flushiter; /* incremented on flush */ xfs_timestamp_t di_atime; /* time last accessed */ xfs_timestamp_t di_mtime; /* time last modified */ xfs_timestamp_t di_ctime; /* time created/inode modified */ __be64 di_size; /* number of bytes in file */ __be64 di_nblocks; /* # of direct & btree blocks used */ __be32 di_extsize; /* basic/minimum extent size for file */ __be32 di_nextents; /* number of extents in data fork */ __be16 di_anextents; /* number of extents in attribute fork*/ __u8 di_forkoff; /* attr fork offs, <<3 for 64b align */ __s8 di_aformat; /* format of attr fork's data */ __be32 di_dmevmask; /* DMIG event mask */ __be16 di_dmstate; /* DMIG state info */ __be16 di_flags; /* random flags, XFS_DIFLAG_... */ __be32 di_gen; /* generation number */ /* di_next_unlinked is the only non-core field in the old dinode */ __be32 di_next_unlinked;/* agi unlinked list ptr */ /* start of the extended dinode, writable fields */ __le32 di_crc; /* CRC of the inode */ __be64 di_changecount; /* number of attribute changes */ __be64 di_lsn; /* flush sequence */ __be64 di_flags2; /* more random flags */ __be32 di_cowextsize; /* basic cow extent size for file */ __u8 di_pad2[12]; /* more padding for future expansion */ /* fields only written to during inode creation */ xfs_timestamp_t di_crtime; /* time created */ __be64 di_ino; /* inode number */ uuid_t di_uuid; /* UUID of the filesystem */ /* structure must be padded to 64 bit alignment */ } xfs_dinode_t; #define XFS_DINODE_CRC_OFF offsetof(struct xfs_dinode, di_crc) #define DI_MAX_FLUSH 0xffff /* * Size of the core inode on disk. Version 1 and 2 inodes have * the same size, but version 3 has grown a few additional fields. */ static inline uint xfs_dinode_size(int version) { if (version == 3) return sizeof(struct xfs_dinode); return offsetof(struct xfs_dinode, di_crc); } /* * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. * Since the pathconf interface is signed, we use 2^31 - 1 instead. * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX. */ #define XFS_MAXLINK ((1U << 31) - 1U) #define XFS_MAXLINK_1 65535U /* * Values for di_format */ typedef enum xfs_dinode_fmt { XFS_DINODE_FMT_DEV, /* xfs_dev_t */ XFS_DINODE_FMT_LOCAL, /* bulk data */ XFS_DINODE_FMT_EXTENTS, /* struct xfs_bmbt_rec */ XFS_DINODE_FMT_BTREE, /* struct xfs_bmdr_block */ XFS_DINODE_FMT_UUID /* uuid_t */ } xfs_dinode_fmt_t; /* * Inode minimum and maximum sizes. */ #define XFS_DINODE_MIN_LOG 8 #define XFS_DINODE_MAX_LOG 11 #define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG) #define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG) /* * Inode size for given fs. */ #define XFS_LITINO(mp, version) \ ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version))) /* * Inode data & attribute fork sizes, per inode. */ #define XFS_DFORK_Q(dip) ((dip)->di_forkoff != 0) #define XFS_DFORK_BOFF(dip) ((int)((dip)->di_forkoff << 3)) #define XFS_DFORK_DSIZE(dip,mp) \ (XFS_DFORK_Q(dip) ? \ XFS_DFORK_BOFF(dip) : \ XFS_LITINO(mp, (dip)->di_version)) #define XFS_DFORK_ASIZE(dip,mp) \ (XFS_DFORK_Q(dip) ? \ XFS_LITINO(mp, (dip)->di_version) - XFS_DFORK_BOFF(dip) : \ 0) #define XFS_DFORK_SIZE(dip,mp,w) \ ((w) == XFS_DATA_FORK ? \ XFS_DFORK_DSIZE(dip, mp) : \ XFS_DFORK_ASIZE(dip, mp)) /* * Return pointers to the data or attribute forks. */ #define XFS_DFORK_DPTR(dip) \ ((char *)dip + xfs_dinode_size(dip->di_version)) #define XFS_DFORK_APTR(dip) \ (XFS_DFORK_DPTR(dip) + XFS_DFORK_BOFF(dip)) #define XFS_DFORK_PTR(dip,w) \ ((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR(dip) : XFS_DFORK_APTR(dip)) #define XFS_DFORK_FORMAT(dip,w) \ ((w) == XFS_DATA_FORK ? \ (dip)->di_format : \ (dip)->di_aformat) #define XFS_DFORK_NEXTENTS(dip,w) \ ((w) == XFS_DATA_FORK ? \ be32_to_cpu((dip)->di_nextents) : \ be16_to_cpu((dip)->di_anextents)) /* * For block and character special files the 32bit dev_t is stored at the * beginning of the data fork. */ static inline xfs_dev_t xfs_dinode_get_rdev(struct xfs_dinode *dip) { return be32_to_cpu(*(__be32 *)XFS_DFORK_DPTR(dip)); } static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) { *(__be32 *)XFS_DFORK_DPTR(dip) = cpu_to_be32(rdev); } /* * Values for di_flags */ #define XFS_DIFLAG_REALTIME_BIT 0 /* file's blocks come from rt area */ #define XFS_DIFLAG_PREALLOC_BIT 1 /* file space has been preallocated */ #define XFS_DIFLAG_NEWRTBM_BIT 2 /* for rtbitmap inode, new format */ #define XFS_DIFLAG_IMMUTABLE_BIT 3 /* inode is immutable */ #define XFS_DIFLAG_APPEND_BIT 4 /* inode is append-only */ #define XFS_DIFLAG_SYNC_BIT 5 /* inode is written synchronously */ #define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */ #define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */ #define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */ #define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */ #define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ #define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ #define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ #define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */ #define XFS_DIFLAG_FILESTREAM_BIT 14 /* use filestream allocator */ #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) #define XFS_DIFLAG_IMMUTABLE (1 << XFS_DIFLAG_IMMUTABLE_BIT) #define XFS_DIFLAG_APPEND (1 << XFS_DIFLAG_APPEND_BIT) #define XFS_DIFLAG_SYNC (1 << XFS_DIFLAG_SYNC_BIT) #define XFS_DIFLAG_NOATIME (1 << XFS_DIFLAG_NOATIME_BIT) #define XFS_DIFLAG_NODUMP (1 << XFS_DIFLAG_NODUMP_BIT) #define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT) #define XFS_DIFLAG_PROJINHERIT (1 << XFS_DIFLAG_PROJINHERIT_BIT) #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) #define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) #define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) #define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT) #define XFS_DIFLAG_FILESTREAM (1 << XFS_DIFLAG_FILESTREAM_BIT) #define XFS_DIFLAG_ANY \ (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM) /* * Values for di_flags2 These start by being exposed to userspace in the upper * 16 bits of the XFS_XFLAG_s range. */ #define XFS_DIFLAG2_DAX_BIT 0 /* use DAX for this inode */ #define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */ #define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */ #define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT) #define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT) #define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT) #define XFS_DIFLAG2_ANY \ (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE) /* * Inode number format: * low inopblog bits - offset in block * next agblklog bits - block number in ag * next agno_log bits - ag number * high agno_log-agblklog-inopblog bits - 0 */ #define XFS_INO_MASK(k) (__uint32_t)((1ULL << (k)) - 1) #define XFS_INO_OFFSET_BITS(mp) (mp)->m_sb.sb_inopblog #define XFS_INO_AGBNO_BITS(mp) (mp)->m_sb.sb_agblklog #define XFS_INO_AGINO_BITS(mp) (mp)->m_agino_log #define XFS_INO_AGNO_BITS(mp) (mp)->m_agno_log #define XFS_INO_BITS(mp) \ XFS_INO_AGNO_BITS(mp) + XFS_INO_AGINO_BITS(mp) #define XFS_INO_TO_AGNO(mp,i) \ ((xfs_agnumber_t)((i) >> XFS_INO_AGINO_BITS(mp))) #define XFS_INO_TO_AGINO(mp,i) \ ((xfs_agino_t)(i) & XFS_INO_MASK(XFS_INO_AGINO_BITS(mp))) #define XFS_INO_TO_AGBNO(mp,i) \ (((xfs_agblock_t)(i) >> XFS_INO_OFFSET_BITS(mp)) & \ XFS_INO_MASK(XFS_INO_AGBNO_BITS(mp))) #define XFS_INO_TO_OFFSET(mp,i) \ ((int)(i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp))) #define XFS_INO_TO_FSB(mp,i) \ XFS_AGB_TO_FSB(mp, XFS_INO_TO_AGNO(mp,i), XFS_INO_TO_AGBNO(mp,i)) #define XFS_AGINO_TO_INO(mp,a,i) \ (((xfs_ino_t)(a) << XFS_INO_AGINO_BITS(mp)) | (i)) #define XFS_AGINO_TO_AGBNO(mp,i) ((i) >> XFS_INO_OFFSET_BITS(mp)) #define XFS_AGINO_TO_OFFSET(mp,i) \ ((i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp))) #define XFS_OFFBNO_TO_AGINO(mp,b,o) \ ((xfs_agino_t)(((b) << XFS_INO_OFFSET_BITS(mp)) | (o))) #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 56) - 1ULL)) #define XFS_MAXINUMBER_32 ((xfs_ino_t)((1ULL << 32) - 1ULL)) /* * RealTime Device format definitions */ /* Min and max rt extent sizes, specified in bytes */ #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */ #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */ #define XFS_BLOCKSIZE(mp) ((mp)->m_sb.sb_blocksize) #define XFS_BLOCKMASK(mp) ((mp)->m_blockmask) #define XFS_BLOCKWSIZE(mp) ((mp)->m_blockwsize) #define XFS_BLOCKWMASK(mp) ((mp)->m_blockwmask) /* * RT Summary and bit manipulation macros. */ #define XFS_SUMOFFS(mp,ls,bb) ((int)((ls) * (mp)->m_sb.sb_rbmblocks + (bb))) #define XFS_SUMOFFSTOBLOCK(mp,s) \ (((s) * (uint)sizeof(xfs_suminfo_t)) >> (mp)->m_sb.sb_blocklog) #define XFS_SUMPTR(mp,bp,so) \ ((xfs_suminfo_t *)((bp)->b_addr + \ (((so) * (uint)sizeof(xfs_suminfo_t)) & XFS_BLOCKMASK(mp)))) #define XFS_BITTOBLOCK(mp,bi) ((bi) >> (mp)->m_blkbit_log) #define XFS_BLOCKTOBIT(mp,bb) ((bb) << (mp)->m_blkbit_log) #define XFS_BITTOWORD(mp,bi) \ ((int)(((bi) >> XFS_NBWORDLOG) & XFS_BLOCKWMASK(mp))) #define XFS_RTMIN(a,b) ((a) < (b) ? (a) : (b)) #define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b)) #define XFS_RTLOBIT(w) xfs_lowbit32(w) #define XFS_RTHIBIT(w) xfs_highbit32(w) #define XFS_RTBLOCKLOG(b) xfs_highbit64(b) /* * Dquot and dquot block format definitions */ #define XFS_DQUOT_MAGIC 0x4451 /* 'DQ' */ #define XFS_DQUOT_VERSION (u_int8_t)0x01 /* latest version number */ /* * This is the main portion of the on-disk representation of quota * information for a user. This is the q_core of the xfs_dquot_t that * is kept in kernel memory. We pad this with some more expansion room * to construct the on disk structure. */ typedef struct xfs_disk_dquot { __be16 d_magic; /* dquot magic = XFS_DQUOT_MAGIC */ __u8 d_version; /* dquot version */ __u8 d_flags; /* XFS_DQ_USER/PROJ/GROUP */ __be32 d_id; /* user,project,group id */ __be64 d_blk_hardlimit;/* absolute limit on disk blks */ __be64 d_blk_softlimit;/* preferred limit on disk blks */ __be64 d_ino_hardlimit;/* maximum # allocated inodes */ __be64 d_ino_softlimit;/* preferred inode limit */ __be64 d_bcount; /* disk blocks owned by the user */ __be64 d_icount; /* inodes owned by the user */ __be32 d_itimer; /* zero if within inode limits if not, this is when we refuse service */ __be32 d_btimer; /* similar to above; for disk blocks */ __be16 d_iwarns; /* warnings issued wrt num inodes */ __be16 d_bwarns; /* warnings issued wrt disk blocks */ __be32 d_pad0; /* 64 bit align */ __be64 d_rtb_hardlimit;/* absolute limit on realtime blks */ __be64 d_rtb_softlimit;/* preferred limit on RT disk blks */ __be64 d_rtbcount; /* realtime blocks owned */ __be32 d_rtbtimer; /* similar to above; for RT disk blocks */ __be16 d_rtbwarns; /* warnings issued wrt RT disk blocks */ __be16 d_pad; } xfs_disk_dquot_t; /* * This is what goes on disk. This is separated from the xfs_disk_dquot because * carrying the unnecessary padding would be a waste of memory. */ typedef struct xfs_dqblk { xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */ char dd_fill[4]; /* filling for posterity */ /* * These two are only present on filesystems with the CRC bits set. */ __be32 dd_crc; /* checksum */ __be64 dd_lsn; /* last modification in log */ uuid_t dd_uuid; /* location information */ } xfs_dqblk_t; #define XFS_DQUOT_CRC_OFF offsetof(struct xfs_dqblk, dd_crc) /* * Remote symlink format and access functions. */ #define XFS_SYMLINK_MAGIC 0x58534c4d /* XSLM */ struct xfs_dsymlink_hdr { __be32 sl_magic; __be32 sl_offset; __be32 sl_bytes; __be32 sl_crc; uuid_t sl_uuid; __be64 sl_owner; __be64 sl_blkno; __be64 sl_lsn; }; #define XFS_SYMLINK_CRC_OFF offsetof(struct xfs_dsymlink_hdr, sl_crc) /* * The maximum pathlen is 1024 bytes. Since the minimum file system * blocksize is 512 bytes, we can get a max of 3 extents back from * bmapi when crc headers are taken into account. */ #define XFS_SYMLINK_MAPS 3 #define XFS_SYMLINK_BUF_SPACE(mp, bufsize) \ ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ sizeof(struct xfs_dsymlink_hdr) : 0)) /* * Allocation Btree format definitions * * There are two on-disk btrees, one sorted by blockno and one sorted * by blockcount and blockno. All blocks look the same to make the code * simpler; if we have time later, we'll make the optimizations. */ #define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */ #define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */ #define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */ #define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */ /* * Data record/key structure */ typedef struct xfs_alloc_rec { __be32 ar_startblock; /* starting block number */ __be32 ar_blockcount; /* count of free blocks */ } xfs_alloc_rec_t, xfs_alloc_key_t; typedef struct xfs_alloc_rec_incore { xfs_agblock_t ar_startblock; /* starting block number */ xfs_extlen_t ar_blockcount; /* count of free blocks */ } xfs_alloc_rec_incore_t; /* btree pointer type */ typedef __be32 xfs_alloc_ptr_t; /* * Block numbers in the AG: * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3. */ #define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1)) #define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1)) /* * Inode Allocation Btree format definitions * * There is a btree for the inode map per allocation group. */ #define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ #define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */ #define XFS_FIBT_MAGIC 0x46494254 /* 'FIBT' */ #define XFS_FIBT_CRC_MAGIC 0x46494233 /* 'FIB3' */ typedef __uint64_t xfs_inofree_t; #define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) #define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3) #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) #define XFS_INOBT_HOLEMASK_FULL 0 /* holemask for full chunk */ #define XFS_INOBT_HOLEMASK_BITS (NBBY * sizeof(__uint16_t)) #define XFS_INODES_PER_HOLEMASK_BIT \ (XFS_INODES_PER_CHUNK / (NBBY * sizeof(__uint16_t))) static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) { return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; } /* * The on-disk inode record structure has two formats. The original "full" * format uses a 4-byte freecount. The "sparse" format uses a 1-byte freecount * and replaces the 3 high-order freecount bytes wth the holemask and inode * count. * * The holemask of the sparse record format allows an inode chunk to have holes * that refer to blocks not owned by the inode record. This facilitates inode * allocation in the event of severe free space fragmentation. */ typedef struct xfs_inobt_rec { __be32 ir_startino; /* starting inode number */ union { struct { __be32 ir_freecount; /* count of free inodes */ } f; struct { __be16 ir_holemask;/* hole mask for sparse chunks */ __u8 ir_count; /* total inode count */ __u8 ir_freecount; /* count of free inodes */ } sp; } ir_u; __be64 ir_free; /* free inode mask */ } xfs_inobt_rec_t; typedef struct xfs_inobt_rec_incore { xfs_agino_t ir_startino; /* starting inode number */ __uint16_t ir_holemask; /* hole mask for sparse chunks */ __uint8_t ir_count; /* total inode count */ __uint8_t ir_freecount; /* count of free inodes (set bits) */ xfs_inofree_t ir_free; /* free inode mask */ } xfs_inobt_rec_incore_t; static inline bool xfs_inobt_issparse(uint16_t holemask) { /* non-zero holemask represents a sparse rec. */ return holemask; } /* * Key structure */ typedef struct xfs_inobt_key { __be32 ir_startino; /* starting inode number */ } xfs_inobt_key_t; /* btree pointer type */ typedef __be32 xfs_inobt_ptr_t; /* * block numbers in the AG. */ #define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) #define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) /* * Reverse mapping btree format definitions * * There is a btree for the reverse map per allocation group */ #define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ /* * Ownership info for an extent. This is used to create reverse-mapping * entries. */ #define XFS_OWNER_INFO_ATTR_FORK (1 << 0) #define XFS_OWNER_INFO_BMBT_BLOCK (1 << 1) struct xfs_owner_info { uint64_t oi_owner; xfs_fileoff_t oi_offset; unsigned int oi_flags; }; /* * Special owner types. * * Seeing as we only support up to 8EB, we have the upper bit of the owner field * to tell us we have a special owner value. We use these for static metadata * allocated at mkfs/growfs time, as well as for freespace management metadata. */ #define XFS_RMAP_OWN_NULL (-1ULL) /* No owner, for growfs */ #define XFS_RMAP_OWN_UNKNOWN (-2ULL) /* Unknown owner, for EFI recovery */ #define XFS_RMAP_OWN_FS (-3ULL) /* static fs metadata */ #define XFS_RMAP_OWN_LOG (-4ULL) /* static fs metadata */ #define XFS_RMAP_OWN_AG (-5ULL) /* AG freespace btree blocks */ #define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */ #define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ #define XFS_RMAP_OWN_REFC (-8ULL) /* refcount tree */ #define XFS_RMAP_OWN_COW (-9ULL) /* cow allocations */ #define XFS_RMAP_OWN_MIN (-10ULL) /* guard */ #define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63))) /* * Data record structure */ struct xfs_rmap_rec { __be32 rm_startblock; /* extent start block */ __be32 rm_blockcount; /* extent length */ __be64 rm_owner; /* extent owner */ __be64 rm_offset; /* offset within the owner */ }; /* * rmap btree record * rm_offset:63 is the attribute fork flag * rm_offset:62 is the bmbt block flag * rm_offset:61 is the unwritten extent flag (same as l0:63 in bmbt) * rm_offset:54-60 aren't used and should be zero * rm_offset:0-53 is the block offset within the inode */ #define XFS_RMAP_OFF_ATTR_FORK ((__uint64_t)1ULL << 63) #define XFS_RMAP_OFF_BMBT_BLOCK ((__uint64_t)1ULL << 62) #define XFS_RMAP_OFF_UNWRITTEN ((__uint64_t)1ULL << 61) #define XFS_RMAP_LEN_MAX ((__uint32_t)~0U) #define XFS_RMAP_OFF_FLAGS (XFS_RMAP_OFF_ATTR_FORK | \ XFS_RMAP_OFF_BMBT_BLOCK | \ XFS_RMAP_OFF_UNWRITTEN) #define XFS_RMAP_OFF_MASK ((__uint64_t)0x3FFFFFFFFFFFFFULL) #define XFS_RMAP_OFF(off) ((off) & XFS_RMAP_OFF_MASK) #define XFS_RMAP_IS_BMBT_BLOCK(off) (!!((off) & XFS_RMAP_OFF_BMBT_BLOCK)) #define XFS_RMAP_IS_ATTR_FORK(off) (!!((off) & XFS_RMAP_OFF_ATTR_FORK)) #define XFS_RMAP_IS_UNWRITTEN(len) (!!((off) & XFS_RMAP_OFF_UNWRITTEN)) #define RMAPBT_STARTBLOCK_BITLEN 32 #define RMAPBT_BLOCKCOUNT_BITLEN 32 #define RMAPBT_OWNER_BITLEN 64 #define RMAPBT_ATTRFLAG_BITLEN 1 #define RMAPBT_BMBTFLAG_BITLEN 1 #define RMAPBT_EXNTFLAG_BITLEN 1 #define RMAPBT_UNUSED_OFFSET_BITLEN 7 #define RMAPBT_OFFSET_BITLEN 54 #define XFS_RMAP_ATTR_FORK (1 << 0) #define XFS_RMAP_BMBT_BLOCK (1 << 1) #define XFS_RMAP_UNWRITTEN (1 << 2) #define XFS_RMAP_KEY_FLAGS (XFS_RMAP_ATTR_FORK | \ XFS_RMAP_BMBT_BLOCK) #define XFS_RMAP_REC_FLAGS (XFS_RMAP_UNWRITTEN) struct xfs_rmap_irec { xfs_agblock_t rm_startblock; /* extent start block */ xfs_extlen_t rm_blockcount; /* extent length */ __uint64_t rm_owner; /* extent owner */ __uint64_t rm_offset; /* offset within the owner */ unsigned int rm_flags; /* state flags */ }; /* * Key structure * * We don't use the length for lookups */ struct xfs_rmap_key { __be32 rm_startblock; /* extent start block */ __be64 rm_owner; /* extent owner */ __be64 rm_offset; /* offset within the owner */ } __attribute__((packed)); /* btree pointer type */ typedef __be32 xfs_rmap_ptr_t; #define XFS_RMAP_BLOCK(mp) \ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ XFS_FIBT_BLOCK(mp) + 1 : \ XFS_IBT_BLOCK(mp) + 1) /* * Reference Count Btree format definitions * */ #define XFS_REFC_CRC_MAGIC 0x52334643 /* 'R3FC' */ unsigned int xfs_refc_block(struct xfs_mount *mp); /* * Data record/key structure * * Each record associates a range of physical blocks (starting at * rc_startblock and ending rc_blockcount blocks later) with a reference * count (rc_refcount). Extents that are being used to stage a copy on * write (CoW) operation are recorded in the refcount btree with a * refcount of 1. All other records must have a refcount > 1 and must * track an extent mapped only by file data forks. * * Extents with a single owner (attributes, metadata, non-shared file * data) are not tracked here. Free space is also not tracked here. * This is consistent with pre-reflink XFS. */ /* * Extents that are being used to stage a copy on write are stored * in the refcount btree with a refcount of 1 and the upper bit set * on the startblock. This speeds up mount time deletion of stale * staging extents because they're all at the right side of the tree. */ #define XFS_REFC_COW_START ((xfs_agblock_t)(1U << 31)) #define REFCNTBT_COWFLAG_BITLEN 1 #define REFCNTBT_AGBLOCK_BITLEN 31 struct xfs_refcount_rec { __be32 rc_startblock; /* starting block number */ __be32 rc_blockcount; /* count of blocks */ __be32 rc_refcount; /* number of inodes linked here */ }; struct xfs_refcount_key { __be32 rc_startblock; /* starting block number */ }; struct xfs_refcount_irec { xfs_agblock_t rc_startblock; /* starting block number */ xfs_extlen_t rc_blockcount; /* count of free blocks */ xfs_nlink_t rc_refcount; /* number of inodes linked here */ }; #define MAXREFCOUNT ((xfs_nlink_t)~0U) #define MAXREFCEXTLEN ((xfs_extlen_t)~0U) /* btree pointer type */ typedef __be32 xfs_refcount_ptr_t; /* * BMAP Btree format definitions * * This includes both the root block definition that sits inside an inode fork * and the record/pointer formats for the leaf/node in the blocks. */ #define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */ #define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */ /* * Bmap root header, on-disk form only. */ typedef struct xfs_bmdr_block { __be16 bb_level; /* 0 is a leaf */ __be16 bb_numrecs; /* current # of data records */ } xfs_bmdr_block_t; /* * Bmap btree record and extent descriptor. * l0:63 is an extent flag (value 1 indicates non-normal). * l0:9-62 are startoff. * l0:0-8 and l1:21-63 are startblock. * l1:0-20 are blockcount. */ #define BMBT_EXNTFLAG_BITLEN 1 #define BMBT_STARTOFF_BITLEN 54 #define BMBT_STARTBLOCK_BITLEN 52 #define BMBT_BLOCKCOUNT_BITLEN 21 typedef struct xfs_bmbt_rec { __be64 l0, l1; } xfs_bmbt_rec_t; typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ typedef xfs_bmbt_rec_t xfs_bmdr_rec_t; typedef struct xfs_bmbt_rec_host { __uint64_t l0, l1; } xfs_bmbt_rec_host_t; /* * Values and macros for delayed-allocation startblock fields. */ #define STARTBLOCKVALBITS 17 #define STARTBLOCKMASKBITS (15 + 20) #define STARTBLOCKMASK \ (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS) static inline int isnullstartblock(xfs_fsblock_t x) { return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK; } static inline xfs_fsblock_t nullstartblock(int k) { ASSERT(k < (1 << STARTBLOCKVALBITS)); return STARTBLOCKMASK | (k); } static inline xfs_filblks_t startblockval(xfs_fsblock_t x) { return (xfs_filblks_t)((x) & ~STARTBLOCKMASK); } /* * Possible extent formats. */ typedef enum { XFS_EXTFMT_NOSTATE = 0, XFS_EXTFMT_HASSTATE } xfs_exntfmt_t; /* * Possible extent states. */ typedef enum { XFS_EXT_NORM, XFS_EXT_UNWRITTEN, XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID } xfs_exntst_t; /* * Incore version of above. */ typedef struct xfs_bmbt_irec { xfs_fileoff_t br_startoff; /* starting file offset */ xfs_fsblock_t br_startblock; /* starting block number */ xfs_filblks_t br_blockcount; /* number of blocks */ xfs_exntst_t br_state; /* extent state */ } xfs_bmbt_irec_t; /* * Key structure for non-leaf levels of the tree. */ typedef struct xfs_bmbt_key { __be64 br_startoff; /* starting file offset */ } xfs_bmbt_key_t, xfs_bmdr_key_t; /* btree pointer type */ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* * Generic Btree block format definitions * * This is a combination of the actual format used on disk for short and long * format btrees. The first three fields are shared by both format, but the * pointers are different and should be used with care. * * To get the size of the actual short or long form headers please use the size * macros below. Never use sizeof(xfs_btree_block). * * The blkno, crc, lsn, owner and uuid fields are only available in filesystems * with the crc feature bit, and all accesses to them must be conditional on * that flag. */ /* short form block header */ struct xfs_btree_block_shdr { __be32 bb_leftsib; __be32 bb_rightsib; __be64 bb_blkno; __be64 bb_lsn; uuid_t bb_uuid; __be32 bb_owner; __le32 bb_crc; }; /* long form block header */ struct xfs_btree_block_lhdr { __be64 bb_leftsib; __be64 bb_rightsib; __be64 bb_blkno; __be64 bb_lsn; uuid_t bb_uuid; __be64 bb_owner; __le32 bb_crc; __be32 bb_pad; /* padding for alignment */ }; struct xfs_btree_block { __be32 bb_magic; /* magic number for block type */ __be16 bb_level; /* 0 is a leaf */ __be16 bb_numrecs; /* current # of data records */ union { struct xfs_btree_block_shdr s; struct xfs_btree_block_lhdr l; } bb_u; /* rest */ }; /* size of a short form block */ #define XFS_BTREE_SBLOCK_LEN \ (offsetof(struct xfs_btree_block, bb_u) + \ offsetof(struct xfs_btree_block_shdr, bb_blkno)) /* size of a long form block */ #define XFS_BTREE_LBLOCK_LEN \ (offsetof(struct xfs_btree_block, bb_u) + \ offsetof(struct xfs_btree_block_lhdr, bb_blkno)) /* sizes of CRC enabled btree blocks */ #define XFS_BTREE_SBLOCK_CRC_LEN \ (offsetof(struct xfs_btree_block, bb_u) + \ sizeof(struct xfs_btree_block_shdr)) #define XFS_BTREE_LBLOCK_CRC_LEN \ (offsetof(struct xfs_btree_block, bb_u) + \ sizeof(struct xfs_btree_block_lhdr)) #define XFS_BTREE_SBLOCK_CRC_OFF \ offsetof(struct xfs_btree_block, bb_u.s.bb_crc) #define XFS_BTREE_LBLOCK_CRC_OFF \ offsetof(struct xfs_btree_block, bb_u.l.bb_crc) /* * On-disk XFS access control list structure. */ struct xfs_acl_entry { __be32 ae_tag; __be32 ae_id; __be16 ae_perm; __be16 ae_pad; /* fill the implicit hole in the structure */ }; struct xfs_acl { __be32 acl_cnt; struct xfs_acl_entry acl_entry[0]; }; /* * The number of ACL entries allowed is defined by the on-disk format. * For v4 superblocks, that is limited to 25 entries. For v5 superblocks, it is * limited only by the maximum size of the xattr that stores the information. */ #define XFS_ACL_MAX_ENTRIES(mp) \ (xfs_sb_version_hascrc(&mp->m_sb) \ ? (XFS_XATTR_SIZE_MAX - sizeof(struct xfs_acl)) / \ sizeof(struct xfs_acl_entry) \ : 25) #define XFS_ACL_SIZE(cnt) \ (sizeof(struct xfs_acl) + \ sizeof(struct xfs_acl_entry) * cnt) #define XFS_ACL_MAX_SIZE(mp) \ XFS_ACL_SIZE(XFS_ACL_MAX_ENTRIES((mp))) /* On-disk XFS extended attribute names */ #define SGI_ACL_FILE "SGI_ACL_FILE" #define SGI_ACL_DEFAULT "SGI_ACL_DEFAULT" #define SGI_ACL_FILE_SIZE (sizeof(SGI_ACL_FILE)-1) #define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1) #endif /* __XFS_FORMAT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_fs.h0000644000000000000000000005455513063067171015440 0ustar /* * Copyright (c) 1995-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_FS_H__ #define __XFS_FS_H__ /* * SGI's XFS filesystem's major stuff (constants, structures) */ /* * Direct I/O attribute record used with XFS_IOC_DIOINFO * d_miniosz is the min xfer size, xfer size multiple and file seek offset * alignment. */ #ifndef HAVE_DIOATTR struct dioattr { __u32 d_mem; /* data buffer memory alignment */ __u32 d_miniosz; /* min xfer size */ __u32 d_maxiosz; /* max xfer size */ }; #endif /* * Flags for the bs_xflags/fsx_xflags field in XFS_IOC_FS[GS]ETXATTR[A] * These are for backwards compatibility only. New code should * use the kernel [4.5 onwards] defined FS_XFLAG_* definitions directly. */ #define XFS_XFLAG_REALTIME FS_XFLAG_REALTIME #define XFS_XFLAG_PREALLOC FS_XFLAG_PREALLOC #define XFS_XFLAG_IMMUTABLE FS_XFLAG_IMMUTABLE #define XFS_XFLAG_APPEND FS_XFLAG_APPEND #define XFS_XFLAG_SYNC FS_XFLAG_SYNC #define XFS_XFLAG_NOATIME FS_XFLAG_NOATIME #define XFS_XFLAG_NODUMP FS_XFLAG_NODUMP #define XFS_XFLAG_RTINHERIT FS_XFLAG_RTINHERIT #define XFS_XFLAG_PROJINHERIT FS_XFLAG_PROJINHERIT #define XFS_XFLAG_NOSYMLINKS FS_XFLAG_NOSYMLINKS #define XFS_XFLAG_EXTSIZE FS_XFLAG_EXTSIZE #define XFS_XFLAG_EXTSZINHERIT FS_XFLAG_EXTSZINHERIT #define XFS_XFLAG_NODEFRAG FS_XFLAG_NODEFRAG #define XFS_XFLAG_FILESTREAM FS_XFLAG_FILESTREAM #define XFS_XFLAG_HASATTR FS_XFLAG_HASATTR #define XFS_IOC_FSGETXATTR FS_IOC_FSGETXATTR #define XFS_IOC_FSSETXATTR FS_IOC_FSSETXATTR /* * Structure for XFS_IOC_GETBMAP. * On input, fill in bmv_offset and bmv_length of the first structure * to indicate the area of interest in the file, and bmv_entries with * the number of array elements given back. The first structure is * updated on return to give the offset and length for the next call. */ #ifndef HAVE_GETBMAP struct getbmap { __s64 bmv_offset; /* file offset of segment in blocks */ __s64 bmv_block; /* starting block (64-bit daddr_t) */ __s64 bmv_length; /* length of segment, blocks */ __s32 bmv_count; /* # of entries in array incl. 1st */ __s32 bmv_entries; /* # of entries filled in (output) */ }; #endif /* * Structure for XFS_IOC_GETBMAPX. Fields bmv_offset through bmv_entries * are used exactly as in the getbmap structure. The getbmapx structure * has additional bmv_iflags and bmv_oflags fields. The bmv_iflags field * is only used for the first structure. It contains input flags * specifying XFS_IOC_GETBMAPX actions. The bmv_oflags field is filled * in by the XFS_IOC_GETBMAPX command for each returned structure after * the first. */ #ifndef HAVE_GETBMAPX struct getbmapx { __s64 bmv_offset; /* file offset of segment in blocks */ __s64 bmv_block; /* starting block (64-bit daddr_t) */ __s64 bmv_length; /* length of segment, blocks */ __s32 bmv_count; /* # of entries in array incl. 1st */ __s32 bmv_entries; /* # of entries filled in (output). */ __s32 bmv_iflags; /* input flags (1st structure) */ __s32 bmv_oflags; /* output flags (after 1st structure)*/ __s32 bmv_unused1; /* future use */ __s32 bmv_unused2; /* future use */ }; #endif /* bmv_iflags values - set by XFS_IOC_GETBMAPX caller. */ #define BMV_IF_ATTRFORK 0x1 /* return attr fork rather than data */ #define BMV_IF_NO_DMAPI_READ 0x2 /* Do not generate DMAPI read event */ #define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */ #define BMV_IF_DELALLOC 0x8 /* rtn status BMV_OF_DELALLOC if req */ #define BMV_IF_NO_HOLES 0x10 /* Do not return holes */ #define BMV_IF_COWFORK 0x20 /* return CoW fork rather than data */ #define BMV_IF_VALID \ (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC| \ BMV_IF_DELALLOC|BMV_IF_NO_HOLES|BMV_IF_COWFORK) /* bmv_oflags values - returned for each non-header segment */ #define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ #define BMV_OF_DELALLOC 0x2 /* segment = delayed allocation */ #define BMV_OF_LAST 0x4 /* segment is the last in the file */ #define BMV_OF_SHARED 0x8 /* segment shared with another file */ /* * Structure for XFS_IOC_FSSETDM. * For use by backup and restore programs to set the XFS on-disk inode * fields di_dmevmask and di_dmstate. These must be set to exactly and * only values previously obtained via xfs_bulkstat! (Specifically the * xfs_bstat_t fields bs_dmevmask and bs_dmstate.) */ #ifndef HAVE_FSDMIDATA struct fsdmidata { __u32 fsd_dmevmask; /* corresponds to di_dmevmask */ __u16 fsd_padding; __u16 fsd_dmstate; /* corresponds to di_dmstate */ }; #endif /* * File segment locking set data type for 64 bit access. * Also used for all the RESV/FREE interfaces. */ typedef struct xfs_flock64 { __s16 l_type; __s16 l_whence; __s64 l_start; __s64 l_len; /* len == 0 means until end of file */ __s32 l_sysid; __u32 l_pid; __s32 l_pad[4]; /* reserve area */ } xfs_flock64_t; /* * Output for XFS_IOC_FSGEOMETRY_V1 */ typedef struct xfs_fsop_geom_v1 { __u32 blocksize; /* filesystem (data) block size */ __u32 rtextsize; /* realtime extent size */ __u32 agblocks; /* fsblocks in an AG */ __u32 agcount; /* number of allocation groups */ __u32 logblocks; /* fsblocks in the log */ __u32 sectsize; /* (data) sector size, bytes */ __u32 inodesize; /* inode size in bytes */ __u32 imaxpct; /* max allowed inode space(%) */ __u64 datablocks; /* fsblocks in data subvolume */ __u64 rtblocks; /* fsblocks in realtime subvol */ __u64 rtextents; /* rt extents in realtime subvol*/ __u64 logstart; /* starting fsblock of the log */ unsigned char uuid[16]; /* unique id of the filesystem */ __u32 sunit; /* stripe unit, fsblocks */ __u32 swidth; /* stripe width, fsblocks */ __s32 version; /* structure version */ __u32 flags; /* superblock version flags */ __u32 logsectsize; /* log sector size, bytes */ __u32 rtsectsize; /* realtime sector size, bytes */ __u32 dirblocksize; /* directory block size, bytes */ } xfs_fsop_geom_v1_t; /* * Output for XFS_IOC_FSGEOMETRY */ typedef struct xfs_fsop_geom { __u32 blocksize; /* filesystem (data) block size */ __u32 rtextsize; /* realtime extent size */ __u32 agblocks; /* fsblocks in an AG */ __u32 agcount; /* number of allocation groups */ __u32 logblocks; /* fsblocks in the log */ __u32 sectsize; /* (data) sector size, bytes */ __u32 inodesize; /* inode size in bytes */ __u32 imaxpct; /* max allowed inode space(%) */ __u64 datablocks; /* fsblocks in data subvolume */ __u64 rtblocks; /* fsblocks in realtime subvol */ __u64 rtextents; /* rt extents in realtime subvol*/ __u64 logstart; /* starting fsblock of the log */ unsigned char uuid[16]; /* unique id of the filesystem */ __u32 sunit; /* stripe unit, fsblocks */ __u32 swidth; /* stripe width, fsblocks */ __s32 version; /* structure version */ __u32 flags; /* superblock version flags */ __u32 logsectsize; /* log sector size, bytes */ __u32 rtsectsize; /* realtime sector size, bytes */ __u32 dirblocksize; /* directory block size, bytes */ __u32 logsunit; /* log stripe unit, bytes */ } xfs_fsop_geom_t; /* Output for XFS_FS_COUNTS */ typedef struct xfs_fsop_counts { __u64 freedata; /* free data section blocks */ __u64 freertx; /* free rt extents */ __u64 freeino; /* free inodes */ __u64 allocino; /* total allocated inodes */ } xfs_fsop_counts_t; /* Input/Output for XFS_GET_RESBLKS and XFS_SET_RESBLKS */ typedef struct xfs_fsop_resblks { __u64 resblks; __u64 resblks_avail; } xfs_fsop_resblks_t; #define XFS_FSOP_GEOM_VERSION 0 #define XFS_FSOP_GEOM_FLAGS_ATTR 0x0001 /* attributes in use */ #define XFS_FSOP_GEOM_FLAGS_NLINK 0x0002 /* 32-bit nlink values */ #define XFS_FSOP_GEOM_FLAGS_QUOTA 0x0004 /* quotas enabled */ #define XFS_FSOP_GEOM_FLAGS_IALIGN 0x0008 /* inode alignment */ #define XFS_FSOP_GEOM_FLAGS_DALIGN 0x0010 /* large data alignment */ #define XFS_FSOP_GEOM_FLAGS_SHARED 0x0020 /* read-only shared */ #define XFS_FSOP_GEOM_FLAGS_EXTFLG 0x0040 /* special extent flag */ #define XFS_FSOP_GEOM_FLAGS_DIRV2 0x0080 /* directory version 2 */ #define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ #define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ #define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ #define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */ #define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ #define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ #define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */ #define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */ #define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */ /* * Minimum and maximum sizes need for growth checks. * * Block counts are in units of filesystem blocks, not basic blocks. */ #define XFS_MIN_AG_BLOCKS 64 #define XFS_MIN_LOG_BLOCKS 512ULL #define XFS_MAX_LOG_BLOCKS (1024 * 1024ULL) #define XFS_MIN_LOG_BYTES (10 * 1024 * 1024ULL) /* keep the maximum size under 2^31 by a small amount */ #define XFS_MAX_LOG_BYTES \ ((2 * 1024 * 1024 * 1024ULL) - XFS_MIN_LOG_BYTES) /* Used for sanity checks on superblock */ #define XFS_MAX_DBLOCKS(s) ((xfs_rfsblock_t)(s)->sb_agcount * (s)->sb_agblocks) #define XFS_MIN_DBLOCKS(s) ((xfs_rfsblock_t)((s)->sb_agcount - 1) * \ (s)->sb_agblocks + XFS_MIN_AG_BLOCKS) /* * Structures for XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG & XFS_IOC_FSGROWFSRT */ typedef struct xfs_growfs_data { __u64 newblocks; /* new data subvol size, fsblocks */ __u32 imaxpct; /* new inode space percentage limit */ } xfs_growfs_data_t; typedef struct xfs_growfs_log { __u32 newblocks; /* new log size, fsblocks */ __u32 isint; /* 1 if new log is internal */ } xfs_growfs_log_t; typedef struct xfs_growfs_rt { __u64 newblocks; /* new realtime size, fsblocks */ __u32 extsize; /* new realtime extent size, fsblocks */ } xfs_growfs_rt_t; /* * Structures returned from ioctl XFS_IOC_FSBULKSTAT & XFS_IOC_FSBULKSTAT_SINGLE */ typedef struct xfs_bstime { time_t tv_sec; /* seconds */ __s32 tv_nsec; /* and nanoseconds */ } xfs_bstime_t; typedef struct xfs_bstat { __u64 bs_ino; /* inode number */ __u16 bs_mode; /* type and mode */ __u16 bs_nlink; /* number of links */ __u32 bs_uid; /* user id */ __u32 bs_gid; /* group id */ __u32 bs_rdev; /* device value */ __s32 bs_blksize; /* block size */ __s64 bs_size; /* file size */ xfs_bstime_t bs_atime; /* access time */ xfs_bstime_t bs_mtime; /* modify time */ xfs_bstime_t bs_ctime; /* inode change time */ int64_t bs_blocks; /* number of blocks */ __u32 bs_xflags; /* extended flags */ __s32 bs_extsize; /* extent size */ __s32 bs_extents; /* number of extents */ __u32 bs_gen; /* generation count */ __u16 bs_projid_lo; /* lower part of project id */ #define bs_projid bs_projid_lo /* (previously just bs_projid) */ __u16 bs_forkoff; /* inode fork offset in bytes */ __u16 bs_projid_hi; /* higher part of project id */ unsigned char bs_pad[6]; /* pad space, unused */ __u32 bs_cowextsize; /* cow extent size */ __u32 bs_dmevmask; /* DMIG event mask */ __u16 bs_dmstate; /* DMIG state info */ __u16 bs_aextents; /* attribute number of extents */ } xfs_bstat_t; /* * Project quota id helpers (previously projid was 16bit only * and using two 16bit values to hold new 32bit projid was choosen * to retain compatibility with "old" filesystems). */ static inline __uint32_t bstat_get_projid(struct xfs_bstat *bs) { return (__uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo; } /* * The user-level BulkStat Request interface structure. */ typedef struct xfs_fsop_bulkreq { __u64 __user *lastip; /* last inode # pointer */ __s32 icount; /* count of entries in buffer */ void __user *ubuffer;/* user buffer for inode desc. */ __s32 __user *ocount; /* output count pointer */ } xfs_fsop_bulkreq_t; /* * Structures returned from xfs_inumbers routine (XFS_IOC_FSINUMBERS). */ typedef struct xfs_inogrp { __u64 xi_startino; /* starting inode number */ __s32 xi_alloccount; /* # bits set in allocmask */ __u64 xi_allocmask; /* mask of allocated inodes */ } xfs_inogrp_t; /* * Error injection. */ typedef struct xfs_error_injection { __s32 fd; __s32 errtag; } xfs_error_injection_t; /* * Speculative preallocation trimming. */ #define XFS_EOFBLOCKS_VERSION 1 struct xfs_fs_eofblocks { __u32 eof_version; __u32 eof_flags; uid_t eof_uid; gid_t eof_gid; prid_t eof_prid; __u32 pad32; __u64 eof_min_file_size; __u64 pad64[12]; }; /* eof_flags values */ #define XFS_EOF_FLAGS_SYNC (1 << 0) /* sync/wait mode scan */ #define XFS_EOF_FLAGS_UID (1 << 1) /* filter by uid */ #define XFS_EOF_FLAGS_GID (1 << 2) /* filter by gid */ #define XFS_EOF_FLAGS_PRID (1 << 3) /* filter by project id */ #define XFS_EOF_FLAGS_MINFILESIZE (1 << 4) /* filter by min file size */ #define XFS_EOF_FLAGS_UNION (1 << 5) /* union filter algorithm; * kernel only, not included in * valid mask */ #define XFS_EOF_FLAGS_VALID \ (XFS_EOF_FLAGS_SYNC | \ XFS_EOF_FLAGS_UID | \ XFS_EOF_FLAGS_GID | \ XFS_EOF_FLAGS_PRID | \ XFS_EOF_FLAGS_MINFILESIZE) /* * The user-level Handle Request interface structure. */ typedef struct xfs_fsop_handlereq { __u32 fd; /* fd for FD_TO_HANDLE */ void __user *path; /* user pathname */ __u32 oflags; /* open flags */ void __user *ihandle;/* user supplied handle */ __u32 ihandlen; /* user supplied length */ void __user *ohandle;/* user buffer for handle */ __u32 __user *ohandlen;/* user buffer length */ } xfs_fsop_handlereq_t; /* * Compound structures for passing args through Handle Request interfaces * xfs_fssetdm_by_handle, xfs_attrlist_by_handle, xfs_attrmulti_by_handle * - ioctls: XFS_IOC_FSSETDM_BY_HANDLE, XFS_IOC_ATTRLIST_BY_HANDLE, and * XFS_IOC_ATTRMULTI_BY_HANDLE */ typedef struct xfs_fsop_setdm_handlereq { struct xfs_fsop_handlereq hreq; /* handle information */ struct fsdmidata __user *data; /* DMAPI data */ } xfs_fsop_setdm_handlereq_t; typedef struct xfs_attrlist_cursor { __u32 opaque[4]; } xfs_attrlist_cursor_t; typedef struct xfs_fsop_attrlist_handlereq { struct xfs_fsop_handlereq hreq; /* handle interface structure */ struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */ __u32 flags; /* which namespace to use */ __u32 buflen; /* length of buffer supplied */ void __user *buffer; /* returned names */ } xfs_fsop_attrlist_handlereq_t; typedef struct xfs_attr_multiop { __u32 am_opcode; #define ATTR_OP_GET 1 /* return the indicated attr's value */ #define ATTR_OP_SET 2 /* set/create the indicated attr/value pair */ #define ATTR_OP_REMOVE 3 /* remove the indicated attr */ __s32 am_error; void __user *am_attrname; void __user *am_attrvalue; __u32 am_length; __u32 am_flags; } xfs_attr_multiop_t; typedef struct xfs_fsop_attrmulti_handlereq { struct xfs_fsop_handlereq hreq; /* handle interface structure */ __u32 opcount;/* count of following multiop */ struct xfs_attr_multiop __user *ops; /* attr_multi data */ } xfs_fsop_attrmulti_handlereq_t; /* * per machine unique filesystem identifier types. */ typedef struct { __u32 val[2]; } xfs_fsid_t; /* file system id type */ typedef struct xfs_fid { __u16 fid_len; /* length of remainder */ __u16 fid_pad; __u32 fid_gen; /* generation number */ __u64 fid_ino; /* 64 bits inode number */ } xfs_fid_t; typedef struct xfs_handle { union { __s64 align; /* force alignment of ha_fid */ xfs_fsid_t _ha_fsid; /* unique file system identifier */ } ha_u; xfs_fid_t ha_fid; /* file system specific file ID */ } xfs_handle_t; #define ha_fsid ha_u._ha_fsid #define XFS_HSIZE(handle) (((char *) &(handle).ha_fid.fid_pad \ - (char *) &(handle)) \ + (handle).ha_fid.fid_len) /* * Structure passed to XFS_IOC_SWAPEXT */ typedef struct xfs_swapext { __int64_t sx_version; /* version */ #define XFS_SX_VERSION 0 __int64_t sx_fdtarget; /* fd of target file */ __int64_t sx_fdtmp; /* fd of tmp file */ xfs_off_t sx_offset; /* offset into file */ xfs_off_t sx_length; /* leng from offset */ char sx_pad[16]; /* pad space, unused */ xfs_bstat_t sx_stat; /* stat of target b4 copy */ } xfs_swapext_t; /* * Flags for going down operation */ #define XFS_FSOP_GOING_FLAGS_DEFAULT 0x0 /* going down */ #define XFS_FSOP_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */ #define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */ /* * ioctl limits */ #ifdef XATTR_LIST_MAX # define XFS_XATTR_LIST_MAX XATTR_LIST_MAX #else # define XFS_XATTR_LIST_MAX 65536 #endif /* * ioctl commands that are used by Linux filesystems */ #define XFS_IOC_GETXFLAGS FS_IOC_GETFLAGS #define XFS_IOC_SETXFLAGS FS_IOC_SETFLAGS #define XFS_IOC_GETVERSION FS_IOC_GETVERSION /* * ioctl commands that replace IRIX fcntl()'s * For 'documentation' purposed more than anything else, * the "cmd #" field reflects the IRIX fcntl number. */ #define XFS_IOC_ALLOCSP _IOW ('X', 10, struct xfs_flock64) #define XFS_IOC_FREESP _IOW ('X', 11, struct xfs_flock64) #define XFS_IOC_DIOINFO _IOR ('X', 30, struct dioattr) #define XFS_IOC_ALLOCSP64 _IOW ('X', 36, struct xfs_flock64) #define XFS_IOC_FREESP64 _IOW ('X', 37, struct xfs_flock64) #define XFS_IOC_GETBMAP _IOWR('X', 38, struct getbmap) #define XFS_IOC_FSSETDM _IOW ('X', 39, struct fsdmidata) #define XFS_IOC_RESVSP _IOW ('X', 40, struct xfs_flock64) #define XFS_IOC_UNRESVSP _IOW ('X', 41, struct xfs_flock64) #define XFS_IOC_RESVSP64 _IOW ('X', 42, struct xfs_flock64) #define XFS_IOC_UNRESVSP64 _IOW ('X', 43, struct xfs_flock64) #define XFS_IOC_GETBMAPA _IOWR('X', 44, struct getbmap) #define XFS_IOC_FSGETXATTRA _IOR ('X', 45, struct fsxattr) /* XFS_IOC_SETBIOSIZE ---- deprecated 46 */ /* XFS_IOC_GETBIOSIZE ---- deprecated 47 */ #define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap) #define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64) #define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks) /* * ioctl commands that replace IRIX syssgi()'s */ #define XFS_IOC_FSGEOMETRY_V1 _IOR ('X', 100, struct xfs_fsop_geom_v1) #define XFS_IOC_FSBULKSTAT _IOWR('X', 101, struct xfs_fsop_bulkreq) #define XFS_IOC_FSBULKSTAT_SINGLE _IOWR('X', 102, struct xfs_fsop_bulkreq) #define XFS_IOC_FSINUMBERS _IOWR('X', 103, struct xfs_fsop_bulkreq) #define XFS_IOC_PATH_TO_FSHANDLE _IOWR('X', 104, struct xfs_fsop_handlereq) #define XFS_IOC_PATH_TO_HANDLE _IOWR('X', 105, struct xfs_fsop_handlereq) #define XFS_IOC_FD_TO_HANDLE _IOWR('X', 106, struct xfs_fsop_handlereq) #define XFS_IOC_OPEN_BY_HANDLE _IOWR('X', 107, struct xfs_fsop_handlereq) #define XFS_IOC_READLINK_BY_HANDLE _IOWR('X', 108, struct xfs_fsop_handlereq) #define XFS_IOC_SWAPEXT _IOWR('X', 109, struct xfs_swapext) #define XFS_IOC_FSGROWFSDATA _IOW ('X', 110, struct xfs_growfs_data) #define XFS_IOC_FSGROWFSLOG _IOW ('X', 111, struct xfs_growfs_log) #define XFS_IOC_FSGROWFSRT _IOW ('X', 112, struct xfs_growfs_rt) #define XFS_IOC_FSCOUNTS _IOR ('X', 113, struct xfs_fsop_counts) #define XFS_IOC_SET_RESBLKS _IOWR('X', 114, struct xfs_fsop_resblks) #define XFS_IOC_GET_RESBLKS _IOR ('X', 115, struct xfs_fsop_resblks) #define XFS_IOC_ERROR_INJECTION _IOW ('X', 116, struct xfs_error_injection) #define XFS_IOC_ERROR_CLEARALL _IOW ('X', 117, struct xfs_error_injection) /* XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 118 */ #define XFS_IOC_FREEZE _IOWR('X', 119, int) /* aka FIFREEZE */ #define XFS_IOC_THAW _IOWR('X', 120, int) /* aka FITHAW */ #define XFS_IOC_FSSETDM_BY_HANDLE _IOW ('X', 121, struct xfs_fsop_setdm_handlereq) #define XFS_IOC_ATTRLIST_BY_HANDLE _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq) #define XFS_IOC_ATTRMULTI_BY_HANDLE _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq) #define XFS_IOC_FSGEOMETRY _IOR ('X', 124, struct xfs_fsop_geom) #define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t) /* XFS_IOC_GETFSUUID ---------- deprecated 140 */ /* reflink ioctls; these MUST match the btrfs ioctl definitions */ /* from struct btrfs_ioctl_clone_range_args */ struct xfs_clone_args { __s64 src_fd; __u64 src_offset; __u64 src_length; __u64 dest_offset; }; /* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */ #define XFS_EXTENT_DATA_SAME 0 #define XFS_EXTENT_DATA_DIFFERS 1 /* from struct btrfs_ioctl_file_extent_same_info */ struct xfs_extent_data_info { __s64 fd; /* in - destination file */ __u64 logical_offset; /* in - start of extent in destination */ __u64 bytes_deduped; /* out - total # of bytes we were able * to dedupe from this file */ /* status of this dedupe operation: * < 0 for error * == XFS_EXTENT_DATA_SAME if dedupe succeeds * == XFS_EXTENT_DATA_DIFFERS if data differs */ __s32 status; /* out - see above description */ __u32 reserved; }; /* from struct btrfs_ioctl_file_extent_same_args */ struct xfs_extent_data { __u64 logical_offset; /* in - start of extent in source */ __u64 length; /* in - length of extent */ __u16 dest_count; /* in - total elements in info array */ __u16 reserved1; __u32 reserved2; struct xfs_extent_data_info info[0]; }; #define XFS_IOC_CLONE _IOW (0x94, 9, int) #define XFS_IOC_CLONE_RANGE _IOW (0x94, 13, struct xfs_clone_args) #define XFS_IOC_FILE_EXTENT_SAME _IOWR(0x94, 54, struct xfs_extent_data) #ifndef HAVE_BBMACROS /* * Block I/O parameterization. A basic block (BB) is the lowest size of * filesystem allocation, and must equal 512. Length units given to bio * routines are in BB's. */ #define BBSHIFT 9 #define BBSIZE (1<> BBSHIFT) #define BTOBBT(bytes) ((__u64)(bytes) >> BBSHIFT) #define BBTOB(bbs) ((bbs) << BBSHIFT) #endif #endif /* __XFS_FS_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_ialloc.c0000644000000000000000000021732613063067170016262 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_ialloc.h" #include "xfs_ialloc_btree.h" #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_trace.h" #include "xfs_rmap.h" /* * Allocation group level functions. */ static inline int xfs_ialloc_cluster_alignment( struct xfs_mount *mp) { if (xfs_sb_version_hasalign(&mp->m_sb) && mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) return mp->m_sb.sb_inoalignmt; return 1; } /* * Lookup a record by ino in the btree given by cur. */ int /* error */ xfs_inobt_lookup( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agino_t ino, /* starting inode of chunk */ xfs_lookup_t dir, /* <=, >=, == */ int *stat) /* success/failure */ { cur->bc_rec.i.ir_startino = ino; cur->bc_rec.i.ir_holemask = 0; cur->bc_rec.i.ir_count = 0; cur->bc_rec.i.ir_freecount = 0; cur->bc_rec.i.ir_free = 0; return xfs_btree_lookup(cur, dir, stat); } /* * Update the record referred to by cur to the value given. * This either works (return 0) or gets an EFSCORRUPTED error. */ STATIC int /* error */ xfs_inobt_update( struct xfs_btree_cur *cur, /* btree cursor */ xfs_inobt_rec_incore_t *irec) /* btree record */ { union xfs_btree_rec rec; rec.inobt.ir_startino = cpu_to_be32(irec->ir_startino); if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) { rec.inobt.ir_u.sp.ir_holemask = cpu_to_be16(irec->ir_holemask); rec.inobt.ir_u.sp.ir_count = irec->ir_count; rec.inobt.ir_u.sp.ir_freecount = irec->ir_freecount; } else { /* ir_holemask/ir_count not supported on-disk */ rec.inobt.ir_u.f.ir_freecount = cpu_to_be32(irec->ir_freecount); } rec.inobt.ir_free = cpu_to_be64(irec->ir_free); return xfs_btree_update(cur, &rec); } /* * Get the data from the pointed-to record. */ int /* error */ xfs_inobt_get_rec( struct xfs_btree_cur *cur, /* btree cursor */ xfs_inobt_rec_incore_t *irec, /* btree record */ int *stat) /* output: success/failure */ { union xfs_btree_rec *rec; int error; error = xfs_btree_get_rec(cur, &rec, stat); if (error || *stat == 0) return error; irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino); if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) { irec->ir_holemask = be16_to_cpu(rec->inobt.ir_u.sp.ir_holemask); irec->ir_count = rec->inobt.ir_u.sp.ir_count; irec->ir_freecount = rec->inobt.ir_u.sp.ir_freecount; } else { /* * ir_holemask/ir_count not supported on-disk. Fill in hardcoded * values for full inode chunks. */ irec->ir_holemask = XFS_INOBT_HOLEMASK_FULL; irec->ir_count = XFS_INODES_PER_CHUNK; irec->ir_freecount = be32_to_cpu(rec->inobt.ir_u.f.ir_freecount); } irec->ir_free = be64_to_cpu(rec->inobt.ir_free); return 0; } /* * Insert a single inobt record. Cursor must already point to desired location. */ STATIC int xfs_inobt_insert_rec( struct xfs_btree_cur *cur, __uint16_t holemask, __uint8_t count, __int32_t freecount, xfs_inofree_t free, int *stat) { cur->bc_rec.i.ir_holemask = holemask; cur->bc_rec.i.ir_count = count; cur->bc_rec.i.ir_freecount = freecount; cur->bc_rec.i.ir_free = free; return xfs_btree_insert(cur, stat); } /* * Insert records describing a newly allocated inode chunk into the inobt. */ STATIC int xfs_inobt_insert( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agino_t newino, xfs_agino_t newlen, xfs_btnum_t btnum) { struct xfs_btree_cur *cur; struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); xfs_agino_t thisino; int i; int error; cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, btnum); for (thisino = newino; thisino < newino + newlen; thisino += XFS_INODES_PER_CHUNK) { error = xfs_inobt_lookup(cur, thisino, XFS_LOOKUP_EQ, &i); if (error) { xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } ASSERT(i == 0); error = xfs_inobt_insert_rec(cur, XFS_INOBT_HOLEMASK_FULL, XFS_INODES_PER_CHUNK, XFS_INODES_PER_CHUNK, XFS_INOBT_ALL_FREE, &i); if (error) { xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } ASSERT(i == 1); } xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; } /* * Verify that the number of free inodes in the AGI is correct. */ #ifdef DEBUG STATIC int xfs_check_agi_freecount( struct xfs_btree_cur *cur, struct xfs_agi *agi) { if (cur->bc_nlevels == 1) { xfs_inobt_rec_incore_t rec; int freecount = 0; int error; int i; error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); if (error) return error; do { error = xfs_inobt_get_rec(cur, &rec, &i); if (error) return error; if (i) { freecount += rec.ir_freecount; error = xfs_btree_increment(cur, 0, &i); if (error) return error; } } while (i == 1); if (!XFS_FORCED_SHUTDOWN(cur->bc_mp)) ASSERT(freecount == be32_to_cpu(agi->agi_freecount)); } return 0; } #else #define xfs_check_agi_freecount(cur, agi) 0 #endif /* * Initialise a new set of inodes. When called without a transaction context * (e.g. from recovery) we initiate a delayed write of the inode buffers rather * than logging them (which in a transaction context puts them into the AIL * for writeback rather than the xfsbufd queue). */ int xfs_ialloc_inode_init( struct xfs_mount *mp, struct xfs_trans *tp, struct list_head *buffer_list, int icount, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_agblock_t length, unsigned int gen) { struct xfs_buf *fbuf; struct xfs_dinode *free; int nbufs, blks_per_cluster, inodes_per_cluster; int version; int i, j; xfs_daddr_t d; xfs_ino_t ino = 0; /* * Loop over the new block(s), filling in the inodes. For small block * sizes, manipulate the inodes in buffers which are multiples of the * blocks size. */ blks_per_cluster = xfs_icluster_size_fsb(mp); inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog; nbufs = length / blks_per_cluster; /* * Figure out what version number to use in the inodes we create. If * the superblock version has caught up to the one that supports the new * inode format, then use the new inode version. Otherwise use the old * version so that old kernels will continue to be able to use the file * system. * * For v3 inodes, we also need to write the inode number into the inode, * so calculate the first inode number of the chunk here as * XFS_OFFBNO_TO_AGINO() only works within a filesystem block, not * across multiple filesystem blocks (such as a cluster) and so cannot * be used in the cluster buffer loop below. * * Further, because we are writing the inode directly into the buffer * and calculating a CRC on the entire inode, we have ot log the entire * inode so that the entire range the CRC covers is present in the log. * That means for v3 inode we log the entire buffer rather than just the * inode cores. */ if (xfs_sb_version_hascrc(&mp->m_sb)) { version = 3; ino = XFS_AGINO_TO_INO(mp, agno, XFS_OFFBNO_TO_AGINO(mp, agbno, 0)); /* * log the initialisation that is about to take place as an * logical operation. This means the transaction does not * need to log the physical changes to the inode buffers as log * recovery will know what initialisation is actually needed. * Hence we only need to log the buffers as "ordered" buffers so * they track in the AIL as if they were physically logged. */ if (tp) xfs_icreate_log(tp, agno, agbno, icount, mp->m_sb.sb_inodesize, length, gen); } else version = 2; for (j = 0; j < nbufs; j++) { /* * Get the block. */ d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster)); fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize * blks_per_cluster, XBF_UNMAPPED); if (!fbuf) return -ENOMEM; /* Initialize the inode buffers and log them appropriately. */ fbuf->b_ops = &xfs_inode_buf_ops; xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length)); for (i = 0; i < inodes_per_cluster; i++) { int ioffset = i << mp->m_sb.sb_inodelog; uint isize = xfs_dinode_size(version); free = xfs_make_iptr(mp, fbuf, i); free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); free->di_version = version; free->di_gen = cpu_to_be32(gen); free->di_next_unlinked = cpu_to_be32(NULLAGINO); if (version == 3) { free->di_ino = cpu_to_be64(ino); ino++; uuid_copy(&free->di_uuid, &mp->m_sb.sb_meta_uuid); xfs_dinode_calc_crc(mp, free); } else if (tp) { /* just log the inode core */ xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1); } } if (tp) { /* * Mark the buffer as an inode allocation buffer so it * sticks in AIL at the point of this allocation * transaction. This ensures the they are on disk before * the tail of the log can be moved past this * transaction (i.e. by preventing relogging from moving * it forward in the log). */ xfs_trans_inode_alloc_buf(tp, fbuf); if (version == 3) { /* * Mark the buffer as ordered so that they are * not physically logged in the transaction but * still tracked in the AIL as part of the * transaction and pin the log appropriately. */ xfs_trans_ordered_buf(tp, fbuf); xfs_trans_log_buf(tp, fbuf, 0, BBTOB(fbuf->b_length) - 1); } } else { fbuf->b_flags |= XBF_DONE; xfs_buf_delwri_queue(fbuf, buffer_list); xfs_buf_relse(fbuf); } } return 0; } /* * Align startino and allocmask for a recently allocated sparse chunk such that * they are fit for insertion (or merge) into the on-disk inode btrees. * * Background: * * When enabled, sparse inode support increases the inode alignment from cluster * size to inode chunk size. This means that the minimum range between two * non-adjacent inode records in the inobt is large enough for a full inode * record. This allows for cluster sized, cluster aligned block allocation * without need to worry about whether the resulting inode record overlaps with * another record in the tree. Without this basic rule, we would have to deal * with the consequences of overlap by potentially undoing recent allocations in * the inode allocation codepath. * * Because of this alignment rule (which is enforced on mount), there are two * inobt possibilities for newly allocated sparse chunks. One is that the * aligned inode record for the chunk covers a range of inodes not already * covered in the inobt (i.e., it is safe to insert a new sparse record). The * other is that a record already exists at the aligned startino that considers * the newly allocated range as sparse. In the latter case, record content is * merged in hope that sparse inode chunks fill to full chunks over time. */ STATIC void xfs_align_sparse_ino( struct xfs_mount *mp, xfs_agino_t *startino, uint16_t *allocmask) { xfs_agblock_t agbno; xfs_agblock_t mod; int offset; agbno = XFS_AGINO_TO_AGBNO(mp, *startino); mod = agbno % mp->m_sb.sb_inoalignmt; if (!mod) return; /* calculate the inode offset and align startino */ offset = mod << mp->m_sb.sb_inopblog; *startino -= offset; /* * Since startino has been aligned down, left shift allocmask such that * it continues to represent the same physical inodes relative to the * new startino. */ *allocmask <<= offset / XFS_INODES_PER_HOLEMASK_BIT; } /* * Determine whether the source inode record can merge into the target. Both * records must be sparse, the inode ranges must match and there must be no * allocation overlap between the records. */ STATIC bool __xfs_inobt_can_merge( struct xfs_inobt_rec_incore *trec, /* tgt record */ struct xfs_inobt_rec_incore *srec) /* src record */ { uint64_t talloc; uint64_t salloc; /* records must cover the same inode range */ if (trec->ir_startino != srec->ir_startino) return false; /* both records must be sparse */ if (!xfs_inobt_issparse(trec->ir_holemask) || !xfs_inobt_issparse(srec->ir_holemask)) return false; /* both records must track some inodes */ if (!trec->ir_count || !srec->ir_count) return false; /* can't exceed capacity of a full record */ if (trec->ir_count + srec->ir_count > XFS_INODES_PER_CHUNK) return false; /* verify there is no allocation overlap */ talloc = xfs_inobt_irec_to_allocmask(trec); salloc = xfs_inobt_irec_to_allocmask(srec); if (talloc & salloc) return false; return true; } /* * Merge the source inode record into the target. The caller must call * __xfs_inobt_can_merge() to ensure the merge is valid. */ STATIC void __xfs_inobt_rec_merge( struct xfs_inobt_rec_incore *trec, /* target */ struct xfs_inobt_rec_incore *srec) /* src */ { ASSERT(trec->ir_startino == srec->ir_startino); /* combine the counts */ trec->ir_count += srec->ir_count; trec->ir_freecount += srec->ir_freecount; /* * Merge the holemask and free mask. For both fields, 0 bits refer to * allocated inodes. We combine the allocated ranges with bitwise AND. */ trec->ir_holemask &= srec->ir_holemask; trec->ir_free &= srec->ir_free; } /* * Insert a new sparse inode chunk into the associated inode btree. The inode * record for the sparse chunk is pre-aligned to a startino that should match * any pre-existing sparse inode record in the tree. This allows sparse chunks * to fill over time. * * This function supports two modes of handling preexisting records depending on * the merge flag. If merge is true, the provided record is merged with the * existing record and updated in place. The merged record is returned in nrec. * If merge is false, an existing record is replaced with the provided record. * If no preexisting record exists, the provided record is always inserted. * * It is considered corruption if a merge is requested and not possible. Given * the sparse inode alignment constraints, this should never happen. */ STATIC int xfs_inobt_insert_sprec( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *agbp, int btnum, struct xfs_inobt_rec_incore *nrec, /* in/out: new/merged rec. */ bool merge) /* merge or replace */ { struct xfs_btree_cur *cur; struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); int error; int i; struct xfs_inobt_rec_incore rec; cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, btnum); /* the new record is pre-aligned so we know where to look */ error = xfs_inobt_lookup(cur, nrec->ir_startino, XFS_LOOKUP_EQ, &i); if (error) goto error; /* if nothing there, insert a new record and return */ if (i == 0) { error = xfs_inobt_insert_rec(cur, nrec->ir_holemask, nrec->ir_count, nrec->ir_freecount, nrec->ir_free, &i); if (error) goto error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error); goto out; } /* * A record exists at this startino. Merge or replace the record * depending on what we've been asked to do. */ if (merge) { error = xfs_inobt_get_rec(cur, &rec, &i); if (error) goto error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error); XFS_WANT_CORRUPTED_GOTO(mp, rec.ir_startino == nrec->ir_startino, error); /* * This should never fail. If we have coexisting records that * cannot merge, something is seriously wrong. */ XFS_WANT_CORRUPTED_GOTO(mp, __xfs_inobt_can_merge(nrec, &rec), error); trace_xfs_irec_merge_pre(mp, agno, rec.ir_startino, rec.ir_holemask, nrec->ir_startino, nrec->ir_holemask); /* merge to nrec to output the updated record */ __xfs_inobt_rec_merge(nrec, &rec); trace_xfs_irec_merge_post(mp, agno, nrec->ir_startino, nrec->ir_holemask); error = xfs_inobt_rec_check_count(mp, nrec); if (error) goto error; } error = xfs_inobt_update(cur, nrec); if (error) goto error; out: xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; error: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } /* * Allocate new inodes in the allocation group specified by agbp. * Return 0 for success, else error code. */ STATIC int /* error code or 0 */ xfs_ialloc_ag_alloc( xfs_trans_t *tp, /* transaction pointer */ xfs_buf_t *agbp, /* alloc group buffer */ int *alloc) { xfs_agi_t *agi; /* allocation group header */ xfs_alloc_arg_t args; /* allocation argument structure */ xfs_agnumber_t agno; int error; xfs_agino_t newino; /* new first inode's number */ xfs_agino_t newlen; /* new number of inodes */ int isaligned = 0; /* inode allocation at stripe unit */ /* boundary */ uint16_t allocmask = (uint16_t) -1; /* init. to full chunk */ struct xfs_inobt_rec_incore rec; struct xfs_perag *pag; int do_sparse = 0; memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = tp->t_mountp; args.fsbno = NULLFSBLOCK; xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INODES); #ifdef DEBUG /* randomly do sparse inode allocations */ if (xfs_sb_version_hassparseinodes(&tp->t_mountp->m_sb) && args.mp->m_ialloc_min_blks < args.mp->m_ialloc_blks) do_sparse = prandom_u32() & 1; #endif /* * Locking will ensure that we don't have two callers in here * at one time. */ newlen = args.mp->m_ialloc_inos; if (args.mp->m_maxicount && percpu_counter_read_positive(&args.mp->m_icount) + newlen > args.mp->m_maxicount) return -ENOSPC; args.minlen = args.maxlen = args.mp->m_ialloc_blks; /* * First try to allocate inodes contiguous with the last-allocated * chunk of inodes. If the filesystem is striped, this will fill * an entire stripe unit with inodes. */ agi = XFS_BUF_TO_AGI(agbp); newino = be32_to_cpu(agi->agi_newino); agno = be32_to_cpu(agi->agi_seqno); args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) + args.mp->m_ialloc_blks; if (do_sparse) goto sparse_alloc; if (likely(newino != NULLAGINO && (args.agbno < be32_to_cpu(agi->agi_length)))) { args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); args.type = XFS_ALLOCTYPE_THIS_BNO; args.prod = 1; /* * We need to take into account alignment here to ensure that * we don't modify the free list if we fail to have an exact * block. If we don't have an exact match, and every oher * attempt allocation attempt fails, we'll end up cancelling * a dirty transaction and shutting down. * * For an exact allocation, alignment must be 1, * however we need to take cluster alignment into account when * fixing up the freelist. Use the minalignslop field to * indicate that extra blocks might be required for alignment, * but not to use them in the actual exact allocation. */ args.alignment = 1; args.minalignslop = xfs_ialloc_cluster_alignment(args.mp) - 1; /* Allow space for the inode btree to split. */ args.minleft = args.mp->m_in_maxlevels - 1; if ((error = xfs_alloc_vextent(&args))) return error; /* * This request might have dirtied the transaction if the AG can * satisfy the request, but the exact block was not available. * If the allocation did fail, subsequent requests will relax * the exact agbno requirement and increase the alignment * instead. It is critical that the total size of the request * (len + alignment + slop) does not increase from this point * on, so reset minalignslop to ensure it is not included in * subsequent requests. */ args.minalignslop = 0; } if (unlikely(args.fsbno == NULLFSBLOCK)) { /* * Set the alignment for the allocation. * If stripe alignment is turned on then align at stripe unit * boundary. * If the cluster size is smaller than a filesystem block * then we're doing I/O for inodes in filesystem block size * pieces, so don't need alignment anyway. */ isaligned = 0; if (args.mp->m_sinoalign) { ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN)); args.alignment = args.mp->m_dalign; isaligned = 1; } else args.alignment = xfs_ialloc_cluster_alignment(args.mp); /* * Need to figure out where to allocate the inode blocks. * Ideally they should be spaced out through the a.g. * For now, just allocate blocks up front. */ args.agbno = be32_to_cpu(agi->agi_root); args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); /* * Allocate a fixed-size extent of inodes. */ args.type = XFS_ALLOCTYPE_NEAR_BNO; args.prod = 1; /* * Allow space for the inode btree to split. */ args.minleft = args.mp->m_in_maxlevels - 1; if ((error = xfs_alloc_vextent(&args))) return error; } /* * If stripe alignment is turned on, then try again with cluster * alignment. */ if (isaligned && args.fsbno == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_NEAR_BNO; args.agbno = be32_to_cpu(agi->agi_root); args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); args.alignment = xfs_ialloc_cluster_alignment(args.mp); if ((error = xfs_alloc_vextent(&args))) return error; } /* * Finally, try a sparse allocation if the filesystem supports it and * the sparse allocation length is smaller than a full chunk. */ if (xfs_sb_version_hassparseinodes(&args.mp->m_sb) && args.mp->m_ialloc_min_blks < args.mp->m_ialloc_blks && args.fsbno == NULLFSBLOCK) { sparse_alloc: args.type = XFS_ALLOCTYPE_NEAR_BNO; args.agbno = be32_to_cpu(agi->agi_root); args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); args.alignment = args.mp->m_sb.sb_spino_align; args.prod = 1; args.minlen = args.mp->m_ialloc_min_blks; args.maxlen = args.minlen; /* * The inode record will be aligned to full chunk size. We must * prevent sparse allocation from AG boundaries that result in * invalid inode records, such as records that start at agbno 0 * or extend beyond the AG. * * Set min agbno to the first aligned, non-zero agbno and max to * the last aligned agbno that is at least one full chunk from * the end of the AG. */ args.min_agbno = args.mp->m_sb.sb_inoalignmt; args.max_agbno = round_down(args.mp->m_sb.sb_agblocks, args.mp->m_sb.sb_inoalignmt) - args.mp->m_ialloc_blks; error = xfs_alloc_vextent(&args); if (error) return error; newlen = args.len << args.mp->m_sb.sb_inopblog; ASSERT(newlen <= XFS_INODES_PER_CHUNK); allocmask = (1 << (newlen / XFS_INODES_PER_HOLEMASK_BIT)) - 1; } if (args.fsbno == NULLFSBLOCK) { *alloc = 0; return 0; } ASSERT(args.len == args.minlen); /* * Stamp and write the inode buffers. * * Seed the new inode cluster with a random generation number. This * prevents short-term reuse of generation numbers if a chunk is * freed and then immediately reallocated. We use random numbers * rather than a linear progression to prevent the next generation * number from being easily guessable. */ error = xfs_ialloc_inode_init(args.mp, tp, NULL, newlen, agno, args.agbno, args.len, prandom_u32()); if (error) return error; /* * Convert the results. */ newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0); if (xfs_inobt_issparse(~allocmask)) { /* * We've allocated a sparse chunk. Align the startino and mask. */ xfs_align_sparse_ino(args.mp, &newino, &allocmask); rec.ir_startino = newino; rec.ir_holemask = ~allocmask; rec.ir_count = newlen; rec.ir_freecount = newlen; rec.ir_free = XFS_INOBT_ALL_FREE; /* * Insert the sparse record into the inobt and allow for a merge * if necessary. If a merge does occur, rec is updated to the * merged record. */ error = xfs_inobt_insert_sprec(args.mp, tp, agbp, XFS_BTNUM_INO, &rec, true); if (error == -EFSCORRUPTED) { xfs_alert(args.mp, "invalid sparse inode record: ino 0x%llx holemask 0x%x count %u", XFS_AGINO_TO_INO(args.mp, agno, rec.ir_startino), rec.ir_holemask, rec.ir_count); xfs_force_shutdown(args.mp, SHUTDOWN_CORRUPT_INCORE); } if (error) return error; /* * We can't merge the part we've just allocated as for the inobt * due to finobt semantics. The original record may or may not * exist independent of whether physical inodes exist in this * sparse chunk. * * We must update the finobt record based on the inobt record. * rec contains the fully merged and up to date inobt record * from the previous call. Set merge false to replace any * existing record with this one. */ if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) { error = xfs_inobt_insert_sprec(args.mp, tp, agbp, XFS_BTNUM_FINO, &rec, false); if (error) return error; } } else { /* full chunk - insert new records to both btrees */ error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen, XFS_BTNUM_INO); if (error) return error; if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) { error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen, XFS_BTNUM_FINO); if (error) return error; } } /* * Update AGI counts and newino. */ be32_add_cpu(&agi->agi_count, newlen); be32_add_cpu(&agi->agi_freecount, newlen); pag = xfs_perag_get(args.mp, agno); pag->pagi_freecount += newlen; xfs_perag_put(pag); agi->agi_newino = cpu_to_be32(newino); /* * Log allocation group header fields */ xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT | XFS_AGI_NEWINO); /* * Modify/log superblock values for inode count and inode free count. */ xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, (long)newlen); xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, (long)newlen); *alloc = 1; return 0; } STATIC xfs_agnumber_t xfs_ialloc_next_ag( xfs_mount_t *mp) { xfs_agnumber_t agno; spin_lock(&mp->m_agirotor_lock); agno = mp->m_agirotor; if (++mp->m_agirotor >= mp->m_maxagi) mp->m_agirotor = 0; spin_unlock(&mp->m_agirotor_lock); return agno; } /* * Select an allocation group to look for a free inode in, based on the parent * inode and the mode. Return the allocation group buffer. */ STATIC xfs_agnumber_t xfs_ialloc_ag_select( xfs_trans_t *tp, /* transaction pointer */ xfs_ino_t parent, /* parent directory inode number */ umode_t mode, /* bits set to indicate file type */ int okalloc) /* ok to allocate more space */ { xfs_agnumber_t agcount; /* number of ag's in the filesystem */ xfs_agnumber_t agno; /* current ag number */ int flags; /* alloc buffer locking flags */ xfs_extlen_t ineed; /* blocks needed for inode allocation */ xfs_extlen_t longest = 0; /* longest extent available */ xfs_mount_t *mp; /* mount point structure */ int needspace; /* file mode implies space allocated */ xfs_perag_t *pag; /* per allocation group data */ xfs_agnumber_t pagno; /* parent (starting) ag number */ int error; /* * Files of these types need at least one block if length > 0 * (and they won't fit in the inode, but that's hard to figure out). */ needspace = S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode); mp = tp->t_mountp; agcount = mp->m_maxagi; if (S_ISDIR(mode)) pagno = xfs_ialloc_next_ag(mp); else { pagno = XFS_INO_TO_AGNO(mp, parent); if (pagno >= agcount) pagno = 0; } ASSERT(pagno < agcount); /* * Loop through allocation groups, looking for one with a little * free space in it. Note we don't look for free inodes, exactly. * Instead, we include whether there is a need to allocate inodes * to mean that blocks must be allocated for them, * if none are currently free. */ agno = pagno; flags = XFS_ALLOC_FLAG_TRYLOCK; for (;;) { pag = xfs_perag_get(mp, agno); if (!pag->pagi_inodeok) { xfs_ialloc_next_ag(mp); goto nextag; } if (!pag->pagi_init) { error = xfs_ialloc_pagi_init(mp, tp, agno); if (error) goto nextag; } if (pag->pagi_freecount) { xfs_perag_put(pag); return agno; } if (!okalloc) goto nextag; if (!pag->pagf_init) { error = xfs_alloc_pagf_init(mp, tp, agno, flags); if (error) goto nextag; } /* * Check that there is enough free space for the file plus a * chunk of inodes if we need to allocate some. If this is the * first pass across the AGs, take into account the potential * space needed for alignment of inode chunks when checking the * longest contiguous free space in the AG - this prevents us * from getting ENOSPC because we have free space larger than * m_ialloc_blks but alignment constraints prevent us from using * it. * * If we can't find an AG with space for full alignment slack to * be taken into account, we must be near ENOSPC in all AGs. * Hence we don't include alignment for the second pass and so * if we fail allocation due to alignment issues then it is most * likely a real ENOSPC condition. */ ineed = mp->m_ialloc_min_blks; if (flags && ineed > 1) ineed += xfs_ialloc_cluster_alignment(mp); longest = pag->pagf_longest; if (!longest) longest = pag->pagf_flcount > 0; if (pag->pagf_freeblks >= needspace + ineed && longest >= ineed) { xfs_perag_put(pag); return agno; } nextag: xfs_perag_put(pag); /* * No point in iterating over the rest, if we're shutting * down. */ if (XFS_FORCED_SHUTDOWN(mp)) return NULLAGNUMBER; agno++; if (agno >= agcount) agno = 0; if (agno == pagno) { if (flags == 0) return NULLAGNUMBER; flags = 0; } } } /* * Try to retrieve the next record to the left/right from the current one. */ STATIC int xfs_ialloc_next_rec( struct xfs_btree_cur *cur, xfs_inobt_rec_incore_t *rec, int *done, int left) { int error; int i; if (left) error = xfs_btree_decrement(cur, 0, &i); else error = xfs_btree_increment(cur, 0, &i); if (error) return error; *done = !i; if (i) { error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); } return 0; } STATIC int xfs_ialloc_get_rec( struct xfs_btree_cur *cur, xfs_agino_t agino, xfs_inobt_rec_incore_t *rec, int *done) { int error; int i; error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_EQ, &i); if (error) return error; *done = !i; if (i) { error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); } return 0; } /* * Return the offset of the first free inode in the record. If the inode chunk * is sparsely allocated, we convert the record holemask to inode granularity * and mask off the unallocated regions from the inode free mask. */ STATIC int xfs_inobt_first_free_inode( struct xfs_inobt_rec_incore *rec) { xfs_inofree_t realfree; /* if there are no holes, return the first available offset */ if (!xfs_inobt_issparse(rec->ir_holemask)) return xfs_lowbit64(rec->ir_free); realfree = xfs_inobt_irec_to_allocmask(rec); realfree &= rec->ir_free; return xfs_lowbit64(realfree); } /* * Allocate an inode using the inobt-only algorithm. */ STATIC int xfs_dialloc_ag_inobt( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_ino_t parent, xfs_ino_t *inop) { struct xfs_mount *mp = tp->t_mountp; struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent); xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent); struct xfs_perag *pag; struct xfs_btree_cur *cur, *tcur; struct xfs_inobt_rec_incore rec, trec; xfs_ino_t ino; int error; int offset; int i, j; pag = xfs_perag_get(mp, agno); ASSERT(pag->pagi_init); ASSERT(pag->pagi_inodeok); ASSERT(pag->pagi_freecount > 0); restart_pagno: cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); /* * If pagino is 0 (this is the root inode allocation) use newino. * This must work because we've just allocated some. */ if (!pagino) pagino = be32_to_cpu(agi->agi_newino); error = xfs_check_agi_freecount(cur, agi); if (error) goto error0; /* * If in the same AG as the parent, try to get near the parent. */ if (pagno == agno) { int doneleft; /* done, to the left */ int doneright; /* done, to the right */ int searchdistance = 10; error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); error = xfs_inobt_get_rec(cur, &rec, &j); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, j == 1, error0); if (rec.ir_freecount > 0) { /* * Found a free inode in the same chunk * as the parent, done. */ goto alloc_inode; } /* * In the same AG as parent, but parent's chunk is full. */ /* duplicate the cursor, search left & right simultaneously */ error = xfs_btree_dup_cursor(cur, &tcur); if (error) goto error0; /* * Skip to last blocks looked up if same parent inode. */ if (pagino != NULLAGINO && pag->pagl_pagino == pagino && pag->pagl_leftrec != NULLAGINO && pag->pagl_rightrec != NULLAGINO) { error = xfs_ialloc_get_rec(tcur, pag->pagl_leftrec, &trec, &doneleft); if (error) goto error1; error = xfs_ialloc_get_rec(cur, pag->pagl_rightrec, &rec, &doneright); if (error) goto error1; } else { /* search left with tcur, back up 1 record */ error = xfs_ialloc_next_rec(tcur, &trec, &doneleft, 1); if (error) goto error1; /* search right with cur, go forward 1 record. */ error = xfs_ialloc_next_rec(cur, &rec, &doneright, 0); if (error) goto error1; } /* * Loop until we find an inode chunk with a free inode. */ while (!doneleft || !doneright) { int useleft; /* using left inode chunk this time */ if (!--searchdistance) { /* * Not in range - save last search * location and allocate a new inode */ xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); pag->pagl_leftrec = trec.ir_startino; pag->pagl_rightrec = rec.ir_startino; pag->pagl_pagino = pagino; goto newino; } /* figure out the closer block if both are valid. */ if (!doneleft && !doneright) { useleft = pagino - (trec.ir_startino + XFS_INODES_PER_CHUNK - 1) < rec.ir_startino - pagino; } else { useleft = !doneleft; } /* free inodes to the left? */ if (useleft && trec.ir_freecount) { rec = trec; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); cur = tcur; pag->pagl_leftrec = trec.ir_startino; pag->pagl_rightrec = rec.ir_startino; pag->pagl_pagino = pagino; goto alloc_inode; } /* free inodes to the right? */ if (!useleft && rec.ir_freecount) { xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); pag->pagl_leftrec = trec.ir_startino; pag->pagl_rightrec = rec.ir_startino; pag->pagl_pagino = pagino; goto alloc_inode; } /* get next record to check */ if (useleft) { error = xfs_ialloc_next_rec(tcur, &trec, &doneleft, 1); } else { error = xfs_ialloc_next_rec(cur, &rec, &doneright, 0); } if (error) goto error1; } /* * We've reached the end of the btree. because * we are only searching a small chunk of the * btree each search, there is obviously free * inodes closer to the parent inode than we * are now. restart the search again. */ pag->pagl_pagino = NULLAGINO; pag->pagl_leftrec = NULLAGINO; pag->pagl_rightrec = NULLAGINO; xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); goto restart_pagno; } /* * In a different AG from the parent. * See if the most recently allocated block has any free. */ newino: if (agi->agi_newino != cpu_to_be32(NULLAGINO)) { error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino), XFS_LOOKUP_EQ, &i); if (error) goto error0; if (i == 1) { error = xfs_inobt_get_rec(cur, &rec, &j); if (error) goto error0; if (j == 1 && rec.ir_freecount > 0) { /* * The last chunk allocated in the group * still has a free inode. */ goto alloc_inode; } } } /* * None left in the last group, search the whole AG */ error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); for (;;) { error = xfs_inobt_get_rec(cur, &rec, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); if (rec.ir_freecount > 0) break; error = xfs_btree_increment(cur, 0, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); } alloc_inode: offset = xfs_inobt_first_free_inode(&rec); ASSERT(offset >= 0); ASSERT(offset < XFS_INODES_PER_CHUNK); ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) % XFS_INODES_PER_CHUNK) == 0); ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); rec.ir_free &= ~XFS_INOBT_MASK(offset); rec.ir_freecount--; error = xfs_inobt_update(cur, &rec); if (error) goto error0; be32_add_cpu(&agi->agi_freecount, -1); xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); pag->pagi_freecount--; error = xfs_check_agi_freecount(cur, agi); if (error) goto error0; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1); xfs_perag_put(pag); *inop = ino; return 0; error1: xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); error0: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); xfs_perag_put(pag); return error; } /* * Use the free inode btree to allocate an inode based on distance from the * parent. Note that the provided cursor may be deleted and replaced. */ STATIC int xfs_dialloc_ag_finobt_near( xfs_agino_t pagino, struct xfs_btree_cur **ocur, struct xfs_inobt_rec_incore *rec) { struct xfs_btree_cur *lcur = *ocur; /* left search cursor */ struct xfs_btree_cur *rcur; /* right search cursor */ struct xfs_inobt_rec_incore rrec; int error; int i, j; error = xfs_inobt_lookup(lcur, pagino, XFS_LOOKUP_LE, &i); if (error) return error; if (i == 1) { error = xfs_inobt_get_rec(lcur, rec, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(lcur->bc_mp, i == 1); /* * See if we've landed in the parent inode record. The finobt * only tracks chunks with at least one free inode, so record * existence is enough. */ if (pagino >= rec->ir_startino && pagino < (rec->ir_startino + XFS_INODES_PER_CHUNK)) return 0; } error = xfs_btree_dup_cursor(lcur, &rcur); if (error) return error; error = xfs_inobt_lookup(rcur, pagino, XFS_LOOKUP_GE, &j); if (error) goto error_rcur; if (j == 1) { error = xfs_inobt_get_rec(rcur, &rrec, &j); if (error) goto error_rcur; XFS_WANT_CORRUPTED_GOTO(lcur->bc_mp, j == 1, error_rcur); } XFS_WANT_CORRUPTED_GOTO(lcur->bc_mp, i == 1 || j == 1, error_rcur); if (i == 1 && j == 1) { /* * Both the left and right records are valid. Choose the closer * inode chunk to the target. */ if ((pagino - rec->ir_startino + XFS_INODES_PER_CHUNK - 1) > (rrec.ir_startino - pagino)) { *rec = rrec; xfs_btree_del_cursor(lcur, XFS_BTREE_NOERROR); *ocur = rcur; } else { xfs_btree_del_cursor(rcur, XFS_BTREE_NOERROR); } } else if (j == 1) { /* only the right record is valid */ *rec = rrec; xfs_btree_del_cursor(lcur, XFS_BTREE_NOERROR); *ocur = rcur; } else if (i == 1) { /* only the left record is valid */ xfs_btree_del_cursor(rcur, XFS_BTREE_NOERROR); } return 0; error_rcur: xfs_btree_del_cursor(rcur, XFS_BTREE_ERROR); return error; } /* * Use the free inode btree to find a free inode based on a newino hint. If * the hint is NULL, find the first free inode in the AG. */ STATIC int xfs_dialloc_ag_finobt_newino( struct xfs_agi *agi, struct xfs_btree_cur *cur, struct xfs_inobt_rec_incore *rec) { int error; int i; if (agi->agi_newino != cpu_to_be32(NULLAGINO)) { error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino), XFS_LOOKUP_EQ, &i); if (error) return error; if (i == 1) { error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); return 0; } } /* * Find the first inode available in the AG. */ error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); return 0; } /* * Update the inobt based on a modification made to the finobt. Also ensure that * the records from both trees are equivalent post-modification. */ STATIC int xfs_dialloc_ag_update_inobt( struct xfs_btree_cur *cur, /* inobt cursor */ struct xfs_inobt_rec_incore *frec, /* finobt record */ int offset) /* inode offset */ { struct xfs_inobt_rec_incore rec; int error; int i; error = xfs_inobt_lookup(cur, frec->ir_startino, XFS_LOOKUP_EQ, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); error = xfs_inobt_get_rec(cur, &rec, &i); if (error) return error; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); ASSERT((XFS_AGINO_TO_OFFSET(cur->bc_mp, rec.ir_startino) % XFS_INODES_PER_CHUNK) == 0); rec.ir_free &= ~XFS_INOBT_MASK(offset); rec.ir_freecount--; XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, (rec.ir_free == frec->ir_free) && (rec.ir_freecount == frec->ir_freecount)); return xfs_inobt_update(cur, &rec); } /* * Allocate an inode using the free inode btree, if available. Otherwise, fall * back to the inobt search algorithm. * * The caller selected an AG for us, and made sure that free inodes are * available. */ STATIC int xfs_dialloc_ag( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_ino_t parent, xfs_ino_t *inop) { struct xfs_mount *mp = tp->t_mountp; struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent); xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent); struct xfs_perag *pag; struct xfs_btree_cur *cur; /* finobt cursor */ struct xfs_btree_cur *icur; /* inobt cursor */ struct xfs_inobt_rec_incore rec; xfs_ino_t ino; int error; int offset; int i; if (!xfs_sb_version_hasfinobt(&mp->m_sb)) return xfs_dialloc_ag_inobt(tp, agbp, parent, inop); pag = xfs_perag_get(mp, agno); /* * If pagino is 0 (this is the root inode allocation) use newino. * This must work because we've just allocated some. */ if (!pagino) pagino = be32_to_cpu(agi->agi_newino); cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO); error = xfs_check_agi_freecount(cur, agi); if (error) goto error_cur; /* * The search algorithm depends on whether we're in the same AG as the * parent. If so, find the closest available inode to the parent. If * not, consider the agi hint or find the first free inode in the AG. */ if (agno == pagno) error = xfs_dialloc_ag_finobt_near(pagino, &cur, &rec); else error = xfs_dialloc_ag_finobt_newino(agi, cur, &rec); if (error) goto error_cur; offset = xfs_inobt_first_free_inode(&rec); ASSERT(offset >= 0); ASSERT(offset < XFS_INODES_PER_CHUNK); ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) % XFS_INODES_PER_CHUNK) == 0); ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); /* * Modify or remove the finobt record. */ rec.ir_free &= ~XFS_INOBT_MASK(offset); rec.ir_freecount--; if (rec.ir_freecount) error = xfs_inobt_update(cur, &rec); else error = xfs_btree_delete(cur, &i); if (error) goto error_cur; /* * The finobt has now been updated appropriately. We haven't updated the * agi and superblock yet, so we can create an inobt cursor and validate * the original freecount. If all is well, make the equivalent update to * the inobt using the finobt record and offset information. */ icur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); error = xfs_check_agi_freecount(icur, agi); if (error) goto error_icur; error = xfs_dialloc_ag_update_inobt(icur, &rec, offset); if (error) goto error_icur; /* * Both trees have now been updated. We must update the perag and * superblock before we can check the freecount for each btree. */ be32_add_cpu(&agi->agi_freecount, -1); xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); pag->pagi_freecount--; xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1); error = xfs_check_agi_freecount(icur, agi); if (error) goto error_icur; error = xfs_check_agi_freecount(cur, agi); if (error) goto error_icur; xfs_btree_del_cursor(icur, XFS_BTREE_NOERROR); xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); xfs_perag_put(pag); *inop = ino; return 0; error_icur: xfs_btree_del_cursor(icur, XFS_BTREE_ERROR); error_cur: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); xfs_perag_put(pag); return error; } /* * Allocate an inode on disk. * * Mode is used to tell whether the new inode will need space, and whether it * is a directory. * * This function is designed to be called twice if it has to do an allocation * to make more free inodes. On the first call, *IO_agbp should be set to NULL. * If an inode is available without having to performn an allocation, an inode * number is returned. In this case, *IO_agbp is set to NULL. If an allocation * needs to be done, xfs_dialloc returns the current AGI buffer in *IO_agbp. * The caller should then commit the current transaction, allocate a * new transaction, and call xfs_dialloc() again, passing in the previous value * of *IO_agbp. IO_agbp should be held across the transactions. Since the AGI * buffer is locked across the two calls, the second call is guaranteed to have * a free inode available. * * Once we successfully pick an inode its number is returned and the on-disk * data structures are updated. The inode itself is not read in, since doing so * would break ordering constraints with xfs_reclaim. */ int xfs_dialloc( struct xfs_trans *tp, xfs_ino_t parent, umode_t mode, int okalloc, struct xfs_buf **IO_agbp, xfs_ino_t *inop) { struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *agbp; xfs_agnumber_t agno; int error; int ialloced; int noroom = 0; xfs_agnumber_t start_agno; struct xfs_perag *pag; if (*IO_agbp) { /* * If the caller passes in a pointer to the AGI buffer, * continue where we left off before. In this case, we * know that the allocation group has free inodes. */ agbp = *IO_agbp; goto out_alloc; } /* * We do not have an agbp, so select an initial allocation * group for inode allocation. */ start_agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc); if (start_agno == NULLAGNUMBER) { *inop = NULLFSINO; return 0; } /* * If we have already hit the ceiling of inode blocks then clear * okalloc so we scan all available agi structures for a free * inode. * * Read rough value of mp->m_icount by percpu_counter_read_positive, * which will sacrifice the preciseness but improve the performance. */ if (mp->m_maxicount && percpu_counter_read_positive(&mp->m_icount) + mp->m_ialloc_inos > mp->m_maxicount) { noroom = 1; okalloc = 0; } /* * Loop until we find an allocation group that either has free inodes * or in which we can allocate some inodes. Iterate through the * allocation groups upward, wrapping at the end. */ agno = start_agno; for (;;) { pag = xfs_perag_get(mp, agno); if (!pag->pagi_inodeok) { xfs_ialloc_next_ag(mp); goto nextag; } if (!pag->pagi_init) { error = xfs_ialloc_pagi_init(mp, tp, agno); if (error) goto out_error; } /* * Do a first racy fast path check if this AG is usable. */ if (!pag->pagi_freecount && !okalloc) goto nextag; /* * Then read in the AGI buffer and recheck with the AGI buffer * lock held. */ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) goto out_error; if (pag->pagi_freecount) { xfs_perag_put(pag); goto out_alloc; } if (!okalloc) goto nextag_relse_buffer; error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced); if (error) { xfs_trans_brelse(tp, agbp); if (error != -ENOSPC) goto out_error; xfs_perag_put(pag); *inop = NULLFSINO; return 0; } if (ialloced) { /* * We successfully allocated some inodes, return * the current context to the caller so that it * can commit the current transaction and call * us again where we left off. */ ASSERT(pag->pagi_freecount > 0); xfs_perag_put(pag); *IO_agbp = agbp; *inop = NULLFSINO; return 0; } nextag_relse_buffer: xfs_trans_brelse(tp, agbp); nextag: xfs_perag_put(pag); if (++agno == mp->m_sb.sb_agcount) agno = 0; if (agno == start_agno) { *inop = NULLFSINO; return noroom ? -ENOSPC : 0; } } out_alloc: *IO_agbp = NULL; return xfs_dialloc_ag(tp, agbp, parent, inop); out_error: xfs_perag_put(pag); return error; } /* * Free the blocks of an inode chunk. We must consider that the inode chunk * might be sparse and only free the regions that are allocated as part of the * chunk. */ STATIC void xfs_difree_inode_chunk( struct xfs_mount *mp, xfs_agnumber_t agno, struct xfs_inobt_rec_incore *rec, struct xfs_defer_ops *dfops) { xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); int startidx, endidx; int nextbit; xfs_agblock_t agbno; int contigblk; struct xfs_owner_info oinfo; DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS); xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno), mp->m_ialloc_blks, &oinfo); return; } /* holemask is only 16-bits (fits in an unsigned long) */ ASSERT(sizeof(rec->ir_holemask) <= sizeof(holemask[0])); holemask[0] = rec->ir_holemask; /* * Find contiguous ranges of zeroes (i.e., allocated regions) in the * holemask and convert the start/end index of each range to an extent. * We start with the start and end index both pointing at the first 0 in * the mask. */ startidx = endidx = find_first_zero_bit(holemask, XFS_INOBT_HOLEMASK_BITS); nextbit = startidx + 1; while (startidx < XFS_INOBT_HOLEMASK_BITS) { nextbit = find_next_zero_bit(holemask, XFS_INOBT_HOLEMASK_BITS, nextbit); /* * If the next zero bit is contiguous, update the end index of * the current range and continue. */ if (nextbit != XFS_INOBT_HOLEMASK_BITS && nextbit == endidx + 1) { endidx = nextbit; goto next; } /* * nextbit is not contiguous with the current end index. Convert * the current start/end to an extent and add it to the free * list. */ agbno = sagbno + (startidx * XFS_INODES_PER_HOLEMASK_BIT) / mp->m_sb.sb_inopblock; contigblk = ((endidx - startidx + 1) * XFS_INODES_PER_HOLEMASK_BIT) / mp->m_sb.sb_inopblock; ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno), contigblk, &oinfo); /* reset range to current bit and carry on... */ startidx = endidx = nextbit; next: nextbit++; } } STATIC int xfs_difree_inobt( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agino_t agino, struct xfs_defer_ops *dfops, struct xfs_icluster *xic, struct xfs_inobt_rec_incore *orec) { struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); struct xfs_perag *pag; struct xfs_btree_cur *cur; struct xfs_inobt_rec_incore rec; int ilen; int error; int i; int off; ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); ASSERT(XFS_AGINO_TO_AGBNO(mp, agino) < be32_to_cpu(agi->agi_length)); /* * Initialize the cursor. */ cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); error = xfs_check_agi_freecount(cur, agi); if (error) goto error0; /* * Look for the entry describing this inode. */ if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) { xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.", __func__, error); goto error0; } XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); error = xfs_inobt_get_rec(cur, &rec, &i); if (error) { xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.", __func__, error); goto error0; } XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); /* * Get the offset in the inode chunk. */ off = agino - rec.ir_startino; ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK); ASSERT(!(rec.ir_free & XFS_INOBT_MASK(off))); /* * Mark the inode free & increment the count. */ rec.ir_free |= XFS_INOBT_MASK(off); rec.ir_freecount++; /* * When an inode chunk is free, it becomes eligible for removal. Don't * remove the chunk if the block size is large enough for multiple inode * chunks (that might not be free). */ if (!(mp->m_flags & XFS_MOUNT_IKEEP) && rec.ir_free == XFS_INOBT_ALL_FREE && mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK) { xic->deleted = 1; xic->first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); xic->alloc = xfs_inobt_irec_to_allocmask(&rec); /* * Remove the inode cluster from the AGI B+Tree, adjust the * AGI and Superblock inode counts, and mark the disk space * to be freed when the transaction is committed. */ ilen = rec.ir_freecount; be32_add_cpu(&agi->agi_count, -ilen); be32_add_cpu(&agi->agi_freecount, -(ilen - 1)); xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT); pag = xfs_perag_get(mp, agno); pag->pagi_freecount -= ilen - 1; xfs_perag_put(pag); xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen); xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1)); if ((error = xfs_btree_delete(cur, &i))) { xfs_warn(mp, "%s: xfs_btree_delete returned error %d.", __func__, error); goto error0; } xfs_difree_inode_chunk(mp, agno, &rec, dfops); } else { xic->deleted = 0; error = xfs_inobt_update(cur, &rec); if (error) { xfs_warn(mp, "%s: xfs_inobt_update returned error %d.", __func__, error); goto error0; } /* * Change the inode free counts and log the ag/sb changes. */ be32_add_cpu(&agi->agi_freecount, 1); xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); pag = xfs_perag_get(mp, agno); pag->pagi_freecount++; xfs_perag_put(pag); xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1); } error = xfs_check_agi_freecount(cur, agi); if (error) goto error0; *orec = rec; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; error0: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } /* * Free an inode in the free inode btree. */ STATIC int xfs_difree_finobt( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agino_t agino, struct xfs_inobt_rec_incore *ibtrec) /* inobt record */ { struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); struct xfs_btree_cur *cur; struct xfs_inobt_rec_incore rec; int offset = agino - ibtrec->ir_startino; int error; int i; cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO); error = xfs_inobt_lookup(cur, ibtrec->ir_startino, XFS_LOOKUP_EQ, &i); if (error) goto error; if (i == 0) { /* * If the record does not exist in the finobt, we must have just * freed an inode in a previously fully allocated chunk. If not, * something is out of sync. */ XFS_WANT_CORRUPTED_GOTO(mp, ibtrec->ir_freecount == 1, error); error = xfs_inobt_insert_rec(cur, ibtrec->ir_holemask, ibtrec->ir_count, ibtrec->ir_freecount, ibtrec->ir_free, &i); if (error) goto error; ASSERT(i == 1); goto out; } /* * Read and update the existing record. We could just copy the ibtrec * across here, but that would defeat the purpose of having redundant * metadata. By making the modifications independently, we can catch * corruptions that we wouldn't see if we just copied from one record * to another. */ error = xfs_inobt_get_rec(cur, &rec, &i); if (error) goto error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error); rec.ir_free |= XFS_INOBT_MASK(offset); rec.ir_freecount++; XFS_WANT_CORRUPTED_GOTO(mp, (rec.ir_free == ibtrec->ir_free) && (rec.ir_freecount == ibtrec->ir_freecount), error); /* * The content of inobt records should always match between the inobt * and finobt. The lifecycle of records in the finobt is different from * the inobt in that the finobt only tracks records with at least one * free inode. Hence, if all of the inodes are free and we aren't * keeping inode chunks permanently on disk, remove the record. * Otherwise, update the record with the new information. * * Note that we currently can't free chunks when the block size is large * enough for multiple chunks. Leave the finobt record to remain in sync * with the inobt. */ if (rec.ir_free == XFS_INOBT_ALL_FREE && mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK && !(mp->m_flags & XFS_MOUNT_IKEEP)) { error = xfs_btree_delete(cur, &i); if (error) goto error; ASSERT(i == 1); } else { error = xfs_inobt_update(cur, &rec); if (error) goto error; } out: error = xfs_check_agi_freecount(cur, agi); if (error) goto error; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; error: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } /* * Free disk inode. Carefully avoids touching the incore inode, all * manipulations incore are the caller's responsibility. * The on-disk inode is not changed by this operation, only the * btree (free inode mask) is changed. */ int xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ struct xfs_defer_ops *dfops, /* extents to free */ struct xfs_icluster *xic) /* cluster info if deleted */ { /* REFERENCED */ xfs_agblock_t agbno; /* block number containing inode */ struct xfs_buf *agbp; /* buffer for allocation group header */ xfs_agino_t agino; /* allocation group inode number */ xfs_agnumber_t agno; /* allocation group number */ int error; /* error return value */ struct xfs_mount *mp; /* mount structure for filesystem */ struct xfs_inobt_rec_incore rec;/* btree record */ mp = tp->t_mountp; /* * Break up inode number into its components. */ agno = XFS_INO_TO_AGNO(mp, inode); if (agno >= mp->m_sb.sb_agcount) { xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).", __func__, agno, mp->m_sb.sb_agcount); ASSERT(0); return -EINVAL; } agino = XFS_INO_TO_AGINO(mp, inode); if (inode != XFS_AGINO_TO_INO(mp, agno, agino)) { xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).", __func__, (unsigned long long)inode, (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino)); ASSERT(0); return -EINVAL; } agbno = XFS_AGINO_TO_AGBNO(mp, agino); if (agbno >= mp->m_sb.sb_agblocks) { xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).", __func__, agbno, mp->m_sb.sb_agblocks); ASSERT(0); return -EINVAL; } /* * Get the allocation group header. */ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) { xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", __func__, error); return error; } /* * Fix up the inode allocation btree. */ error = xfs_difree_inobt(mp, tp, agbp, agino, dfops, xic, &rec); if (error) goto error0; /* * Fix up the free inode btree. */ if (xfs_sb_version_hasfinobt(&mp->m_sb)) { error = xfs_difree_finobt(mp, tp, agbp, agino, &rec); if (error) goto error0; } return 0; error0: return error; } STATIC int xfs_imap_lookup( struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, xfs_agino_t agino, xfs_agblock_t agbno, xfs_agblock_t *chunk_agbno, xfs_agblock_t *offset_agbno, int flags) { struct xfs_inobt_rec_incore rec; struct xfs_btree_cur *cur; struct xfs_buf *agbp; int error; int i; error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) { xfs_alert(mp, "%s: xfs_ialloc_read_agi() returned error %d, agno %d", __func__, error, agno); return error; } /* * Lookup the inode record for the given agino. If the record cannot be * found, then it's an invalid inode number and we should abort. Once * we have a record, we need to ensure it contains the inode number * we are looking up. */ cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i); if (!error) { if (i) error = xfs_inobt_get_rec(cur, &rec, &i); if (!error && i == 0) error = -EINVAL; } xfs_trans_brelse(tp, agbp); xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); if (error) return error; /* check that the returned record contains the required inode */ if (rec.ir_startino > agino || rec.ir_startino + mp->m_ialloc_inos <= agino) return -EINVAL; /* for untrusted inodes check it is allocated first */ if ((flags & XFS_IGET_UNTRUSTED) && (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))) return -EINVAL; *chunk_agbno = XFS_AGINO_TO_AGBNO(mp, rec.ir_startino); *offset_agbno = agbno - *chunk_agbno; return 0; } /* * Return the location of the inode in imap, for mapping it into a buffer. */ int xfs_imap( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ xfs_ino_t ino, /* inode to locate */ struct xfs_imap *imap, /* location map structure */ uint flags) /* flags for inode btree lookup */ { xfs_agblock_t agbno; /* block number of inode in the alloc group */ xfs_agino_t agino; /* inode number within alloc group */ xfs_agnumber_t agno; /* allocation group number */ int blks_per_cluster; /* num blocks per inode cluster */ xfs_agblock_t chunk_agbno; /* first block in inode chunk */ xfs_agblock_t cluster_agbno; /* first block in inode cluster */ int error; /* error code */ int offset; /* index of inode in its buffer */ xfs_agblock_t offset_agbno; /* blks from chunk start to inode */ ASSERT(ino != NULLFSINO); /* * Split up the inode number into its parts. */ agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || ino != XFS_AGINO_TO_INO(mp, agno, agino)) { #ifdef DEBUG /* * Don't output diagnostic information for untrusted inodes * as they can be invalid without implying corruption. */ if (flags & XFS_IGET_UNTRUSTED) return -EINVAL; if (agno >= mp->m_sb.sb_agcount) { xfs_alert(mp, "%s: agno (%d) >= mp->m_sb.sb_agcount (%d)", __func__, agno, mp->m_sb.sb_agcount); } if (agbno >= mp->m_sb.sb_agblocks) { xfs_alert(mp, "%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)", __func__, (unsigned long long)agbno, (unsigned long)mp->m_sb.sb_agblocks); } if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) { xfs_alert(mp, "%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)", __func__, ino, XFS_AGINO_TO_INO(mp, agno, agino)); } xfs_stack_trace(); #endif /* DEBUG */ return -EINVAL; } blks_per_cluster = xfs_icluster_size_fsb(mp); /* * For bulkstat and handle lookups, we have an untrusted inode number * that we have to verify is valid. We cannot do this just by reading * the inode buffer as it may have been unlinked and removed leaving * inodes in stale state on disk. Hence we have to do a btree lookup * in all cases where an untrusted inode number is passed. */ if (flags & XFS_IGET_UNTRUSTED) { error = xfs_imap_lookup(mp, tp, agno, agino, agbno, &chunk_agbno, &offset_agbno, flags); if (error) return error; goto out_map; } /* * If the inode cluster size is the same as the blocksize or * smaller we get to the buffer by simple arithmetics. */ if (blks_per_cluster == 1) { offset = XFS_INO_TO_OFFSET(mp, ino); ASSERT(offset < mp->m_sb.sb_inopblock); imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno); imap->im_len = XFS_FSB_TO_BB(mp, 1); imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog); return 0; } /* * If the inode chunks are aligned then use simple maths to * find the location. Otherwise we have to do a btree * lookup to find the location. */ if (mp->m_inoalign_mask) { offset_agbno = agbno & mp->m_inoalign_mask; chunk_agbno = agbno - offset_agbno; } else { error = xfs_imap_lookup(mp, tp, agno, agino, agbno, &chunk_agbno, &offset_agbno, flags); if (error) return error; } out_map: ASSERT(agbno >= chunk_agbno); cluster_agbno = chunk_agbno + ((offset_agbno / blks_per_cluster) * blks_per_cluster); offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) + XFS_INO_TO_OFFSET(mp, ino); imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno); imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster); imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog); /* * If the inode number maps to a block outside the bounds * of the file system then return NULL rather than calling * read_buf and panicing when we get an error from the * driver. */ if ((imap->im_blkno + imap->im_len) > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) { xfs_alert(mp, "%s: (im_blkno (0x%llx) + im_len (0x%llx)) > sb_dblocks (0x%llx)", __func__, (unsigned long long) imap->im_blkno, (unsigned long long) imap->im_len, XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)); return -EINVAL; } return 0; } /* * Compute and fill in value of m_in_maxlevels. */ void xfs_ialloc_compute_maxlevels( xfs_mount_t *mp) /* file system mount structure */ { uint inodes; inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG; mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr, inodes); } /* * Log specified fields for the ag hdr (inode section). The growth of the agi * structure over time requires that we interpret the buffer as two logical * regions delineated by the end of the unlinked list. This is due to the size * of the hash table and its location in the middle of the agi. * * For example, a request to log a field before agi_unlinked and a field after * agi_unlinked could cause us to log the entire hash table and use an excessive * amount of log space. To avoid this behavior, log the region up through * agi_unlinked in one call and the region after agi_unlinked through the end of * the structure in another. */ void xfs_ialloc_log_agi( xfs_trans_t *tp, /* transaction pointer */ xfs_buf_t *bp, /* allocation group header buffer */ int fields) /* bitmask of fields to log */ { int first; /* first byte number */ int last; /* last byte number */ static const short offsets[] = { /* field starting offsets */ /* keep in sync with bit definitions */ offsetof(xfs_agi_t, agi_magicnum), offsetof(xfs_agi_t, agi_versionnum), offsetof(xfs_agi_t, agi_seqno), offsetof(xfs_agi_t, agi_length), offsetof(xfs_agi_t, agi_count), offsetof(xfs_agi_t, agi_root), offsetof(xfs_agi_t, agi_level), offsetof(xfs_agi_t, agi_freecount), offsetof(xfs_agi_t, agi_newino), offsetof(xfs_agi_t, agi_dirino), offsetof(xfs_agi_t, agi_unlinked), offsetof(xfs_agi_t, agi_free_root), offsetof(xfs_agi_t, agi_free_level), sizeof(xfs_agi_t) }; #ifdef DEBUG xfs_agi_t *agi; /* allocation group header */ agi = XFS_BUF_TO_AGI(bp); ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); #endif xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGI_BUF); /* * Compute byte offsets for the first and last fields in the first * region and log the agi buffer. This only logs up through * agi_unlinked. */ if (fields & XFS_AGI_ALL_BITS_R1) { xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS_R1, &first, &last); xfs_trans_log_buf(tp, bp, first, last); } /* * Mask off the bits in the first region and calculate the first and * last field offsets for any bits in the second region. */ fields &= ~XFS_AGI_ALL_BITS_R1; if (fields) { xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS_R2, &first, &last); xfs_trans_log_buf(tp, bp, first, last); } } #ifdef DEBUG STATIC void xfs_check_agi_unlinked( struct xfs_agi *agi) { int i; for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) ASSERT(agi->agi_unlinked[i]); } #else #define xfs_check_agi_unlinked(agi) #endif static bool xfs_agi_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_agi *agi = XFS_BUF_TO_AGI(bp); if (xfs_sb_version_hascrc(&mp->m_sb)) { if (!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(XFS_BUF_TO_AGI(bp)->agi_lsn))) return false; } /* * Validate the magic number of the agi block. */ if (agi->agi_magicnum != cpu_to_be32(XFS_AGI_MAGIC)) return false; if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) return false; if (be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS) return false; /* * during growfs operations, the perag is not fully initialised, * so we can't use it for any useful checking. growfs ensures we can't * use it by using uncached buffers that don't have the perag attached * so we can detect and avoid this problem. */ if (bp->b_pag && be32_to_cpu(agi->agi_seqno) != bp->b_pag->pag_agno) return false; xfs_check_agi_unlinked(agi); return true; } static void xfs_agi_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; if (xfs_sb_version_hascrc(&mp->m_sb) && !xfs_buf_verify_cksum(bp, XFS_AGI_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (XFS_TEST_ERROR(!xfs_agi_verify(bp), mp, XFS_ERRTAG_IALLOC_READ_AGI, XFS_RANDOM_IALLOC_READ_AGI)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void xfs_agi_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; if (!xfs_agi_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) XFS_BUF_TO_AGI(bp)->agi_lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_AGI_CRC_OFF); } const struct xfs_buf_ops xfs_agi_buf_ops = { .name = "xfs_agi", .verify_read = xfs_agi_read_verify, .verify_write = xfs_agi_write_verify, }; /* * Read in the allocation group header (inode allocation section) */ int xfs_read_agi( struct xfs_mount *mp, /* file system mount structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ struct xfs_buf **bpp) /* allocation group hdr buf */ { int error; trace_xfs_read_agi(mp, agno); ASSERT(agno != NULLAGNUMBER); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops); if (error) return error; xfs_buf_set_ref(*bpp, XFS_AGI_REF); return 0; } int xfs_ialloc_read_agi( struct xfs_mount *mp, /* file system mount structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ struct xfs_buf **bpp) /* allocation group hdr buf */ { struct xfs_agi *agi; /* allocation group header */ struct xfs_perag *pag; /* per allocation group data */ int error; trace_xfs_ialloc_read_agi(mp, agno); error = xfs_read_agi(mp, tp, agno, bpp); if (error) return error; agi = XFS_BUF_TO_AGI(*bpp); pag = xfs_perag_get(mp, agno); if (!pag->pagi_init) { pag->pagi_freecount = be32_to_cpu(agi->agi_freecount); pag->pagi_count = be32_to_cpu(agi->agi_count); pag->pagi_init = 1; } /* * It's possible for these to be out of sync if * we are in the middle of a forced shutdown. */ ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) || XFS_FORCED_SHUTDOWN(mp)); xfs_perag_put(pag); return 0; } /* * Read in the agi to initialise the per-ag data in the mount structure */ int xfs_ialloc_pagi_init( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ xfs_agnumber_t agno) /* allocation group number */ { xfs_buf_t *bp = NULL; int error; error = xfs_ialloc_read_agi(mp, tp, agno, &bp); if (error) return error; if (bp) xfs_trans_brelse(tp, bp); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_ialloc.h0000644000000000000000000001271313063067171016261 0ustar /* * Copyright (c) 2000,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_IALLOC_H__ #define __XFS_IALLOC_H__ struct xfs_buf; struct xfs_dinode; struct xfs_imap; struct xfs_mount; struct xfs_trans; struct xfs_btree_cur; /* Move inodes in clusters of this size */ #define XFS_INODE_BIG_CLUSTER_SIZE 8192 struct xfs_icluster { bool deleted; /* record is deleted */ xfs_ino_t first_ino; /* first inode number */ uint64_t alloc; /* inode phys. allocation bitmap for * sparse chunks */ }; /* Calculate and return the number of filesystem blocks per inode cluster */ static inline int xfs_icluster_size_fsb( struct xfs_mount *mp) { if (mp->m_sb.sb_blocksize >= mp->m_inode_cluster_size) return 1; return mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog; } /* * Make an inode pointer out of the buffer/offset. */ static inline struct xfs_dinode * xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) { return xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog); } /* * Allocate an inode on disk. * Mode is used to tell whether the new inode will need space, and whether * it is a directory. * * To work within the constraint of one allocation per transaction, * xfs_dialloc() is designed to be called twice if it has to do an * allocation to make more free inodes. If an inode is * available without an allocation, agbp would be set to the current * agbp and alloc_done set to false. * If an allocation needed to be done, agbp would be set to the * inode header of the allocation group and alloc_done set to true. * The caller should then commit the current transaction and allocate a new * transaction. xfs_dialloc() should then be called again with * the agbp value returned from the previous call. * * Once we successfully pick an inode its number is returned and the * on-disk data structures are updated. The inode itself is not read * in, since doing so would break ordering constraints with xfs_reclaim. * * *agbp should be set to NULL on the first call, *alloc_done set to FALSE. */ int /* error */ xfs_dialloc( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t parent, /* parent inode (directory) */ umode_t mode, /* mode bits for new inode */ int okalloc, /* ok to allocate more space */ struct xfs_buf **agbp, /* buf for a.g. inode header */ xfs_ino_t *inop); /* inode number allocated */ /* * Free disk inode. Carefully avoids touching the incore inode, all * manipulations incore are the caller's responsibility. * The on-disk inode is not changed by this operation, only the * btree (free inode mask) is changed. */ int /* error */ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ struct xfs_defer_ops *dfops, /* extents to free */ struct xfs_icluster *ifree); /* cluster info if deleted */ /* * Return the location of the inode in imap, for mapping it into a buffer. */ int xfs_imap( struct xfs_mount *mp, /* file system mount structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t ino, /* inode to locate */ struct xfs_imap *imap, /* location map structure */ uint flags); /* flags for inode btree lookup */ /* * Compute and fill in value of m_in_maxlevels. */ void xfs_ialloc_compute_maxlevels( struct xfs_mount *mp); /* file system mount structure */ /* * Log specified fields for the ag hdr (inode section) */ void xfs_ialloc_log_agi( struct xfs_trans *tp, /* transaction pointer */ struct xfs_buf *bp, /* allocation group header buffer */ int fields); /* bitmask of fields to log */ /* * Read in the allocation group header (inode allocation section) */ int /* error */ xfs_ialloc_read_agi( struct xfs_mount *mp, /* file system mount structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ struct xfs_buf **bpp); /* allocation group hdr buf */ /* * Read in the allocation group header to initialise the per-ag data * in the mount structure */ int xfs_ialloc_pagi_init( struct xfs_mount *mp, /* file system mount structure */ struct xfs_trans *tp, /* transaction pointer */ xfs_agnumber_t agno); /* allocation group number */ /* * Lookup a record by ino in the btree given by cur. */ int xfs_inobt_lookup(struct xfs_btree_cur *cur, xfs_agino_t ino, xfs_lookup_t dir, int *stat); /* * Get the data from the pointed-to record. */ int xfs_inobt_get_rec(struct xfs_btree_cur *cur, xfs_inobt_rec_incore_t *rec, int *stat); /* * Inode chunk initialisation routine */ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp, struct list_head *buffer_list, int icount, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_agblock_t length, unsigned int gen); int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **bpp); #endif /* __XFS_IALLOC_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_ialloc_btree.c0000644000000000000000000003025113063067171017432 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_ialloc.h" #include "xfs_ialloc_btree.h" #include "xfs_alloc.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_rmap.h" STATIC int xfs_inobt_get_minrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_inobt_mnr[level != 0]; } STATIC struct xfs_btree_cur * xfs_inobt_dup_cursor( struct xfs_btree_cur *cur) { return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agbp, cur->bc_private.a.agno, cur->bc_btnum); } STATIC void xfs_inobt_set_root( struct xfs_btree_cur *cur, union xfs_btree_ptr *nptr, int inc) /* level change */ { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); agi->agi_root = nptr->s; be32_add_cpu(&agi->agi_level, inc); xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); } STATIC void xfs_finobt_set_root( struct xfs_btree_cur *cur, union xfs_btree_ptr *nptr, int inc) /* level change */ { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); agi->agi_free_root = nptr->s; be32_add_cpu(&agi->agi_free_level, inc); xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL); } STATIC int xfs_inobt_alloc_block( struct xfs_btree_cur *cur, union xfs_btree_ptr *start, union xfs_btree_ptr *new, int *stat) { xfs_alloc_arg_t args; /* block allocation args */ int error; /* error return value */ xfs_agblock_t sbno = be32_to_cpu(start->s); XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); memset(&args, 0, sizeof(args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INOBT); args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); args.minlen = 1; args.maxlen = 1; args.prod = 1; args.type = XFS_ALLOCTYPE_NEAR_BNO; error = xfs_alloc_vextent(&args); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } if (args.fsbno == NULLFSBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } ASSERT(args.len == 1); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno)); *stat = 1; return 0; } STATIC int xfs_inobt_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { struct xfs_owner_info oinfo; xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT); return xfs_free_extent(cur->bc_tp, XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1, &oinfo, XFS_AG_RESV_NONE); } STATIC int xfs_inobt_get_maxrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_inobt_mxr[level != 0]; } STATIC void xfs_inobt_init_key_from_rec( union xfs_btree_key *key, union xfs_btree_rec *rec) { key->inobt.ir_startino = rec->inobt.ir_startino; } STATIC void xfs_inobt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) { rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) { rec->inobt.ir_u.sp.ir_holemask = cpu_to_be16(cur->bc_rec.i.ir_holemask); rec->inobt.ir_u.sp.ir_count = cur->bc_rec.i.ir_count; rec->inobt.ir_u.sp.ir_freecount = cur->bc_rec.i.ir_freecount; } else { /* ir_holemask/ir_count not supported on-disk */ rec->inobt.ir_u.f.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); } rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); } /* * initial value of ptr for lookup */ STATIC void xfs_inobt_init_ptr_from_cur( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); ptr->s = agi->agi_root; } STATIC void xfs_finobt_init_ptr_from_cur( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); ptr->s = agi->agi_free_root; } STATIC __int64_t xfs_inobt_key_diff( struct xfs_btree_cur *cur, union xfs_btree_key *key) { return (__int64_t)be32_to_cpu(key->inobt.ir_startino) - cur->bc_rec.i.ir_startino; } static int xfs_inobt_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); unsigned int level; /* * During growfs operations, we can't verify the exact owner as the * perag is not fully initialised and hence not attached to the buffer. * * Similarly, during log recovery we will have a perag structure * attached, but the agi information will not yet have been initialised * from the on disk AGI. We don't currently use any of this information, * but beware of the landmine (i.e. need to check pag->pagi_init) if we * ever do. */ switch (block->bb_magic) { case cpu_to_be32(XFS_IBT_CRC_MAGIC): case cpu_to_be32(XFS_FIBT_CRC_MAGIC): if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; /* fall through */ case cpu_to_be32(XFS_IBT_MAGIC): case cpu_to_be32(XFS_FIBT_MAGIC): break; default: return 0; } /* level verification */ level = be16_to_cpu(block->bb_level); if (level >= mp->m_in_maxlevels) return false; return xfs_btree_sblock_verify(bp, mp->m_inobt_mxr[level != 0]); } static void xfs_inobt_read_verify( struct xfs_buf *bp) { if (!xfs_btree_sblock_verify_crc(bp)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_inobt_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_verifier_error(bp); } } static void xfs_inobt_write_verify( struct xfs_buf *bp) { if (!xfs_inobt_verify(bp)) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } xfs_btree_sblock_calc_crc(bp); } const struct xfs_buf_ops xfs_inobt_buf_ops = { .name = "xfs_inobt", .verify_read = xfs_inobt_read_verify, .verify_write = xfs_inobt_write_verify, }; #if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_inobt_keys_inorder( struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2) { return be32_to_cpu(k1->inobt.ir_startino) < be32_to_cpu(k2->inobt.ir_startino); } STATIC int xfs_inobt_recs_inorder( struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2) { return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <= be32_to_cpu(r2->inobt.ir_startino); } #endif /* DEBUG */ static const struct xfs_btree_ops xfs_inobt_ops = { .rec_len = sizeof(xfs_inobt_rec_t), .key_len = sizeof(xfs_inobt_key_t), .dup_cursor = xfs_inobt_dup_cursor, .set_root = xfs_inobt_set_root, .alloc_block = xfs_inobt_alloc_block, .free_block = xfs_inobt_free_block, .get_minrecs = xfs_inobt_get_minrecs, .get_maxrecs = xfs_inobt_get_maxrecs, .init_key_from_rec = xfs_inobt_init_key_from_rec, .init_rec_from_cur = xfs_inobt_init_rec_from_cur, .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, .buf_ops = &xfs_inobt_buf_ops, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_inobt_keys_inorder, .recs_inorder = xfs_inobt_recs_inorder, #endif }; static const struct xfs_btree_ops xfs_finobt_ops = { .rec_len = sizeof(xfs_inobt_rec_t), .key_len = sizeof(xfs_inobt_key_t), .dup_cursor = xfs_inobt_dup_cursor, .set_root = xfs_finobt_set_root, .alloc_block = xfs_inobt_alloc_block, .free_block = xfs_inobt_free_block, .get_minrecs = xfs_inobt_get_minrecs, .get_maxrecs = xfs_inobt_get_maxrecs, .init_key_from_rec = xfs_inobt_init_key_from_rec, .init_rec_from_cur = xfs_inobt_init_rec_from_cur, .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, .buf_ops = &xfs_inobt_buf_ops, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_inobt_keys_inorder, .recs_inorder = xfs_inobt_recs_inorder, #endif }; /* * Allocate a new inode btree cursor. */ struct xfs_btree_cur * /* new inode btree cursor */ xfs_inobt_init_cursor( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ struct xfs_buf *agbp, /* buffer for agi structure */ xfs_agnumber_t agno, /* allocation group number */ xfs_btnum_t btnum) /* ialloc or free ino btree */ { struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); struct xfs_btree_cur *cur; cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); cur->bc_tp = tp; cur->bc_mp = mp; cur->bc_btnum = btnum; if (btnum == XFS_BTNUM_INO) { cur->bc_nlevels = be32_to_cpu(agi->agi_level); cur->bc_ops = &xfs_inobt_ops; } else { cur->bc_nlevels = be32_to_cpu(agi->agi_free_level); cur->bc_ops = &xfs_finobt_ops; } cur->bc_blocklog = mp->m_sb.sb_blocklog; if (xfs_sb_version_hascrc(&mp->m_sb)) cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; return cur; } /* * Calculate number of records in an inobt btree block. */ int xfs_inobt_maxrecs( struct xfs_mount *mp, int blocklen, int leaf) { blocklen -= XFS_INOBT_BLOCK_LEN(mp); if (leaf) return blocklen / sizeof(xfs_inobt_rec_t); return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t)); } /* * Convert the inode record holemask to an inode allocation bitmap. The inode * allocation bitmap is inode granularity and specifies whether an inode is * physically allocated on disk (not whether the inode is considered allocated * or free by the fs). * * A bit value of 1 means the inode is allocated, a value of 0 means it is free. */ uint64_t xfs_inobt_irec_to_allocmask( struct xfs_inobt_rec_incore *rec) { uint64_t bitmap = 0; uint64_t inodespbit; int nextbit; uint allocbitmap; /* * The holemask has 16-bits for a 64 inode record. Therefore each * holemask bit represents multiple inodes. Create a mask of bits to set * in the allocmask for each holemask bit. */ inodespbit = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1; /* * Allocated inodes are represented by 0 bits in holemask. Invert the 0 * bits to 1 and convert to a uint so we can use xfs_next_bit(). Mask * anything beyond the 16 holemask bits since this casts to a larger * type. */ allocbitmap = ~rec->ir_holemask & ((1 << XFS_INOBT_HOLEMASK_BITS) - 1); /* * allocbitmap is the inverted holemask so every set bit represents * allocated inodes. To expand from 16-bit holemask granularity to * 64-bit (e.g., bit-per-inode), set inodespbit bits in the target * bitmap for every holemask bit. */ nextbit = xfs_next_bit(&allocbitmap, 1, 0); while (nextbit != -1) { ASSERT(nextbit < (sizeof(rec->ir_holemask) * NBBY)); bitmap |= (inodespbit << (nextbit * XFS_INODES_PER_HOLEMASK_BIT)); nextbit = xfs_next_bit(&allocbitmap, 1, nextbit + 1); } return bitmap; } #if defined(DEBUG) || defined(XFS_WARN) /* * Verify that an in-core inode record has a valid inode count. */ int xfs_inobt_rec_check_count( struct xfs_mount *mp, struct xfs_inobt_rec_incore *rec) { int inocount = 0; int nextbit = 0; uint64_t allocbmap; int wordsz; wordsz = sizeof(allocbmap) / sizeof(unsigned int); allocbmap = xfs_inobt_irec_to_allocmask(rec); nextbit = xfs_next_bit((uint *) &allocbmap, wordsz, nextbit); while (nextbit != -1) { inocount++; nextbit = xfs_next_bit((uint *) &allocbmap, wordsz, nextbit + 1); } if (inocount != rec->ir_count) return -EFSCORRUPTED; return 0; } #endif /* DEBUG */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_ialloc_btree.h0000644000000000000000000000447013063067171017443 0ustar /* * Copyright (c) 2000,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_IALLOC_BTREE_H__ #define __XFS_IALLOC_BTREE_H__ /* * Inode map on-disk structures */ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; /* * Btree block header size depends on a superblock flag. */ #define XFS_INOBT_BLOCK_LEN(mp) \ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN) /* * Record, key, and pointer address macros for btree blocks. * * (note that some of these may appear unused, but they are used in userspace) */ #define XFS_INOBT_REC_ADDR(mp, block, index) \ ((xfs_inobt_rec_t *) \ ((char *)(block) + \ XFS_INOBT_BLOCK_LEN(mp) + \ (((index) - 1) * sizeof(xfs_inobt_rec_t)))) #define XFS_INOBT_KEY_ADDR(mp, block, index) \ ((xfs_inobt_key_t *) \ ((char *)(block) + \ XFS_INOBT_BLOCK_LEN(mp) + \ ((index) - 1) * sizeof(xfs_inobt_key_t))) #define XFS_INOBT_PTR_ADDR(mp, block, index, maxrecs) \ ((xfs_inobt_ptr_t *) \ ((char *)(block) + \ XFS_INOBT_BLOCK_LEN(mp) + \ (maxrecs) * sizeof(xfs_inobt_key_t) + \ ((index) - 1) * sizeof(xfs_inobt_ptr_t))) extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t, xfs_btnum_t); extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); /* ir_holemask to inode allocation bitmap conversion */ uint64_t xfs_inobt_irec_to_allocmask(struct xfs_inobt_rec_incore *); #if defined(DEBUG) || defined(XFS_WARN) int xfs_inobt_rec_check_count(struct xfs_mount *, struct xfs_inobt_rec_incore *); #else #define xfs_inobt_rec_check_count(mp, rec) 0 #endif /* DEBUG */ #endif /* __XFS_IALLOC_BTREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_inode_buf.c0000644000000000000000000004125513063067171016746 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_ialloc.h" /* * Check that none of the inode's in the buffer have a next * unlinked field of 0. */ #if defined(DEBUG) void xfs_inobp_check( xfs_mount_t *mp, xfs_buf_t *bp) { int i; int j; xfs_dinode_t *dip; j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog; for (i = 0; i < j; i++) { dip = xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize); if (!dip->di_next_unlinked) { xfs_alert(mp, "Detected bogus zero next_unlinked field in inode %d buffer 0x%llx.", i, (long long)bp->b_bn); } } } #endif bool xfs_dinode_good_version( struct xfs_mount *mp, __u8 version) { if (xfs_sb_version_hascrc(&mp->m_sb)) return version == 3; return version == 1 || version == 2; } /* * If we are doing readahead on an inode buffer, we might be in log recovery * reading an inode allocation buffer that hasn't yet been replayed, and hence * has not had the inode cores stamped into it. Hence for readahead, the buffer * may be potentially invalid. * * If the readahead buffer is invalid, we need to mark it with an error and * clear the DONE status of the buffer so that a followup read will re-read it * from disk. We don't report the error otherwise to avoid warnings during log * recovery and we don't get unnecssary panics on debug kernels. We use EIO here * because all we want to do is say readahead failed; there is no-one to report * the error to, so this will distinguish it from a non-ra verifier failure. * Changes to this readahead error behavour also need to be reflected in * xfs_dquot_buf_readahead_verify(). */ static void xfs_inode_buf_verify( struct xfs_buf *bp, bool readahead) { struct xfs_mount *mp = bp->b_target->bt_mount; int i; int ni; /* * Validate the magic number and version of every inode in the buffer */ ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock; for (i = 0; i < ni; i++) { int di_ok; xfs_dinode_t *dip; dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog)); di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) && xfs_dinode_good_version(mp, dip->di_version); if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, XFS_RANDOM_ITOBP_INOTOBP))) { if (readahead) { bp->b_flags &= ~XBF_DONE; xfs_buf_ioerror(bp, -EIO); return; } xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); #ifdef DEBUG xfs_alert(mp, "bad inode magic/vsn daddr %lld #%d (magic=%x)", (unsigned long long)bp->b_bn, i, be16_to_cpu(dip->di_magic)); #endif } } xfs_inobp_check(mp, bp); } static void xfs_inode_buf_read_verify( struct xfs_buf *bp) { xfs_inode_buf_verify(bp, false); } static void xfs_inode_buf_readahead_verify( struct xfs_buf *bp) { xfs_inode_buf_verify(bp, true); } static void xfs_inode_buf_write_verify( struct xfs_buf *bp) { xfs_inode_buf_verify(bp, false); } const struct xfs_buf_ops xfs_inode_buf_ops = { .name = "xfs_inode", .verify_read = xfs_inode_buf_read_verify, .verify_write = xfs_inode_buf_write_verify, }; const struct xfs_buf_ops xfs_inode_buf_ra_ops = { .name = "xxfs_inode_ra", .verify_read = xfs_inode_buf_readahead_verify, .verify_write = xfs_inode_buf_write_verify, }; /* * This routine is called to map an inode to the buffer containing the on-disk * version of the inode. It returns a pointer to the buffer containing the * on-disk inode in the bpp parameter, and in the dipp parameter it returns a * pointer to the on-disk inode within that buffer. * * If a non-zero error is returned, then the contents of bpp and dipp are * undefined. */ int xfs_imap_to_bp( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_imap *imap, struct xfs_dinode **dipp, struct xfs_buf **bpp, uint buf_flags, uint iget_flags) { struct xfs_buf *bp; int error; buf_flags |= XBF_UNMAPPED; error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno, (int)imap->im_len, buf_flags, &bp, &xfs_inode_buf_ops); if (error) { if (error == -EAGAIN) { ASSERT(buf_flags & XBF_TRYLOCK); return error; } if (error == -EFSCORRUPTED && (iget_flags & XFS_IGET_UNTRUSTED)) return -EINVAL; xfs_warn(mp, "%s: xfs_trans_read_buf() returned error %d.", __func__, error); return error; } *bpp = bp; *dipp = xfs_buf_offset(bp, imap->im_boffset); return 0; } void xfs_inode_from_disk( struct xfs_inode *ip, struct xfs_dinode *from) { struct xfs_icdinode *to = &ip->i_d; struct inode *inode = VFS_I(ip); /* * Convert v1 inodes immediately to v2 inode format as this is the * minimum inode version format we support in the rest of the code. */ to->di_version = from->di_version; if (to->di_version == 1) { set_nlink(inode, be16_to_cpu(from->di_onlink)); to->di_projid_lo = 0; to->di_projid_hi = 0; to->di_version = 2; } else { set_nlink(inode, be32_to_cpu(from->di_nlink)); to->di_projid_lo = be16_to_cpu(from->di_projid_lo); to->di_projid_hi = be16_to_cpu(from->di_projid_hi); } to->di_format = from->di_format; to->di_uid = be32_to_cpu(from->di_uid); to->di_gid = be32_to_cpu(from->di_gid); to->di_flushiter = be16_to_cpu(from->di_flushiter); /* * Time is signed, so need to convert to signed 32 bit before * storing in inode timestamp which may be 64 bit. Otherwise * a time before epoch is converted to a time long after epoch * on 64 bit systems. */ inode->i_atime.tv_sec = (int)be32_to_cpu(from->di_atime.t_sec); inode->i_atime.tv_nsec = (int)be32_to_cpu(from->di_atime.t_nsec); inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec); inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec); inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec); inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec); inode->i_generation = be32_to_cpu(from->di_gen); inode->i_mode = be16_to_cpu(from->di_mode); to->di_size = be64_to_cpu(from->di_size); to->di_nblocks = be64_to_cpu(from->di_nblocks); to->di_extsize = be32_to_cpu(from->di_extsize); to->di_nextents = be32_to_cpu(from->di_nextents); to->di_anextents = be16_to_cpu(from->di_anextents); to->di_forkoff = from->di_forkoff; to->di_aformat = from->di_aformat; to->di_dmevmask = be32_to_cpu(from->di_dmevmask); to->di_dmstate = be16_to_cpu(from->di_dmstate); to->di_flags = be16_to_cpu(from->di_flags); if (to->di_version == 3) { inode->i_version = be64_to_cpu(from->di_changecount); to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); to->di_flags2 = be64_to_cpu(from->di_flags2); to->di_cowextsize = be32_to_cpu(from->di_cowextsize); } } void xfs_inode_to_disk( struct xfs_inode *ip, struct xfs_dinode *to, xfs_lsn_t lsn) { struct xfs_icdinode *from = &ip->i_d; struct inode *inode = VFS_I(ip); to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); to->di_onlink = 0; to->di_version = from->di_version; to->di_format = from->di_format; to->di_uid = cpu_to_be32(from->di_uid); to->di_gid = cpu_to_be32(from->di_gid); to->di_projid_lo = cpu_to_be16(from->di_projid_lo); to->di_projid_hi = cpu_to_be16(from->di_projid_hi); memset(to->di_pad, 0, sizeof(to->di_pad)); to->di_atime.t_sec = cpu_to_be32(inode->i_atime.tv_sec); to->di_atime.t_nsec = cpu_to_be32(inode->i_atime.tv_nsec); to->di_mtime.t_sec = cpu_to_be32(inode->i_mtime.tv_sec); to->di_mtime.t_nsec = cpu_to_be32(inode->i_mtime.tv_nsec); to->di_ctime.t_sec = cpu_to_be32(inode->i_ctime.tv_sec); to->di_ctime.t_nsec = cpu_to_be32(inode->i_ctime.tv_nsec); to->di_nlink = cpu_to_be32(inode->i_nlink); to->di_gen = cpu_to_be32(inode->i_generation); to->di_mode = cpu_to_be16(inode->i_mode); to->di_size = cpu_to_be64(from->di_size); to->di_nblocks = cpu_to_be64(from->di_nblocks); to->di_extsize = cpu_to_be32(from->di_extsize); to->di_nextents = cpu_to_be32(from->di_nextents); to->di_anextents = cpu_to_be16(from->di_anextents); to->di_forkoff = from->di_forkoff; to->di_aformat = from->di_aformat; to->di_dmevmask = cpu_to_be32(from->di_dmevmask); to->di_dmstate = cpu_to_be16(from->di_dmstate); to->di_flags = cpu_to_be16(from->di_flags); if (from->di_version == 3) { to->di_changecount = cpu_to_be64(inode->i_version); to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); to->di_flags2 = cpu_to_be64(from->di_flags2); to->di_cowextsize = cpu_to_be32(from->di_cowextsize); to->di_ino = cpu_to_be64(ip->i_ino); to->di_lsn = cpu_to_be64(lsn); memset(to->di_pad2, 0, sizeof(to->di_pad2)); uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid); to->di_flushiter = 0; } else { to->di_flushiter = cpu_to_be16(from->di_flushiter); } } void xfs_log_dinode_to_disk( struct xfs_log_dinode *from, struct xfs_dinode *to) { to->di_magic = cpu_to_be16(from->di_magic); to->di_mode = cpu_to_be16(from->di_mode); to->di_version = from->di_version; to->di_format = from->di_format; to->di_onlink = 0; to->di_uid = cpu_to_be32(from->di_uid); to->di_gid = cpu_to_be32(from->di_gid); to->di_nlink = cpu_to_be32(from->di_nlink); to->di_projid_lo = cpu_to_be16(from->di_projid_lo); to->di_projid_hi = cpu_to_be16(from->di_projid_hi); memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec); to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec); to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec); to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec); to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec); to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec); to->di_size = cpu_to_be64(from->di_size); to->di_nblocks = cpu_to_be64(from->di_nblocks); to->di_extsize = cpu_to_be32(from->di_extsize); to->di_nextents = cpu_to_be32(from->di_nextents); to->di_anextents = cpu_to_be16(from->di_anextents); to->di_forkoff = from->di_forkoff; to->di_aformat = from->di_aformat; to->di_dmevmask = cpu_to_be32(from->di_dmevmask); to->di_dmstate = cpu_to_be16(from->di_dmstate); to->di_flags = cpu_to_be16(from->di_flags); to->di_gen = cpu_to_be32(from->di_gen); if (from->di_version == 3) { to->di_changecount = cpu_to_be64(from->di_changecount); to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); to->di_flags2 = cpu_to_be64(from->di_flags2); to->di_cowextsize = cpu_to_be32(from->di_cowextsize); to->di_ino = cpu_to_be64(from->di_ino); to->di_lsn = cpu_to_be64(from->di_lsn); memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2)); uuid_copy(&to->di_uuid, &from->di_uuid); to->di_flushiter = 0; } else { to->di_flushiter = cpu_to_be16(from->di_flushiter); } } bool xfs_dinode_verify( struct xfs_mount *mp, xfs_ino_t ino, struct xfs_dinode *dip) { uint16_t flags; uint64_t flags2; if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) return false; /* only version 3 or greater inodes are extensively verified here */ if (dip->di_version < 3) return true; if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize, XFS_DINODE_CRC_OFF)) return false; if (be64_to_cpu(dip->di_ino) != ino) return false; if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid)) return false; flags = be16_to_cpu(dip->di_flags); flags2 = be64_to_cpu(dip->di_flags2); /* don't allow reflink/cowextsize if we don't have reflink */ if ((flags2 & (XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)) && !xfs_sb_version_hasreflink(&mp->m_sb)) return false; /* don't let reflink and realtime mix */ if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & XFS_DIFLAG_REALTIME)) return false; /* don't let reflink and dax mix */ if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags2 & XFS_DIFLAG2_DAX)) return false; return true; } void xfs_dinode_calc_crc( struct xfs_mount *mp, struct xfs_dinode *dip) { __uint32_t crc; if (dip->di_version < 3) return; ASSERT(xfs_sb_version_hascrc(&mp->m_sb)); crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize, XFS_DINODE_CRC_OFF); dip->di_crc = xfs_end_cksum(crc); } /* * Read the disk inode attributes into the in-core inode structure. * * For version 5 superblocks, if we are initialising a new inode and we are not * utilising the XFS_MOUNT_IKEEP inode cluster mode, we can simple build the new * inode core with a random generation number. If we are keeping inodes around, * we need to read the inode cluster to get the existing generation number off * disk. Further, if we are using version 4 superblocks (i.e. v1/v2 inode * format) then log recovery is dependent on the di_flushiter field being * initialised from the current on-disk value and hence we must also read the * inode off disk. */ int xfs_iread( xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *ip, uint iget_flags) { xfs_buf_t *bp; xfs_dinode_t *dip; int error; /* * Fill in the location information in the in-core inode. */ error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags); if (error) return error; /* shortcut IO on inode allocation if possible */ if ((iget_flags & XFS_IGET_CREATE) && xfs_sb_version_hascrc(&mp->m_sb) && !(mp->m_flags & XFS_MOUNT_IKEEP)) { /* initialise the on-disk inode core */ memset(&ip->i_d, 0, sizeof(ip->i_d)); VFS_I(ip)->i_generation = prandom_u32(); if (xfs_sb_version_hascrc(&mp->m_sb)) ip->i_d.di_version = 3; else ip->i_d.di_version = 2; return 0; } /* * Get pointers to the on-disk inode and the buffer containing it. */ error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &bp, 0, iget_flags); if (error) return error; /* even unallocated inodes are verified */ if (!xfs_dinode_verify(mp, ip->i_ino, dip)) { xfs_alert(mp, "%s: validation failed for inode %lld failed", __func__, ip->i_ino); XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, dip); error = -EFSCORRUPTED; goto out_brelse; } /* * If the on-disk inode is already linked to a directory * entry, copy all of the inode into the in-core inode. * xfs_iformat_fork() handles copying in the inode format * specific information. * Otherwise, just get the truly permanent information. */ if (dip->di_mode) { xfs_inode_from_disk(ip, dip); error = xfs_iformat_fork(ip, dip); if (error) { #ifdef DEBUG xfs_alert(mp, "%s: xfs_iformat() returned error %d", __func__, error); #endif /* DEBUG */ goto out_brelse; } } else { /* * Partial initialisation of the in-core inode. Just the bits * that xfs_ialloc won't overwrite or relies on being correct. */ ip->i_d.di_version = dip->di_version; VFS_I(ip)->i_generation = be32_to_cpu(dip->di_gen); ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter); /* * Make sure to pull in the mode here as well in * case the inode is released without being used. * This ensures that xfs_inactive() will see that * the inode is already free and not try to mess * with the uninitialized part of it. */ VFS_I(ip)->i_mode = 0; } ASSERT(ip->i_d.di_version >= 2); ip->i_delayed_blks = 0; /* * Mark the buffer containing the inode as something to keep * around for a while. This helps to keep recently accessed * meta-data in-core longer. */ xfs_buf_set_ref(bp, XFS_INO_REF); /* * Use xfs_trans_brelse() to release the buffer containing the on-disk * inode, because it was acquired with xfs_trans_read_buf() in * xfs_imap_to_bp() above. If tp is NULL, this is just a normal * brelse(). If we're within a transaction, then xfs_trans_brelse() * will only release the buffer if it is not dirty within the * transaction. It will be OK to release the buffer in this case, * because inodes on disk are never destroyed and we will be locking the * new in-core inode before putting it in the cache where other * processes can find it. Thus we don't have to worry about the inode * being changed just because we released the buffer. */ out_brelse: xfs_trans_brelse(tp, bp); return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_inode_buf.h0000644000000000000000000000663413063067171016755 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_INODE_BUF_H__ #define __XFS_INODE_BUF_H__ struct xfs_inode; struct xfs_dinode; /* * In memory representation of the XFS inode. This is held in the in-core struct * xfs_inode and represents the current on disk values but the structure is not * in on-disk format. That is, this structure is always translated to on-disk * format specific structures at the appropriate time. */ struct xfs_icdinode { __int8_t di_version; /* inode version */ __int8_t di_format; /* format of di_c data */ __uint16_t di_flushiter; /* incremented on flush */ __uint32_t di_uid; /* owner's user id */ __uint32_t di_gid; /* owner's group id */ __uint16_t di_projid_lo; /* lower part of owner's project id */ __uint16_t di_projid_hi; /* higher part of owner's project id */ xfs_fsize_t di_size; /* number of bytes in file */ xfs_rfsblock_t di_nblocks; /* # of direct & btree blocks used */ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */ xfs_extnum_t di_nextents; /* number of extents in data fork */ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/ __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */ __int8_t di_aformat; /* format of attr fork's data */ __uint32_t di_dmevmask; /* DMIG event mask */ __uint16_t di_dmstate; /* DMIG state info */ __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ __uint64_t di_flags2; /* more random flags */ __uint32_t di_cowextsize; /* basic cow extent size for file */ xfs_ictimestamp_t di_crtime; /* time created */ }; /* * Inode location information. Stored in the inode and passed to * xfs_imap_to_bp() to get a buffer and dinode for a given inode. */ struct xfs_imap { xfs_daddr_t im_blkno; /* starting BB of inode chunk */ unsigned short im_len; /* length in BBs of inode chunk */ unsigned short im_boffset; /* inode offset in block in bytes */ }; int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, struct xfs_imap *, struct xfs_dinode **, struct xfs_buf **, uint, uint); int xfs_iread(struct xfs_mount *, struct xfs_trans *, struct xfs_inode *, uint); void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *); void xfs_inode_to_disk(struct xfs_inode *ip, struct xfs_dinode *to, xfs_lsn_t lsn); void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from); void xfs_log_dinode_to_disk(struct xfs_log_dinode *from, struct xfs_dinode *to); bool xfs_dinode_verify(struct xfs_mount *mp, xfs_ino_t ino, struct xfs_dinode *dip); bool xfs_dinode_good_version(struct xfs_mount *mp, __u8 version); #if defined(DEBUG) void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); #else #define xfs_inobp_check(mp, bp) #endif /* DEBUG */ #endif /* __XFS_INODE_BUF_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_inode_fork.c0000644000000000000000000016224113063067170017131 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_bmap_btree.h" #include "xfs_bmap.h" #include "xfs_trace.h" #include "xfs_attr_sf.h" #include "xfs_da_format.h" kmem_zone_t *xfs_ifork_zone; STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int); STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int); STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int); #ifdef DEBUG /* * Make sure that the extents in the given memory buffer * are valid. */ void xfs_validate_extents( xfs_ifork_t *ifp, int nrecs, xfs_exntfmt_t fmt) { xfs_bmbt_irec_t irec; xfs_bmbt_rec_host_t rec; int i; for (i = 0; i < nrecs; i++) { xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i); rec.l0 = get_unaligned(&ep->l0); rec.l1 = get_unaligned(&ep->l1); xfs_bmbt_get_all(&rec, &irec); if (fmt == XFS_EXTFMT_NOSTATE) ASSERT(irec.br_state == XFS_EXT_NORM); } } #else /* DEBUG */ #define xfs_validate_extents(ifp, nrecs, fmt) #endif /* DEBUG */ /* * Move inode type and inode format specific information from the * on-disk inode to the in-core inode. For fifos, devs, and sockets * this means set if_rdev to the proper value. For files, directories, * and symlinks this means to bring in the in-line data or extent * pointers. For a file in B-tree format, only the root is immediately * brought in-core. The rest will be in-lined in if_extents when it * is first referenced (see xfs_iread_extents()). */ int xfs_iformat_fork( xfs_inode_t *ip, xfs_dinode_t *dip) { xfs_attr_shortform_t *atp; int size; int error = 0; xfs_fsize_t di_size; if (unlikely(be32_to_cpu(dip->di_nextents) + be16_to_cpu(dip->di_anextents) > be64_to_cpu(dip->di_nblocks))) { xfs_warn(ip->i_mount, "corrupt dinode %Lu, extent total = %d, nblocks = %Lu.", (unsigned long long)ip->i_ino, (int)(be32_to_cpu(dip->di_nextents) + be16_to_cpu(dip->di_anextents)), (unsigned long long) be64_to_cpu(dip->di_nblocks)); XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } if (unlikely(dip->di_forkoff > ip->i_mount->m_sb.sb_inodesize)) { xfs_warn(ip->i_mount, "corrupt dinode %Lu, forkoff = 0x%x.", (unsigned long long)ip->i_ino, dip->di_forkoff); XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && !ip->i_mount->m_rtdev_targp)) { xfs_warn(ip->i_mount, "corrupt dinode %Lu, has realtime flag set.", ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(realtime)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } if (unlikely(xfs_is_reflink_inode(ip) && (VFS_I(ip)->i_mode & S_IFMT) != S_IFREG)) { xfs_warn(ip->i_mount, "corrupt dinode %llu, wrong file type for reflink.", ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(reflink)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } if (unlikely(xfs_is_reflink_inode(ip) && (ip->i_d.di_flags & XFS_DIFLAG_REALTIME))) { xfs_warn(ip->i_mount, "corrupt dinode %llu, has reflink+realtime flag set.", ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(reflink)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } switch (VFS_I(ip)->i_mode & S_IFMT) { case S_IFIFO: case S_IFCHR: case S_IFBLK: case S_IFSOCK: if (unlikely(dip->di_format != XFS_DINODE_FMT_DEV)) { XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } ip->i_d.di_size = 0; ip->i_df.if_u2.if_rdev = xfs_dinode_get_rdev(dip); break; case S_IFREG: case S_IFLNK: case S_IFDIR: switch (dip->di_format) { case XFS_DINODE_FMT_LOCAL: /* * no local regular files yet */ if (unlikely(S_ISREG(be16_to_cpu(dip->di_mode)))) { xfs_warn(ip->i_mount, "corrupt inode %Lu (local format for regular file).", (unsigned long long) ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(4)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } di_size = be64_to_cpu(dip->di_size); if (unlikely(di_size < 0 || di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) { xfs_warn(ip->i_mount, "corrupt inode %Lu (bad size %Ld for local inode).", (unsigned long long) ip->i_ino, (long long) di_size); XFS_CORRUPTION_ERROR("xfs_iformat(5)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } size = (int)di_size; error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, size); break; case XFS_DINODE_FMT_EXTENTS: error = xfs_iformat_extents(ip, dip, XFS_DATA_FORK); break; case XFS_DINODE_FMT_BTREE: error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK); break; default: XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW, ip->i_mount); return -EFSCORRUPTED; } break; default: XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW, ip->i_mount); return -EFSCORRUPTED; } if (error) return error; if (xfs_is_reflink_inode(ip)) { ASSERT(ip->i_cowfp == NULL); xfs_ifork_init_cow(ip); } if (!XFS_DFORK_Q(dip)) return 0; ASSERT(ip->i_afp == NULL); ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP | KM_NOFS); switch (dip->di_aformat) { case XFS_DINODE_FMT_LOCAL: atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); size = be16_to_cpu(atp->hdr.totsize); if (unlikely(size < sizeof(struct xfs_attr_sf_hdr))) { xfs_warn(ip->i_mount, "corrupt inode %Lu (bad attr fork size %Ld).", (unsigned long long) ip->i_ino, (long long) size); XFS_CORRUPTION_ERROR("xfs_iformat(8)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); error = -EFSCORRUPTED; break; } error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size); break; case XFS_DINODE_FMT_EXTENTS: error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK); break; case XFS_DINODE_FMT_BTREE: error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK); break; default: error = -EFSCORRUPTED; break; } if (error) { kmem_zone_free(xfs_ifork_zone, ip->i_afp); ip->i_afp = NULL; if (ip->i_cowfp) kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); ip->i_cowfp = NULL; xfs_idestroy_fork(ip, XFS_DATA_FORK); } return error; } void xfs_init_local_fork( struct xfs_inode *ip, int whichfork, const void *data, int size) { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); int mem_size = size, real_size = 0; bool zero_terminate; /* * If we are using the local fork to store a symlink body we need to * zero-terminate it so that we can pass it back to the VFS directly. * Overallocate the in-memory fork by one for that and add a zero * to terminate it below. */ zero_terminate = S_ISLNK(VFS_I(ip)->i_mode); if (zero_terminate) mem_size++; if (size == 0) ifp->if_u1.if_data = NULL; else if (mem_size <= sizeof(ifp->if_u2.if_inline_data)) ifp->if_u1.if_data = ifp->if_u2.if_inline_data; else { real_size = roundup(mem_size, 4); ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); } if (size) { memcpy(ifp->if_u1.if_data, data, size); if (zero_terminate) ifp->if_u1.if_data[size] = '\0'; } ifp->if_bytes = size; ifp->if_real_bytes = real_size; ifp->if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT); ifp->if_flags |= XFS_IFINLINE; } /* * The file is in-lined in the on-disk inode. * If it fits into if_inline_data, then copy * it there, otherwise allocate a buffer for it * and copy the data there. Either way, set * if_data to point at the data. * If we allocate a buffer for the data, make * sure that its size is a multiple of 4 and * record the real size in i_real_bytes. */ STATIC int xfs_iformat_local( xfs_inode_t *ip, xfs_dinode_t *dip, int whichfork, int size) { /* * If the size is unreasonable, then something * is wrong and we just bail out rather than crash in * kmem_alloc() or memcpy() below. */ if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { xfs_warn(ip->i_mount, "corrupt inode %Lu (bad size %d for local fork, size = %d).", (unsigned long long) ip->i_ino, size, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)); XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size); return 0; } /* * The file consists of a set of extents all * of which fit into the on-disk inode. * If there are few enough extents to fit into * the if_inline_ext, then copy them there. * Otherwise allocate a buffer for them and copy * them into it. Either way, set if_extents * to point at the extents. */ STATIC int xfs_iformat_extents( xfs_inode_t *ip, xfs_dinode_t *dip, int whichfork) { xfs_bmbt_rec_t *dp; xfs_ifork_t *ifp; int nex; int size; int i; ifp = XFS_IFORK_PTR(ip, whichfork); nex = XFS_DFORK_NEXTENTS(dip, whichfork); size = nex * (uint)sizeof(xfs_bmbt_rec_t); /* * If the number of extents is unreasonable, then something * is wrong and we just bail out rather than crash in * kmem_alloc() or memcpy() below. */ if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).", (unsigned long long) ip->i_ino, nex); XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); return -EFSCORRUPTED; } ifp->if_real_bytes = 0; if (nex == 0) ifp->if_u1.if_extents = NULL; else if (nex <= XFS_INLINE_EXTS) ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; else xfs_iext_add(ifp, 0, nex); ifp->if_bytes = size; if (size) { dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork); xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip)); for (i = 0; i < nex; i++, dp++) { xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i); ep->l0 = get_unaligned_be64(&dp->l0); ep->l1 = get_unaligned_be64(&dp->l1); } XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork); if (whichfork != XFS_DATA_FORK || XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE) if (unlikely(xfs_check_nostate_extents( ifp, 0, nex))) { XFS_ERROR_REPORT("xfs_iformat_extents(2)", XFS_ERRLEVEL_LOW, ip->i_mount); return -EFSCORRUPTED; } } ifp->if_flags |= XFS_IFEXTENTS; return 0; } /* * The file has too many extents to fit into * the inode, so they are in B-tree format. * Allocate a buffer for the root of the B-tree * and copy the root into it. The i_extents * field will remain NULL until all of the * extents are read in (when they are needed). */ STATIC int xfs_iformat_btree( xfs_inode_t *ip, xfs_dinode_t *dip, int whichfork) { struct xfs_mount *mp = ip->i_mount; xfs_bmdr_block_t *dfp; xfs_ifork_t *ifp; /* REFERENCED */ int nrecs; int size; ifp = XFS_IFORK_PTR(ip, whichfork); dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); size = XFS_BMAP_BROOT_SPACE(mp, dfp); nrecs = be16_to_cpu(dfp->bb_numrecs); /* * blow out if -- fork has less extents than can fit in * fork (fork shouldn't be a btree format), root btree * block has more records than can fit into the fork, * or the number of extents is greater than the number of * blocks. */ if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= XFS_IFORK_MAXEXT(ip, whichfork) || XFS_BMDR_SPACE_CALC(nrecs) > XFS_DFORK_SIZE(dip, mp, whichfork) || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) { xfs_warn(mp, "corrupt inode %Lu (btree).", (unsigned long long) ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW, mp, dip); return -EFSCORRUPTED; } ifp->if_broot_bytes = size; ifp->if_broot = kmem_alloc(size, KM_SLEEP | KM_NOFS); ASSERT(ifp->if_broot != NULL); /* * Copy and convert from the on-disk structure * to the in-memory structure. */ xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork), ifp->if_broot, size); ifp->if_flags &= ~XFS_IFEXTENTS; ifp->if_flags |= XFS_IFBROOT; return 0; } /* * Read in extents from a btree-format inode. * Allocate and fill in if_extents. Real work is done in xfs_bmap.c. */ int xfs_iread_extents( xfs_trans_t *tp, xfs_inode_t *ip, int whichfork) { int error; xfs_ifork_t *ifp; xfs_extnum_t nextents; ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) { XFS_ERROR_REPORT("xfs_iread_extents", XFS_ERRLEVEL_LOW, ip->i_mount); return -EFSCORRUPTED; } nextents = XFS_IFORK_NEXTENTS(ip, whichfork); ifp = XFS_IFORK_PTR(ip, whichfork); /* * We know that the size is valid (it's checked in iformat_btree) */ ifp->if_bytes = ifp->if_real_bytes = 0; ifp->if_flags |= XFS_IFEXTENTS; xfs_iext_add(ifp, 0, nextents); error = xfs_bmap_read_extents(tp, ip, whichfork); if (error) { xfs_iext_destroy(ifp); ifp->if_flags &= ~XFS_IFEXTENTS; return error; } xfs_validate_extents(ifp, nextents, XFS_EXTFMT_INODE(ip)); return 0; } /* * Reallocate the space for if_broot based on the number of records * being added or deleted as indicated in rec_diff. Move the records * and pointers in if_broot to fit the new size. When shrinking this * will eliminate holes between the records and pointers created by * the caller. When growing this will create holes to be filled in * by the caller. * * The caller must not request to add more records than would fit in * the on-disk inode root. If the if_broot is currently NULL, then * if we are adding records, one will be allocated. The caller must also * not request that the number of records go below zero, although * it can go to zero. * * ip -- the inode whose if_broot area is changing * ext_diff -- the change in the number of records, positive or negative, * requested for the if_broot array. */ void xfs_iroot_realloc( xfs_inode_t *ip, int rec_diff, int whichfork) { struct xfs_mount *mp = ip->i_mount; int cur_max; xfs_ifork_t *ifp; struct xfs_btree_block *new_broot; int new_max; size_t new_size; char *np; char *op; /* * Handle the degenerate case quietly. */ if (rec_diff == 0) { return; } ifp = XFS_IFORK_PTR(ip, whichfork); if (rec_diff > 0) { /* * If there wasn't any memory allocated before, just * allocate it now and get out. */ if (ifp->if_broot_bytes == 0) { new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff); ifp->if_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS); ifp->if_broot_bytes = (int)new_size; return; } /* * If there is already an existing if_broot, then we need * to realloc() it and shift the pointers to their new * location. The records don't change location because * they are kept butted up against the btree block header. */ cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); new_max = cur_max + rec_diff; new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max); ifp->if_broot = kmem_realloc(ifp->if_broot, new_size, KM_SLEEP | KM_NOFS); op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, ifp->if_broot_bytes); np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, (int)new_size); ifp->if_broot_bytes = (int)new_size; ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= XFS_IFORK_SIZE(ip, whichfork)); memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t)); return; } /* * rec_diff is less than 0. In this case, we are shrinking the * if_broot buffer. It must already exist. If we go to zero * records, just get rid of the root and clear the status bit. */ ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0)); cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); new_max = cur_max + rec_diff; ASSERT(new_max >= 0); if (new_max > 0) new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max); else new_size = 0; if (new_size > 0) { new_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS); /* * First copy over the btree block header. */ memcpy(new_broot, ifp->if_broot, XFS_BMBT_BLOCK_LEN(ip->i_mount)); } else { new_broot = NULL; ifp->if_flags &= ~XFS_IFBROOT; } /* * Only copy the records and pointers if there are any. */ if (new_max > 0) { /* * First copy the records. */ op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1); np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1); memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t)); /* * Then copy the pointers. */ op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, ifp->if_broot_bytes); np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1, (int)new_size); memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t)); } kmem_free(ifp->if_broot); ifp->if_broot = new_broot; ifp->if_broot_bytes = (int)new_size; if (ifp->if_broot) ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= XFS_IFORK_SIZE(ip, whichfork)); return; } /* * This is called when the amount of space needed for if_data * is increased or decreased. The change in size is indicated by * the number of bytes that need to be added or deleted in the * byte_diff parameter. * * If the amount of space needed has decreased below the size of the * inline buffer, then switch to using the inline buffer. Otherwise, * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer * to what is needed. * * ip -- the inode whose if_data area is changing * byte_diff -- the change in the number of bytes, positive or negative, * requested for the if_data array. */ void xfs_idata_realloc( xfs_inode_t *ip, int byte_diff, int whichfork) { xfs_ifork_t *ifp; int new_size; int real_size; if (byte_diff == 0) { return; } ifp = XFS_IFORK_PTR(ip, whichfork); new_size = (int)ifp->if_bytes + byte_diff; ASSERT(new_size >= 0); if (new_size == 0) { if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { kmem_free(ifp->if_u1.if_data); } ifp->if_u1.if_data = NULL; real_size = 0; } else if (new_size <= sizeof(ifp->if_u2.if_inline_data)) { /* * If the valid extents/data can fit in if_inline_ext/data, * copy them from the malloc'd vector and free it. */ if (ifp->if_u1.if_data == NULL) { ifp->if_u1.if_data = ifp->if_u2.if_inline_data; } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { ASSERT(ifp->if_real_bytes != 0); memcpy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data, new_size); kmem_free(ifp->if_u1.if_data); ifp->if_u1.if_data = ifp->if_u2.if_inline_data; } real_size = 0; } else { /* * Stuck with malloc/realloc. * For inline data, the underlying buffer must be * a multiple of 4 bytes in size so that it can be * logged and stay on word boundaries. We enforce * that here. */ real_size = roundup(new_size, 4); if (ifp->if_u1.if_data == NULL) { ASSERT(ifp->if_real_bytes == 0); ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { /* * Only do the realloc if the underlying size * is really changing. */ if (ifp->if_real_bytes != real_size) { ifp->if_u1.if_data = kmem_realloc(ifp->if_u1.if_data, real_size, KM_SLEEP | KM_NOFS); } } else { ASSERT(ifp->if_real_bytes == 0); ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); memcpy(ifp->if_u1.if_data, ifp->if_u2.if_inline_data, ifp->if_bytes); } } ifp->if_real_bytes = real_size; ifp->if_bytes = new_size; ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); } void xfs_idestroy_fork( xfs_inode_t *ip, int whichfork) { xfs_ifork_t *ifp; ifp = XFS_IFORK_PTR(ip, whichfork); if (ifp->if_broot != NULL) { kmem_free(ifp->if_broot); ifp->if_broot = NULL; } /* * If the format is local, then we can't have an extents * array so just look for an inline data array. If we're * not local then we may or may not have an extents list, * so check and free it up if we do. */ if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) && (ifp->if_u1.if_data != NULL)) { ASSERT(ifp->if_real_bytes != 0); kmem_free(ifp->if_u1.if_data); ifp->if_u1.if_data = NULL; ifp->if_real_bytes = 0; } } else if ((ifp->if_flags & XFS_IFEXTENTS) && ((ifp->if_flags & XFS_IFEXTIREC) || ((ifp->if_u1.if_extents != NULL) && (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext)))) { ASSERT(ifp->if_real_bytes != 0); xfs_iext_destroy(ifp); } ASSERT(ifp->if_u1.if_extents == NULL || ifp->if_u1.if_extents == ifp->if_u2.if_inline_ext); ASSERT(ifp->if_real_bytes == 0); if (whichfork == XFS_ATTR_FORK) { kmem_zone_free(xfs_ifork_zone, ip->i_afp); ip->i_afp = NULL; } else if (whichfork == XFS_COW_FORK) { kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); ip->i_cowfp = NULL; } } /* * Convert in-core extents to on-disk form * * For either the data or attr fork in extent format, we need to endian convert * the in-core extent as we place them into the on-disk inode. * * In the case of the data fork, the in-core and on-disk fork sizes can be * different due to delayed allocation extents. We only copy on-disk extents * here, so callers must always use the physical fork size to determine the * size of the buffer passed to this routine. We will return the size actually * used. */ int xfs_iextents_copy( xfs_inode_t *ip, xfs_bmbt_rec_t *dp, int whichfork) { int copied; int i; xfs_ifork_t *ifp; int nrecs; xfs_fsblock_t start_block; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); ASSERT(ifp->if_bytes > 0); nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); XFS_BMAP_TRACE_EXLIST(ip, nrecs, whichfork); ASSERT(nrecs > 0); /* * There are some delayed allocation extents in the * inode, so copy the extents one at a time and skip * the delayed ones. There must be at least one * non-delayed extent. */ copied = 0; for (i = 0; i < nrecs; i++) { xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i); start_block = xfs_bmbt_get_startblock(ep); if (isnullstartblock(start_block)) { /* * It's a delayed allocation extent, so skip it. */ continue; } /* Translate to on disk format */ put_unaligned_be64(ep->l0, &dp->l0); put_unaligned_be64(ep->l1, &dp->l1); dp++; copied++; } ASSERT(copied != 0); xfs_validate_extents(ifp, copied, XFS_EXTFMT_INODE(ip)); return (copied * (uint)sizeof(xfs_bmbt_rec_t)); } /* * Each of the following cases stores data into the same region * of the on-disk inode, so only one of them can be valid at * any given time. While it is possible to have conflicting formats * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is * in EXTENTS format, this can only happen when the fork has * changed formats after being modified but before being flushed. * In these cases, the format always takes precedence, because the * format indicates the current state of the fork. */ void xfs_iflush_fork( xfs_inode_t *ip, xfs_dinode_t *dip, xfs_inode_log_item_t *iip, int whichfork) { char *cp; xfs_ifork_t *ifp; xfs_mount_t *mp; static const short brootflag[2] = { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT }; static const short dataflag[2] = { XFS_ILOG_DDATA, XFS_ILOG_ADATA }; static const short extflag[2] = { XFS_ILOG_DEXT, XFS_ILOG_AEXT }; if (!iip) return; ifp = XFS_IFORK_PTR(ip, whichfork); /* * This can happen if we gave up in iformat in an error path, * for the attribute fork. */ if (!ifp) { ASSERT(whichfork == XFS_ATTR_FORK); return; } cp = XFS_DFORK_PTR(dip, whichfork); mp = ip->i_mount; switch (XFS_IFORK_FORMAT(ip, whichfork)) { case XFS_DINODE_FMT_LOCAL: if ((iip->ili_fields & dataflag[whichfork]) && (ifp->if_bytes > 0)) { ASSERT(ifp->if_u1.if_data != NULL); ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes); } break; case XFS_DINODE_FMT_EXTENTS: ASSERT((ifp->if_flags & XFS_IFEXTENTS) || !(iip->ili_fields & extflag[whichfork])); if ((iip->ili_fields & extflag[whichfork]) && (ifp->if_bytes > 0)) { ASSERT(xfs_iext_get_ext(ifp, 0)); ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0); (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp, whichfork); } break; case XFS_DINODE_FMT_BTREE: if ((iip->ili_fields & brootflag[whichfork]) && (ifp->if_broot_bytes > 0)) { ASSERT(ifp->if_broot != NULL); ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= XFS_IFORK_SIZE(ip, whichfork)); xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes, (xfs_bmdr_block_t *)cp, XFS_DFORK_SIZE(dip, mp, whichfork)); } break; case XFS_DINODE_FMT_DEV: if (iip->ili_fields & XFS_ILOG_DEV) { ASSERT(whichfork == XFS_DATA_FORK); xfs_dinode_put_rdev(dip, ip->i_df.if_u2.if_rdev); } break; case XFS_DINODE_FMT_UUID: if (iip->ili_fields & XFS_ILOG_UUID) { ASSERT(whichfork == XFS_DATA_FORK); memcpy(XFS_DFORK_DPTR(dip), &ip->i_df.if_u2.if_uuid, sizeof(uuid_t)); } break; default: ASSERT(0); break; } } /* * Return a pointer to the extent record at file index idx. */ xfs_bmbt_rec_host_t * xfs_iext_get_ext( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_extnum_t idx) /* index of target extent */ { ASSERT(idx >= 0); ASSERT(idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)); if ((ifp->if_flags & XFS_IFEXTIREC) && (idx == 0)) { return ifp->if_u1.if_ext_irec->er_extbuf; } else if (ifp->if_flags & XFS_IFEXTIREC) { xfs_ext_irec_t *erp; /* irec pointer */ int erp_idx = 0; /* irec index */ xfs_extnum_t page_idx = idx; /* ext index in target list */ erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 0); return &erp->er_extbuf[page_idx]; } else if (ifp->if_bytes) { return &ifp->if_u1.if_extents[idx]; } else { return NULL; } } /* Convert bmap state flags to an inode fork. */ struct xfs_ifork * xfs_iext_state_to_fork( struct xfs_inode *ip, int state) { if (state & BMAP_COWFORK) return ip->i_cowfp; else if (state & BMAP_ATTRFORK) return ip->i_afp; return &ip->i_df; } /* * Insert new item(s) into the extent records for incore inode * fork 'ifp'. 'count' new items are inserted at index 'idx'. */ void xfs_iext_insert( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* starting index of new items */ xfs_extnum_t count, /* number of inserted items */ xfs_bmbt_irec_t *new, /* items to insert */ int state) /* type of extent conversion */ { xfs_ifork_t *ifp = xfs_iext_state_to_fork(ip, state); xfs_extnum_t i; /* extent record index */ trace_xfs_iext_insert(ip, idx, new, state, _RET_IP_); ASSERT(ifp->if_flags & XFS_IFEXTENTS); xfs_iext_add(ifp, idx, count); for (i = idx; i < idx + count; i++, new++) xfs_bmbt_set_all(xfs_iext_get_ext(ifp, i), new); } /* * This is called when the amount of space required for incore file * extents needs to be increased. The ext_diff parameter stores the * number of new extents being added and the idx parameter contains * the extent index where the new extents will be added. If the new * extents are being appended, then we just need to (re)allocate and * initialize the space. Otherwise, if the new extents are being * inserted into the middle of the existing entries, a bit more work * is required to make room for the new extents to be inserted. The * caller is responsible for filling in the new extent entries upon * return. */ void xfs_iext_add( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_extnum_t idx, /* index to begin adding exts */ int ext_diff) /* number of extents to add */ { int byte_diff; /* new bytes being added */ int new_size; /* size of extents after adding */ xfs_extnum_t nextents; /* number of extents in file */ nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ASSERT((idx >= 0) && (idx <= nextents)); byte_diff = ext_diff * sizeof(xfs_bmbt_rec_t); new_size = ifp->if_bytes + byte_diff; /* * If the new number of extents (nextents + ext_diff) * fits inside the inode, then continue to use the inline * extent buffer. */ if (nextents + ext_diff <= XFS_INLINE_EXTS) { if (idx < nextents) { memmove(&ifp->if_u2.if_inline_ext[idx + ext_diff], &ifp->if_u2.if_inline_ext[idx], (nextents - idx) * sizeof(xfs_bmbt_rec_t)); memset(&ifp->if_u2.if_inline_ext[idx], 0, byte_diff); } ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; ifp->if_real_bytes = 0; } /* * Otherwise use a linear (direct) extent list. * If the extents are currently inside the inode, * xfs_iext_realloc_direct will switch us from * inline to direct extent allocation mode. */ else if (nextents + ext_diff <= XFS_LINEAR_EXTS) { xfs_iext_realloc_direct(ifp, new_size); if (idx < nextents) { memmove(&ifp->if_u1.if_extents[idx + ext_diff], &ifp->if_u1.if_extents[idx], (nextents - idx) * sizeof(xfs_bmbt_rec_t)); memset(&ifp->if_u1.if_extents[idx], 0, byte_diff); } } /* Indirection array */ else { xfs_ext_irec_t *erp; int erp_idx = 0; int page_idx = idx; ASSERT(nextents + ext_diff > XFS_LINEAR_EXTS); if (ifp->if_flags & XFS_IFEXTIREC) { erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 1); } else { xfs_iext_irec_init(ifp); ASSERT(ifp->if_flags & XFS_IFEXTIREC); erp = ifp->if_u1.if_ext_irec; } /* Extents fit in target extent page */ if (erp && erp->er_extcount + ext_diff <= XFS_LINEAR_EXTS) { if (page_idx < erp->er_extcount) { memmove(&erp->er_extbuf[page_idx + ext_diff], &erp->er_extbuf[page_idx], (erp->er_extcount - page_idx) * sizeof(xfs_bmbt_rec_t)); memset(&erp->er_extbuf[page_idx], 0, byte_diff); } erp->er_extcount += ext_diff; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff); } /* Insert a new extent page */ else if (erp) { xfs_iext_add_indirect_multi(ifp, erp_idx, page_idx, ext_diff); } /* * If extent(s) are being appended to the last page in * the indirection array and the new extent(s) don't fit * in the page, then erp is NULL and erp_idx is set to * the next index needed in the indirection array. */ else { uint count = ext_diff; while (count) { erp = xfs_iext_irec_new(ifp, erp_idx); erp->er_extcount = min(count, XFS_LINEAR_EXTS); count -= erp->er_extcount; if (count) erp_idx++; } } } ifp->if_bytes = new_size; } /* * This is called when incore extents are being added to the indirection * array and the new extents do not fit in the target extent list. The * erp_idx parameter contains the irec index for the target extent list * in the indirection array, and the idx parameter contains the extent * index within the list. The number of extents being added is stored * in the count parameter. * * |-------| |-------| * | | | | idx - number of extents before idx * | idx | | count | * | | | | count - number of extents being inserted at idx * |-------| |-------| * | count | | nex2 | nex2 - number of extents after idx + count * |-------| |-------| */ void xfs_iext_add_indirect_multi( xfs_ifork_t *ifp, /* inode fork pointer */ int erp_idx, /* target extent irec index */ xfs_extnum_t idx, /* index within target list */ int count) /* new extents being added */ { int byte_diff; /* new bytes being added */ xfs_ext_irec_t *erp; /* pointer to irec entry */ xfs_extnum_t ext_diff; /* number of extents to add */ xfs_extnum_t ext_cnt; /* new extents still needed */ xfs_extnum_t nex2; /* extents after idx + count */ xfs_bmbt_rec_t *nex2_ep = NULL; /* temp list for nex2 extents */ int nlists; /* number of irec's (lists) */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); erp = &ifp->if_u1.if_ext_irec[erp_idx]; nex2 = erp->er_extcount - idx; nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; /* * Save second part of target extent list * (all extents past */ if (nex2) { byte_diff = nex2 * sizeof(xfs_bmbt_rec_t); nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_NOFS); memmove(nex2_ep, &erp->er_extbuf[idx], byte_diff); erp->er_extcount -= nex2; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -nex2); memset(&erp->er_extbuf[idx], 0, byte_diff); } /* * Add the new extents to the end of the target * list, then allocate new irec record(s) and * extent buffer(s) as needed to store the rest * of the new extents. */ ext_cnt = count; ext_diff = MIN(ext_cnt, (int)XFS_LINEAR_EXTS - erp->er_extcount); if (ext_diff) { erp->er_extcount += ext_diff; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff); ext_cnt -= ext_diff; } while (ext_cnt) { erp_idx++; erp = xfs_iext_irec_new(ifp, erp_idx); ext_diff = MIN(ext_cnt, (int)XFS_LINEAR_EXTS); erp->er_extcount = ext_diff; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff); ext_cnt -= ext_diff; } /* Add nex2 extents back to indirection array */ if (nex2) { xfs_extnum_t ext_avail; int i; byte_diff = nex2 * sizeof(xfs_bmbt_rec_t); ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; i = 0; /* * If nex2 extents fit in the current page, append * nex2_ep after the new extents. */ if (nex2 <= ext_avail) { i = erp->er_extcount; } /* * Otherwise, check if space is available in the * next page. */ else if ((erp_idx < nlists - 1) && (nex2 <= (ext_avail = XFS_LINEAR_EXTS - ifp->if_u1.if_ext_irec[erp_idx+1].er_extcount))) { erp_idx++; erp++; /* Create a hole for nex2 extents */ memmove(&erp->er_extbuf[nex2], erp->er_extbuf, erp->er_extcount * sizeof(xfs_bmbt_rec_t)); } /* * Final choice, create a new extent page for * nex2 extents. */ else { erp_idx++; erp = xfs_iext_irec_new(ifp, erp_idx); } memmove(&erp->er_extbuf[i], nex2_ep, byte_diff); kmem_free(nex2_ep); erp->er_extcount += nex2; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, nex2); } } /* * This is called when the amount of space required for incore file * extents needs to be decreased. The ext_diff parameter stores the * number of extents to be removed and the idx parameter contains * the extent index where the extents will be removed from. * * If the amount of space needed has decreased below the linear * limit, XFS_IEXT_BUFSZ, then switch to using the contiguous * extent array. Otherwise, use kmem_realloc() to adjust the * size to what is needed. */ void xfs_iext_remove( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* index to begin removing exts */ int ext_diff, /* number of extents to remove */ int state) /* type of extent conversion */ { xfs_ifork_t *ifp = xfs_iext_state_to_fork(ip, state); xfs_extnum_t nextents; /* number of extents in file */ int new_size; /* size of extents after removal */ trace_xfs_iext_remove(ip, idx, state, _RET_IP_); ASSERT(ext_diff > 0); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); new_size = (nextents - ext_diff) * sizeof(xfs_bmbt_rec_t); if (new_size == 0) { xfs_iext_destroy(ifp); } else if (ifp->if_flags & XFS_IFEXTIREC) { xfs_iext_remove_indirect(ifp, idx, ext_diff); } else if (ifp->if_real_bytes) { xfs_iext_remove_direct(ifp, idx, ext_diff); } else { xfs_iext_remove_inline(ifp, idx, ext_diff); } ifp->if_bytes = new_size; } /* * This removes ext_diff extents from the inline buffer, beginning * at extent index idx. */ void xfs_iext_remove_inline( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_extnum_t idx, /* index to begin removing exts */ int ext_diff) /* number of extents to remove */ { int nextents; /* number of extents in file */ ASSERT(!(ifp->if_flags & XFS_IFEXTIREC)); ASSERT(idx < XFS_INLINE_EXTS); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ASSERT(((nextents - ext_diff) > 0) && (nextents - ext_diff) < XFS_INLINE_EXTS); if (idx + ext_diff < nextents) { memmove(&ifp->if_u2.if_inline_ext[idx], &ifp->if_u2.if_inline_ext[idx + ext_diff], (nextents - (idx + ext_diff)) * sizeof(xfs_bmbt_rec_t)); memset(&ifp->if_u2.if_inline_ext[nextents - ext_diff], 0, ext_diff * sizeof(xfs_bmbt_rec_t)); } else { memset(&ifp->if_u2.if_inline_ext[idx], 0, ext_diff * sizeof(xfs_bmbt_rec_t)); } } /* * This removes ext_diff extents from a linear (direct) extent list, * beginning at extent index idx. If the extents are being removed * from the end of the list (ie. truncate) then we just need to re- * allocate the list to remove the extra space. Otherwise, if the * extents are being removed from the middle of the existing extent * entries, then we first need to move the extent records beginning * at idx + ext_diff up in the list to overwrite the records being * removed, then remove the extra space via kmem_realloc. */ void xfs_iext_remove_direct( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_extnum_t idx, /* index to begin removing exts */ int ext_diff) /* number of extents to remove */ { xfs_extnum_t nextents; /* number of extents in file */ int new_size; /* size of extents after removal */ ASSERT(!(ifp->if_flags & XFS_IFEXTIREC)); new_size = ifp->if_bytes - (ext_diff * sizeof(xfs_bmbt_rec_t)); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); if (new_size == 0) { xfs_iext_destroy(ifp); return; } /* Move extents up in the list (if needed) */ if (idx + ext_diff < nextents) { memmove(&ifp->if_u1.if_extents[idx], &ifp->if_u1.if_extents[idx + ext_diff], (nextents - (idx + ext_diff)) * sizeof(xfs_bmbt_rec_t)); } memset(&ifp->if_u1.if_extents[nextents - ext_diff], 0, ext_diff * sizeof(xfs_bmbt_rec_t)); /* * Reallocate the direct extent list. If the extents * will fit inside the inode then xfs_iext_realloc_direct * will switch from direct to inline extent allocation * mode for us. */ xfs_iext_realloc_direct(ifp, new_size); ifp->if_bytes = new_size; } /* * This is called when incore extents are being removed from the * indirection array and the extents being removed span multiple extent * buffers. The idx parameter contains the file extent index where we * want to begin removing extents, and the count parameter contains * how many extents need to be removed. * * |-------| |-------| * | nex1 | | | nex1 - number of extents before idx * |-------| | count | * | | | | count - number of extents being removed at idx * | count | |-------| * | | | nex2 | nex2 - number of extents after idx + count * |-------| |-------| */ void xfs_iext_remove_indirect( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_extnum_t idx, /* index to begin removing extents */ int count) /* number of extents to remove */ { xfs_ext_irec_t *erp; /* indirection array pointer */ int erp_idx = 0; /* indirection array index */ xfs_extnum_t ext_cnt; /* extents left to remove */ xfs_extnum_t ext_diff; /* extents to remove in current list */ xfs_extnum_t nex1; /* number of extents before idx */ xfs_extnum_t nex2; /* extents after idx + count */ int page_idx = idx; /* index in target extent list */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 0); ASSERT(erp != NULL); nex1 = page_idx; ext_cnt = count; while (ext_cnt) { nex2 = MAX((erp->er_extcount - (nex1 + ext_cnt)), 0); ext_diff = MIN(ext_cnt, (erp->er_extcount - nex1)); /* * Check for deletion of entire list; * xfs_iext_irec_remove() updates extent offsets. */ if (ext_diff == erp->er_extcount) { xfs_iext_irec_remove(ifp, erp_idx); ext_cnt -= ext_diff; nex1 = 0; if (ext_cnt) { ASSERT(erp_idx < ifp->if_real_bytes / XFS_IEXT_BUFSZ); erp = &ifp->if_u1.if_ext_irec[erp_idx]; nex1 = 0; continue; } else { break; } } /* Move extents up (if needed) */ if (nex2) { memmove(&erp->er_extbuf[nex1], &erp->er_extbuf[nex1 + ext_diff], nex2 * sizeof(xfs_bmbt_rec_t)); } /* Zero out rest of page */ memset(&erp->er_extbuf[nex1 + nex2], 0, (XFS_IEXT_BUFSZ - ((nex1 + nex2) * sizeof(xfs_bmbt_rec_t)))); /* Update remaining counters */ erp->er_extcount -= ext_diff; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -ext_diff); ext_cnt -= ext_diff; nex1 = 0; erp_idx++; erp++; } ifp->if_bytes -= count * sizeof(xfs_bmbt_rec_t); xfs_iext_irec_compact(ifp); } /* * Create, destroy, or resize a linear (direct) block of extents. */ void xfs_iext_realloc_direct( xfs_ifork_t *ifp, /* inode fork pointer */ int new_size) /* new size of extents after adding */ { int rnew_size; /* real new size of extents */ rnew_size = new_size; ASSERT(!(ifp->if_flags & XFS_IFEXTIREC) || ((new_size >= 0) && (new_size <= XFS_IEXT_BUFSZ) && (new_size != ifp->if_real_bytes))); /* Free extent records */ if (new_size == 0) { xfs_iext_destroy(ifp); } /* Resize direct extent list and zero any new bytes */ else if (ifp->if_real_bytes) { /* Check if extents will fit inside the inode */ if (new_size <= XFS_INLINE_EXTS * sizeof(xfs_bmbt_rec_t)) { xfs_iext_direct_to_inline(ifp, new_size / (uint)sizeof(xfs_bmbt_rec_t)); ifp->if_bytes = new_size; return; } if (!is_power_of_2(new_size)){ rnew_size = roundup_pow_of_two(new_size); } if (rnew_size != ifp->if_real_bytes) { ifp->if_u1.if_extents = kmem_realloc(ifp->if_u1.if_extents, rnew_size, KM_NOFS); } if (rnew_size > ifp->if_real_bytes) { memset(&ifp->if_u1.if_extents[ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)], 0, rnew_size - ifp->if_real_bytes); } } /* Switch from the inline extent buffer to a direct extent list */ else { if (!is_power_of_2(new_size)) { rnew_size = roundup_pow_of_two(new_size); } xfs_iext_inline_to_direct(ifp, rnew_size); } ifp->if_real_bytes = rnew_size; ifp->if_bytes = new_size; } /* * Switch from linear (direct) extent records to inline buffer. */ void xfs_iext_direct_to_inline( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_extnum_t nextents) /* number of extents in file */ { ASSERT(ifp->if_flags & XFS_IFEXTENTS); ASSERT(nextents <= XFS_INLINE_EXTS); /* * The inline buffer was zeroed when we switched * from inline to direct extent allocation mode, * so we don't need to clear it here. */ memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, nextents * sizeof(xfs_bmbt_rec_t)); kmem_free(ifp->if_u1.if_extents); ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; ifp->if_real_bytes = 0; } /* * Switch from inline buffer to linear (direct) extent records. * new_size should already be rounded up to the next power of 2 * by the caller (when appropriate), so use new_size as it is. * However, since new_size may be rounded up, we can't update * if_bytes here. It is the caller's responsibility to update * if_bytes upon return. */ void xfs_iext_inline_to_direct( xfs_ifork_t *ifp, /* inode fork pointer */ int new_size) /* number of extents in file */ { ifp->if_u1.if_extents = kmem_alloc(new_size, KM_NOFS); memset(ifp->if_u1.if_extents, 0, new_size); if (ifp->if_bytes) { memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext, ifp->if_bytes); memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS * sizeof(xfs_bmbt_rec_t)); } ifp->if_real_bytes = new_size; } /* * Resize an extent indirection array to new_size bytes. */ STATIC void xfs_iext_realloc_indirect( xfs_ifork_t *ifp, /* inode fork pointer */ int new_size) /* new indirection array size */ { #ifdef DEBUG int nlists; /* number of irec's (ex lists) */ int size; /* current indirection array size */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; size = nlists * sizeof(xfs_ext_irec_t); ASSERT(ifp->if_real_bytes); ASSERT((new_size >= 0) && (new_size != size)); #endif if (new_size == 0) { xfs_iext_destroy(ifp); } else { ifp->if_u1.if_ext_irec = kmem_realloc(ifp->if_u1.if_ext_irec, new_size, KM_NOFS); } } /* * Switch from indirection array to linear (direct) extent allocations. */ STATIC void xfs_iext_indirect_to_direct( xfs_ifork_t *ifp) /* inode fork pointer */ { xfs_bmbt_rec_host_t *ep; /* extent record pointer */ xfs_extnum_t nextents; /* number of extents in file */ int size; /* size of file extents */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ASSERT(nextents <= XFS_LINEAR_EXTS); size = nextents * sizeof(xfs_bmbt_rec_t); xfs_iext_irec_compact_pages(ifp); ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); ep = ifp->if_u1.if_ext_irec->er_extbuf; kmem_free(ifp->if_u1.if_ext_irec); ifp->if_flags &= ~XFS_IFEXTIREC; ifp->if_u1.if_extents = ep; ifp->if_bytes = size; if (nextents < XFS_LINEAR_EXTS) { xfs_iext_realloc_direct(ifp, size); } } /* * Remove all records from the indirection array. */ STATIC void xfs_iext_irec_remove_all( struct xfs_ifork *ifp) { int nlists; int i; ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; for (i = 0; i < nlists; i++) kmem_free(ifp->if_u1.if_ext_irec[i].er_extbuf); kmem_free(ifp->if_u1.if_ext_irec); ifp->if_flags &= ~XFS_IFEXTIREC; } /* * Free incore file extents. */ void xfs_iext_destroy( xfs_ifork_t *ifp) /* inode fork pointer */ { if (ifp->if_flags & XFS_IFEXTIREC) { xfs_iext_irec_remove_all(ifp); } else if (ifp->if_real_bytes) { kmem_free(ifp->if_u1.if_extents); } else if (ifp->if_bytes) { memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS * sizeof(xfs_bmbt_rec_t)); } ifp->if_u1.if_extents = NULL; ifp->if_real_bytes = 0; ifp->if_bytes = 0; } /* * Return a pointer to the extent record for file system block bno. */ xfs_bmbt_rec_host_t * /* pointer to found extent record */ xfs_iext_bno_to_ext( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_fileoff_t bno, /* block number to search for */ xfs_extnum_t *idxp) /* index of target extent */ { xfs_bmbt_rec_host_t *base; /* pointer to first extent */ xfs_filblks_t blockcount = 0; /* number of blocks in extent */ xfs_bmbt_rec_host_t *ep = NULL; /* pointer to target extent */ xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ int high; /* upper boundary in search */ xfs_extnum_t idx = 0; /* index of target extent */ int low; /* lower boundary in search */ xfs_extnum_t nextents; /* number of file extents */ xfs_fileoff_t startoff = 0; /* start offset of extent */ nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); if (nextents == 0) { *idxp = 0; return NULL; } low = 0; if (ifp->if_flags & XFS_IFEXTIREC) { /* Find target extent list */ int erp_idx = 0; erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx); base = erp->er_extbuf; high = erp->er_extcount - 1; } else { base = ifp->if_u1.if_extents; high = nextents - 1; } /* Binary search extent records */ while (low <= high) { idx = (low + high) >> 1; ep = base + idx; startoff = xfs_bmbt_get_startoff(ep); blockcount = xfs_bmbt_get_blockcount(ep); if (bno < startoff) { high = idx - 1; } else if (bno >= startoff + blockcount) { low = idx + 1; } else { /* Convert back to file-based extent index */ if (ifp->if_flags & XFS_IFEXTIREC) { idx += erp->er_extoff; } *idxp = idx; return ep; } } /* Convert back to file-based extent index */ if (ifp->if_flags & XFS_IFEXTIREC) { idx += erp->er_extoff; } if (bno >= startoff + blockcount) { if (++idx == nextents) { ep = NULL; } else { ep = xfs_iext_get_ext(ifp, idx); } } *idxp = idx; return ep; } /* * Return a pointer to the indirection array entry containing the * extent record for filesystem block bno. Store the index of the * target irec in *erp_idxp. */ xfs_ext_irec_t * /* pointer to found extent record */ xfs_iext_bno_to_irec( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_fileoff_t bno, /* block number to search for */ int *erp_idxp) /* irec index of target ext list */ { xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ xfs_ext_irec_t *erp_next; /* next indirection array entry */ int erp_idx; /* indirection array index */ int nlists; /* number of extent irec's (lists) */ int high; /* binary search upper limit */ int low; /* binary search lower limit */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; erp_idx = 0; low = 0; high = nlists - 1; while (low <= high) { erp_idx = (low + high) >> 1; erp = &ifp->if_u1.if_ext_irec[erp_idx]; erp_next = erp_idx < nlists - 1 ? erp + 1 : NULL; if (bno < xfs_bmbt_get_startoff(erp->er_extbuf)) { high = erp_idx - 1; } else if (erp_next && bno >= xfs_bmbt_get_startoff(erp_next->er_extbuf)) { low = erp_idx + 1; } else { break; } } *erp_idxp = erp_idx; return erp; } /* * Return a pointer to the indirection array entry containing the * extent record at file extent index *idxp. Store the index of the * target irec in *erp_idxp and store the page index of the target * extent record in *idxp. */ xfs_ext_irec_t * xfs_iext_idx_to_irec( xfs_ifork_t *ifp, /* inode fork pointer */ xfs_extnum_t *idxp, /* extent index (file -> page) */ int *erp_idxp, /* pointer to target irec */ int realloc) /* new bytes were just added */ { xfs_ext_irec_t *prev; /* pointer to previous irec */ xfs_ext_irec_t *erp = NULL; /* pointer to current irec */ int erp_idx; /* indirection array index */ int nlists; /* number of irec's (ex lists) */ int high; /* binary search upper limit */ int low; /* binary search lower limit */ xfs_extnum_t page_idx = *idxp; /* extent index in target list */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); ASSERT(page_idx >= 0); ASSERT(page_idx <= ifp->if_bytes / sizeof(xfs_bmbt_rec_t)); ASSERT(page_idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t) || realloc); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; erp_idx = 0; low = 0; high = nlists - 1; /* Binary search extent irec's */ while (low <= high) { erp_idx = (low + high) >> 1; erp = &ifp->if_u1.if_ext_irec[erp_idx]; prev = erp_idx > 0 ? erp - 1 : NULL; if (page_idx < erp->er_extoff || (page_idx == erp->er_extoff && realloc && prev && prev->er_extcount < XFS_LINEAR_EXTS)) { high = erp_idx - 1; } else if (page_idx > erp->er_extoff + erp->er_extcount || (page_idx == erp->er_extoff + erp->er_extcount && !realloc)) { low = erp_idx + 1; } else if (page_idx == erp->er_extoff + erp->er_extcount && erp->er_extcount == XFS_LINEAR_EXTS) { ASSERT(realloc); page_idx = 0; erp_idx++; erp = erp_idx < nlists ? erp + 1 : NULL; break; } else { page_idx -= erp->er_extoff; break; } } *idxp = page_idx; *erp_idxp = erp_idx; return erp; } /* * Allocate and initialize an indirection array once the space needed * for incore extents increases above XFS_IEXT_BUFSZ. */ void xfs_iext_irec_init( xfs_ifork_t *ifp) /* inode fork pointer */ { xfs_ext_irec_t *erp; /* indirection array pointer */ xfs_extnum_t nextents; /* number of extents in file */ ASSERT(!(ifp->if_flags & XFS_IFEXTIREC)); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ASSERT(nextents <= XFS_LINEAR_EXTS); erp = kmem_alloc(sizeof(xfs_ext_irec_t), KM_NOFS); if (nextents == 0) { ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS); } else if (!ifp->if_real_bytes) { xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ); } else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) { xfs_iext_realloc_direct(ifp, XFS_IEXT_BUFSZ); } erp->er_extbuf = ifp->if_u1.if_extents; erp->er_extcount = nextents; erp->er_extoff = 0; ifp->if_flags |= XFS_IFEXTIREC; ifp->if_real_bytes = XFS_IEXT_BUFSZ; ifp->if_bytes = nextents * sizeof(xfs_bmbt_rec_t); ifp->if_u1.if_ext_irec = erp; return; } /* * Allocate and initialize a new entry in the indirection array. */ xfs_ext_irec_t * xfs_iext_irec_new( xfs_ifork_t *ifp, /* inode fork pointer */ int erp_idx) /* index for new irec */ { xfs_ext_irec_t *erp; /* indirection array pointer */ int i; /* loop counter */ int nlists; /* number of irec's (ex lists) */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; /* Resize indirection array */ xfs_iext_realloc_indirect(ifp, ++nlists * sizeof(xfs_ext_irec_t)); /* * Move records down in the array so the * new page can use erp_idx. */ erp = ifp->if_u1.if_ext_irec; for (i = nlists - 1; i > erp_idx; i--) { memmove(&erp[i], &erp[i-1], sizeof(xfs_ext_irec_t)); } ASSERT(i == erp_idx); /* Initialize new extent record */ erp = ifp->if_u1.if_ext_irec; erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS); ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ); erp[erp_idx].er_extcount = 0; erp[erp_idx].er_extoff = erp_idx > 0 ? erp[erp_idx-1].er_extoff + erp[erp_idx-1].er_extcount : 0; return (&erp[erp_idx]); } /* * Remove a record from the indirection array. */ void xfs_iext_irec_remove( xfs_ifork_t *ifp, /* inode fork pointer */ int erp_idx) /* irec index to remove */ { xfs_ext_irec_t *erp; /* indirection array pointer */ int i; /* loop counter */ int nlists; /* number of irec's (ex lists) */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; erp = &ifp->if_u1.if_ext_irec[erp_idx]; if (erp->er_extbuf) { xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -erp->er_extcount); kmem_free(erp->er_extbuf); } /* Compact extent records */ erp = ifp->if_u1.if_ext_irec; for (i = erp_idx; i < nlists - 1; i++) { memmove(&erp[i], &erp[i+1], sizeof(xfs_ext_irec_t)); } /* * Manually free the last extent record from the indirection * array. A call to xfs_iext_realloc_indirect() with a size * of zero would result in a call to xfs_iext_destroy() which * would in turn call this function again, creating a nasty * infinite loop. */ if (--nlists) { xfs_iext_realloc_indirect(ifp, nlists * sizeof(xfs_ext_irec_t)); } else { kmem_free(ifp->if_u1.if_ext_irec); } ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; } /* * This is called to clean up large amounts of unused memory allocated * by the indirection array. Before compacting anything though, verify * that the indirection array is still needed and switch back to the * linear extent list (or even the inline buffer) if possible. The * compaction policy is as follows: * * Full Compaction: Extents fit into a single page (or inline buffer) * Partial Compaction: Extents occupy less than 50% of allocated space * No Compaction: Extents occupy at least 50% of allocated space */ void xfs_iext_irec_compact( xfs_ifork_t *ifp) /* inode fork pointer */ { xfs_extnum_t nextents; /* number of extents in file */ int nlists; /* number of irec's (ex lists) */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); if (nextents == 0) { xfs_iext_destroy(ifp); } else if (nextents <= XFS_INLINE_EXTS) { xfs_iext_indirect_to_direct(ifp); xfs_iext_direct_to_inline(ifp, nextents); } else if (nextents <= XFS_LINEAR_EXTS) { xfs_iext_indirect_to_direct(ifp); } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { xfs_iext_irec_compact_pages(ifp); } } /* * Combine extents from neighboring extent pages. */ void xfs_iext_irec_compact_pages( xfs_ifork_t *ifp) /* inode fork pointer */ { xfs_ext_irec_t *erp, *erp_next;/* pointers to irec entries */ int erp_idx = 0; /* indirection array index */ int nlists; /* number of irec's (ex lists) */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; while (erp_idx < nlists - 1) { erp = &ifp->if_u1.if_ext_irec[erp_idx]; erp_next = erp + 1; if (erp_next->er_extcount <= (XFS_LINEAR_EXTS - erp->er_extcount)) { memcpy(&erp->er_extbuf[erp->er_extcount], erp_next->er_extbuf, erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); erp->er_extcount += erp_next->er_extcount; /* * Free page before removing extent record * so er_extoffs don't get modified in * xfs_iext_irec_remove. */ kmem_free(erp_next->er_extbuf); erp_next->er_extbuf = NULL; xfs_iext_irec_remove(ifp, erp_idx + 1); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; } else { erp_idx++; } } } /* * This is called to update the er_extoff field in the indirection * array when extents have been added or removed from one of the * extent lists. erp_idx contains the irec index to begin updating * at and ext_diff contains the number of extents that were added * or removed. */ void xfs_iext_irec_update_extoffs( xfs_ifork_t *ifp, /* inode fork pointer */ int erp_idx, /* irec index to update */ int ext_diff) /* number of new extents */ { int i; /* loop counter */ int nlists; /* number of irec's (ex lists */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; for (i = erp_idx; i < nlists; i++) { ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff; } } /* * Initialize an inode's copy-on-write fork. */ void xfs_ifork_init_cow( struct xfs_inode *ip) { if (ip->i_cowfp) return; ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP | KM_NOFS); ip->i_cowfp->if_flags = XFS_IFEXTENTS; ip->i_cformat = XFS_DINODE_FMT_EXTENTS; ip->i_cnextents = 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_inode_fork.h0000644000000000000000000001613413063067170017135 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_INODE_FORK_H__ #define __XFS_INODE_FORK_H__ struct xfs_inode_log_item; struct xfs_dinode; /* * The following xfs_ext_irec_t struct introduces a second (top) level * to the in-core extent allocation scheme. These structs are allocated * in a contiguous block, creating an indirection array where each entry * (irec) contains a pointer to a buffer of in-core extent records which * it manages. Each extent buffer is 4k in size, since 4k is the system * page size on Linux i386 and systems with larger page sizes don't seem * to gain much, if anything, by using their native page size as the * extent buffer size. Also, using 4k extent buffers everywhere provides * a consistent interface for CXFS across different platforms. * * There is currently no limit on the number of irec's (extent lists) * allowed, so heavily fragmented files may require an indirection array * which spans multiple system pages of memory. The number of extents * which would require this amount of contiguous memory is very large * and should not cause problems in the foreseeable future. However, * if the memory needed for the contiguous array ever becomes a problem, * it is possible that a third level of indirection may be required. */ typedef struct xfs_ext_irec { xfs_bmbt_rec_host_t *er_extbuf; /* block of extent records */ xfs_extnum_t er_extoff; /* extent offset in file */ xfs_extnum_t er_extcount; /* number of extents in page/block */ } xfs_ext_irec_t; /* * File incore extent information, present for each of data & attr forks. */ #define XFS_IEXT_BUFSZ 4096 #define XFS_LINEAR_EXTS (XFS_IEXT_BUFSZ / (uint)sizeof(xfs_bmbt_rec_t)) #define XFS_INLINE_EXTS 2 #define XFS_INLINE_DATA 32 typedef struct xfs_ifork { int if_bytes; /* bytes in if_u1 */ int if_real_bytes; /* bytes allocated in if_u1 */ struct xfs_btree_block *if_broot; /* file's incore btree root */ short if_broot_bytes; /* bytes allocated for root */ unsigned char if_flags; /* per-fork flags */ union { xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */ xfs_ext_irec_t *if_ext_irec; /* irec map file exts */ char *if_data; /* inline file data */ } if_u1; union { xfs_bmbt_rec_host_t if_inline_ext[XFS_INLINE_EXTS]; /* very small file extents */ char if_inline_data[XFS_INLINE_DATA]; /* very small file data */ xfs_dev_t if_rdev; /* dev number if special */ uuid_t if_uuid; /* mount point value */ } if_u2; } xfs_ifork_t; /* * Per-fork incore inode flags. */ #define XFS_IFINLINE 0x01 /* Inline data is read in */ #define XFS_IFEXTENTS 0x02 /* All extent pointers are read in */ #define XFS_IFBROOT 0x04 /* i_broot points to the bmap b-tree root */ #define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */ /* * Fork handling. */ #define XFS_IFORK_Q(ip) ((ip)->i_d.di_forkoff != 0) #define XFS_IFORK_BOFF(ip) ((int)((ip)->i_d.di_forkoff << 3)) #define XFS_IFORK_PTR(ip,w) \ ((w) == XFS_DATA_FORK ? \ &(ip)->i_df : \ ((w) == XFS_ATTR_FORK ? \ (ip)->i_afp : \ (ip)->i_cowfp)) #define XFS_IFORK_DSIZE(ip) \ (XFS_IFORK_Q(ip) ? \ XFS_IFORK_BOFF(ip) : \ XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version)) #define XFS_IFORK_ASIZE(ip) \ (XFS_IFORK_Q(ip) ? \ XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version) - \ XFS_IFORK_BOFF(ip) : \ 0) #define XFS_IFORK_SIZE(ip,w) \ ((w) == XFS_DATA_FORK ? \ XFS_IFORK_DSIZE(ip) : \ ((w) == XFS_ATTR_FORK ? \ XFS_IFORK_ASIZE(ip) : \ 0)) #define XFS_IFORK_FORMAT(ip,w) \ ((w) == XFS_DATA_FORK ? \ (ip)->i_d.di_format : \ ((w) == XFS_ATTR_FORK ? \ (ip)->i_d.di_aformat : \ (ip)->i_cformat)) #define XFS_IFORK_FMT_SET(ip,w,n) \ ((w) == XFS_DATA_FORK ? \ ((ip)->i_d.di_format = (n)) : \ ((w) == XFS_ATTR_FORK ? \ ((ip)->i_d.di_aformat = (n)) : \ ((ip)->i_cformat = (n)))) #define XFS_IFORK_NEXTENTS(ip,w) \ ((w) == XFS_DATA_FORK ? \ (ip)->i_d.di_nextents : \ ((w) == XFS_ATTR_FORK ? \ (ip)->i_d.di_anextents : \ (ip)->i_cnextents)) #define XFS_IFORK_NEXT_SET(ip,w,n) \ ((w) == XFS_DATA_FORK ? \ ((ip)->i_d.di_nextents = (n)) : \ ((w) == XFS_ATTR_FORK ? \ ((ip)->i_d.di_anextents = (n)) : \ ((ip)->i_cnextents = (n)))) #define XFS_IFORK_MAXEXT(ip, w) \ (XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t)) struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state); int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, struct xfs_inode_log_item *, int); void xfs_idestroy_fork(struct xfs_inode *, int); void xfs_idata_realloc(struct xfs_inode *, int, int); void xfs_iroot_realloc(struct xfs_inode *, int, int); int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, int); void xfs_init_local_fork(struct xfs_inode *, int, const void *, int); struct xfs_bmbt_rec_host * xfs_iext_get_ext(struct xfs_ifork *, xfs_extnum_t); void xfs_iext_insert(struct xfs_inode *, xfs_extnum_t, xfs_extnum_t, struct xfs_bmbt_irec *, int); void xfs_iext_add(struct xfs_ifork *, xfs_extnum_t, int); void xfs_iext_add_indirect_multi(struct xfs_ifork *, int, xfs_extnum_t, int); void xfs_iext_remove(struct xfs_inode *, xfs_extnum_t, int, int); void xfs_iext_remove_inline(struct xfs_ifork *, xfs_extnum_t, int); void xfs_iext_remove_direct(struct xfs_ifork *, xfs_extnum_t, int); void xfs_iext_remove_indirect(struct xfs_ifork *, xfs_extnum_t, int); void xfs_iext_realloc_direct(struct xfs_ifork *, int); void xfs_iext_direct_to_inline(struct xfs_ifork *, xfs_extnum_t); void xfs_iext_inline_to_direct(struct xfs_ifork *, int); void xfs_iext_destroy(struct xfs_ifork *); struct xfs_bmbt_rec_host * xfs_iext_bno_to_ext(struct xfs_ifork *, xfs_fileoff_t, int *); struct xfs_ext_irec * xfs_iext_bno_to_irec(struct xfs_ifork *, xfs_fileoff_t, int *); struct xfs_ext_irec * xfs_iext_idx_to_irec(struct xfs_ifork *, xfs_extnum_t *, int *, int); void xfs_iext_irec_init(struct xfs_ifork *); struct xfs_ext_irec * xfs_iext_irec_new(struct xfs_ifork *, int); void xfs_iext_irec_remove(struct xfs_ifork *, int); void xfs_iext_irec_compact(struct xfs_ifork *); void xfs_iext_irec_compact_pages(struct xfs_ifork *); void xfs_iext_irec_compact_full(struct xfs_ifork *); void xfs_iext_irec_update_extoffs(struct xfs_ifork *, int, int); extern struct kmem_zone *xfs_ifork_zone; extern void xfs_ifork_init_cow(struct xfs_inode *ip); #endif /* __XFS_INODE_FORK_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_log_format.h0000644000000000000000000007276013063067171017157 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_LOG_FORMAT_H__ #define __XFS_LOG_FORMAT_H__ struct xfs_mount; struct xfs_trans_res; /* * On-disk Log Format definitions. * * This file contains all the on-disk format definitions used within the log. It * includes the physical log structure itself, as well as all the log item * format structures that are written into the log and intepreted by log * recovery. We start with the physical log format definitions, and then work * through all the log items definitions and everything they encode into the * log. */ typedef __uint32_t xlog_tid_t; #define XLOG_MIN_ICLOGS 2 #define XLOG_MAX_ICLOGS 8 #define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe /* Invalid cycle number */ #define XLOG_VERSION_1 1 #define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */ #define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2) #define XLOG_MIN_RECORD_BSIZE (16*1024) /* eventually 32k */ #define XLOG_BIG_RECORD_BSIZE (32*1024) /* 32k buffers */ #define XLOG_MAX_RECORD_BSIZE (256*1024) #define XLOG_HEADER_CYCLE_SIZE (32*1024) /* cycle data in header */ #define XLOG_MIN_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */ #define XLOG_BIG_RECORD_BSHIFT 15 /* 32k == 1 << 15 */ #define XLOG_MAX_RECORD_BSHIFT 18 /* 256k == 1 << 18 */ #define XLOG_BTOLSUNIT(log, b) (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \ (log)->l_mp->m_sb.sb_logsunit) #define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit) #define XLOG_HEADER_SIZE 512 /* Minimum number of transactions that must fit in the log (defined by mkfs) */ #define XFS_MIN_LOG_FACTOR 3 #define XLOG_REC_SHIFT(log) \ BTOBB(1 << (xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? \ XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT)) #define XLOG_TOTAL_REC_SHIFT(log) \ BTOBB(XLOG_MAX_ICLOGS << (xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? \ XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT)) /* get lsn fields */ #define CYCLE_LSN(lsn) ((uint)((lsn)>>32)) #define BLOCK_LSN(lsn) ((uint)(lsn)) /* this is used in a spot where we might otherwise double-endian-flip */ #define CYCLE_LSN_DISK(lsn) (((__be32 *)&(lsn))[0]) static inline xfs_lsn_t xlog_assign_lsn(uint cycle, uint block) { return ((xfs_lsn_t)cycle << 32) | block; } static inline uint xlog_get_cycle(char *ptr) { if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM) return be32_to_cpu(*((__be32 *)ptr + 1)); else return be32_to_cpu(*(__be32 *)ptr); } /* Log Clients */ #define XFS_TRANSACTION 0x69 #define XFS_VOLUME 0x2 #define XFS_LOG 0xaa #define XLOG_UNMOUNT_TYPE 0x556e /* Un for Unmount */ /* Region types for iovec's i_type */ #define XLOG_REG_TYPE_BFORMAT 1 #define XLOG_REG_TYPE_BCHUNK 2 #define XLOG_REG_TYPE_EFI_FORMAT 3 #define XLOG_REG_TYPE_EFD_FORMAT 4 #define XLOG_REG_TYPE_IFORMAT 5 #define XLOG_REG_TYPE_ICORE 6 #define XLOG_REG_TYPE_IEXT 7 #define XLOG_REG_TYPE_IBROOT 8 #define XLOG_REG_TYPE_ILOCAL 9 #define XLOG_REG_TYPE_IATTR_EXT 10 #define XLOG_REG_TYPE_IATTR_BROOT 11 #define XLOG_REG_TYPE_IATTR_LOCAL 12 #define XLOG_REG_TYPE_QFORMAT 13 #define XLOG_REG_TYPE_DQUOT 14 #define XLOG_REG_TYPE_QUOTAOFF 15 #define XLOG_REG_TYPE_LRHEADER 16 #define XLOG_REG_TYPE_UNMOUNT 17 #define XLOG_REG_TYPE_COMMIT 18 #define XLOG_REG_TYPE_TRANSHDR 19 #define XLOG_REG_TYPE_ICREATE 20 #define XLOG_REG_TYPE_RUI_FORMAT 21 #define XLOG_REG_TYPE_RUD_FORMAT 22 #define XLOG_REG_TYPE_CUI_FORMAT 23 #define XLOG_REG_TYPE_CUD_FORMAT 24 #define XLOG_REG_TYPE_BUI_FORMAT 25 #define XLOG_REG_TYPE_BUD_FORMAT 26 #define XLOG_REG_TYPE_MAX 26 /* * Flags to log operation header * * The first write of a new transaction will be preceded with a start * record, XLOG_START_TRANS. Once a transaction is committed, a commit * record is written, XLOG_COMMIT_TRANS. If a single region can not fit into * the remainder of the current active in-core log, it is split up into * multiple regions. Each partial region will be marked with a * XLOG_CONTINUE_TRANS until the last one, which gets marked with XLOG_END_TRANS. * */ #define XLOG_START_TRANS 0x01 /* Start a new transaction */ #define XLOG_COMMIT_TRANS 0x02 /* Commit this transaction */ #define XLOG_CONTINUE_TRANS 0x04 /* Cont this trans into new region */ #define XLOG_WAS_CONT_TRANS 0x08 /* Cont this trans into new region */ #define XLOG_END_TRANS 0x10 /* End a continued transaction */ #define XLOG_UNMOUNT_TRANS 0x20 /* Unmount a filesystem transaction */ typedef struct xlog_op_header { __be32 oh_tid; /* transaction id of operation : 4 b */ __be32 oh_len; /* bytes in data region : 4 b */ __u8 oh_clientid; /* who sent me this : 1 b */ __u8 oh_flags; /* : 1 b */ __u16 oh_res2; /* 32 bit align : 2 b */ } xlog_op_header_t; /* valid values for h_fmt */ #define XLOG_FMT_UNKNOWN 0 #define XLOG_FMT_LINUX_LE 1 #define XLOG_FMT_LINUX_BE 2 #define XLOG_FMT_IRIX_BE 3 /* our fmt */ #ifdef XFS_NATIVE_HOST #define XLOG_FMT XLOG_FMT_LINUX_BE #else #define XLOG_FMT XLOG_FMT_LINUX_LE #endif typedef struct xlog_rec_header { __be32 h_magicno; /* log record (LR) identifier : 4 */ __be32 h_cycle; /* write cycle of log : 4 */ __be32 h_version; /* LR version : 4 */ __be32 h_len; /* len in bytes; should be 64-bit aligned: 4 */ __be64 h_lsn; /* lsn of this LR : 8 */ __be64 h_tail_lsn; /* lsn of 1st LR w/ buffers not committed: 8 */ __le32 h_crc; /* crc of log record : 4 */ __be32 h_prev_block; /* block number to previous LR : 4 */ __be32 h_num_logops; /* number of log operations in this LR : 4 */ __be32 h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /* new fields */ __be32 h_fmt; /* format of log record : 4 */ uuid_t h_fs_uuid; /* uuid of FS : 16 */ __be32 h_size; /* iclog size : 4 */ } xlog_rec_header_t; typedef struct xlog_rec_ext_header { __be32 xh_cycle; /* write cycle of log : 4 */ __be32 xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /* : 256 */ } xlog_rec_ext_header_t; /* * Quite misnamed, because this union lays out the actual on-disk log buffer. */ typedef union xlog_in_core2 { xlog_rec_header_t hic_header; xlog_rec_ext_header_t hic_xheader; char hic_sector[XLOG_HEADER_SIZE]; } xlog_in_core_2_t; /* not an on-disk structure, but needed by log recovery in userspace */ typedef struct xfs_log_iovec { void *i_addr; /* beginning address of region */ int i_len; /* length in bytes of region */ uint i_type; /* type of region */ } xfs_log_iovec_t; /* * Transaction Header definitions. * * This is the structure written in the log at the head of every transaction. It * identifies the type and id of the transaction, and contains the number of * items logged by the transaction so we know how many to expect during * recovery. * * Do not change the below structure without redoing the code in * xlog_recover_add_to_trans() and xlog_recover_add_to_cont_trans(). */ typedef struct xfs_trans_header { uint th_magic; /* magic number */ uint th_type; /* transaction type */ __int32_t th_tid; /* transaction id (unused) */ uint th_num_items; /* num items logged by trans */ } xfs_trans_header_t; #define XFS_TRANS_HEADER_MAGIC 0x5452414e /* TRAN */ /* * The only type valid for th_type in CIL-enabled file system logs: */ #define XFS_TRANS_CHECKPOINT 40 /* * Log item types. */ #define XFS_LI_EFI 0x1236 #define XFS_LI_EFD 0x1237 #define XFS_LI_IUNLINK 0x1238 #define XFS_LI_INODE 0x123b /* aligned ino chunks, var-size ibufs */ #define XFS_LI_BUF 0x123c /* v2 bufs, variable sized inode bufs */ #define XFS_LI_DQUOT 0x123d #define XFS_LI_QUOTAOFF 0x123e #define XFS_LI_ICREATE 0x123f #define XFS_LI_RUI 0x1240 /* rmap update intent */ #define XFS_LI_RUD 0x1241 #define XFS_LI_CUI 0x1242 /* refcount update intent */ #define XFS_LI_CUD 0x1243 #define XFS_LI_BUI 0x1244 /* bmbt update intent */ #define XFS_LI_BUD 0x1245 #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ { XFS_LI_EFD, "XFS_LI_EFD" }, \ { XFS_LI_IUNLINK, "XFS_LI_IUNLINK" }, \ { XFS_LI_INODE, "XFS_LI_INODE" }, \ { XFS_LI_BUF, "XFS_LI_BUF" }, \ { XFS_LI_DQUOT, "XFS_LI_DQUOT" }, \ { XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \ { XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \ { XFS_LI_RUI, "XFS_LI_RUI" }, \ { XFS_LI_RUD, "XFS_LI_RUD" }, \ { XFS_LI_CUI, "XFS_LI_CUI" }, \ { XFS_LI_CUD, "XFS_LI_CUD" }, \ { XFS_LI_BUI, "XFS_LI_BUI" }, \ { XFS_LI_BUD, "XFS_LI_BUD" } /* * Inode Log Item Format definitions. * * This is the structure used to lay out an inode log item in the * log. The size of the inline data/extents/b-tree root to be logged * (if any) is indicated in the ilf_dsize field. Changes to this structure * must be added on to the end. */ typedef struct xfs_inode_log_format { __uint16_t ilf_type; /* inode log item type */ __uint16_t ilf_size; /* size of this item */ __uint32_t ilf_fields; /* flags for fields logged */ __uint16_t ilf_asize; /* size of attr d/ext/root */ __uint16_t ilf_dsize; /* size of data/ext/root */ __uint64_t ilf_ino; /* inode number */ union { __uint32_t ilfu_rdev; /* rdev value for dev inode*/ uuid_t ilfu_uuid; /* mount point value */ } ilf_u; __int64_t ilf_blkno; /* blkno of inode buffer */ __int32_t ilf_len; /* len of inode buffer */ __int32_t ilf_boffset; /* off of inode in buffer */ } xfs_inode_log_format_t; typedef struct xfs_inode_log_format_32 { __uint16_t ilf_type; /* inode log item type */ __uint16_t ilf_size; /* size of this item */ __uint32_t ilf_fields; /* flags for fields logged */ __uint16_t ilf_asize; /* size of attr d/ext/root */ __uint16_t ilf_dsize; /* size of data/ext/root */ __uint64_t ilf_ino; /* inode number */ union { __uint32_t ilfu_rdev; /* rdev value for dev inode*/ uuid_t ilfu_uuid; /* mount point value */ } ilf_u; __int64_t ilf_blkno; /* blkno of inode buffer */ __int32_t ilf_len; /* len of inode buffer */ __int32_t ilf_boffset; /* off of inode in buffer */ } __attribute__((packed)) xfs_inode_log_format_32_t; typedef struct xfs_inode_log_format_64 { __uint16_t ilf_type; /* inode log item type */ __uint16_t ilf_size; /* size of this item */ __uint32_t ilf_fields; /* flags for fields logged */ __uint16_t ilf_asize; /* size of attr d/ext/root */ __uint16_t ilf_dsize; /* size of data/ext/root */ __uint32_t ilf_pad; /* pad for 64 bit boundary */ __uint64_t ilf_ino; /* inode number */ union { __uint32_t ilfu_rdev; /* rdev value for dev inode*/ uuid_t ilfu_uuid; /* mount point value */ } ilf_u; __int64_t ilf_blkno; /* blkno of inode buffer */ __int32_t ilf_len; /* len of inode buffer */ __int32_t ilf_boffset; /* off of inode in buffer */ } xfs_inode_log_format_64_t; /* * Flags for xfs_trans_log_inode flags field. */ #define XFS_ILOG_CORE 0x001 /* log standard inode fields */ #define XFS_ILOG_DDATA 0x002 /* log i_df.if_data */ #define XFS_ILOG_DEXT 0x004 /* log i_df.if_extents */ #define XFS_ILOG_DBROOT 0x008 /* log i_df.i_broot */ #define XFS_ILOG_DEV 0x010 /* log the dev field */ #define XFS_ILOG_UUID 0x020 /* log the uuid field */ #define XFS_ILOG_ADATA 0x040 /* log i_af.if_data */ #define XFS_ILOG_AEXT 0x080 /* log i_af.if_extents */ #define XFS_ILOG_ABROOT 0x100 /* log i_af.i_broot */ #define XFS_ILOG_DOWNER 0x200 /* change the data fork owner on replay */ #define XFS_ILOG_AOWNER 0x400 /* change the attr fork owner on replay */ /* * The timestamps are dirty, but not necessarily anything else in the inode * core. Unlike the other fields above this one must never make it to disk * in the ilf_fields of the inode_log_format, but is purely store in-memory in * ili_fields in the inode_log_item. */ #define XFS_ILOG_TIMESTAMP 0x4000 #define XFS_ILOG_NONCORE (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ XFS_ILOG_DBROOT | XFS_ILOG_DEV | \ XFS_ILOG_UUID | XFS_ILOG_ADATA | \ XFS_ILOG_AEXT | XFS_ILOG_ABROOT | \ XFS_ILOG_DOWNER | XFS_ILOG_AOWNER) #define XFS_ILOG_DFORK (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ XFS_ILOG_DBROOT) #define XFS_ILOG_AFORK (XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ XFS_ILOG_ABROOT) #define XFS_ILOG_ALL (XFS_ILOG_CORE | XFS_ILOG_DDATA | \ XFS_ILOG_DEXT | XFS_ILOG_DBROOT | \ XFS_ILOG_DEV | XFS_ILOG_UUID | \ XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP | \ XFS_ILOG_DOWNER | XFS_ILOG_AOWNER) static inline int xfs_ilog_fbroot(int w) { return (w == XFS_DATA_FORK ? XFS_ILOG_DBROOT : XFS_ILOG_ABROOT); } static inline int xfs_ilog_fext(int w) { return (w == XFS_DATA_FORK ? XFS_ILOG_DEXT : XFS_ILOG_AEXT); } static inline int xfs_ilog_fdata(int w) { return (w == XFS_DATA_FORK ? XFS_ILOG_DDATA : XFS_ILOG_ADATA); } /* * Incore version of the on-disk inode core structures. We log this directly * into the journal in host CPU format (for better or worse) and as such * directly mirrors the xfs_dinode structure as it must contain all the same * information. */ typedef struct xfs_ictimestamp { __int32_t t_sec; /* timestamp seconds */ __int32_t t_nsec; /* timestamp nanoseconds */ } xfs_ictimestamp_t; /* * Define the format of the inode core that is logged. This structure must be * kept identical to struct xfs_dinode except for the endianness annotations. */ struct xfs_log_dinode { __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ __uint16_t di_mode; /* mode and type of file */ __int8_t di_version; /* inode version */ __int8_t di_format; /* format of di_c data */ __uint8_t di_pad3[2]; /* unused in v2/3 inodes */ __uint32_t di_uid; /* owner's user id */ __uint32_t di_gid; /* owner's group id */ __uint32_t di_nlink; /* number of links to file */ __uint16_t di_projid_lo; /* lower part of owner's project id */ __uint16_t di_projid_hi; /* higher part of owner's project id */ __uint8_t di_pad[6]; /* unused, zeroed space */ __uint16_t di_flushiter; /* incremented on flush */ xfs_ictimestamp_t di_atime; /* time last accessed */ xfs_ictimestamp_t di_mtime; /* time last modified */ xfs_ictimestamp_t di_ctime; /* time created/inode modified */ xfs_fsize_t di_size; /* number of bytes in file */ xfs_rfsblock_t di_nblocks; /* # of direct & btree blocks used */ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */ xfs_extnum_t di_nextents; /* number of extents in data fork */ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/ __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */ __int8_t di_aformat; /* format of attr fork's data */ __uint32_t di_dmevmask; /* DMIG event mask */ __uint16_t di_dmstate; /* DMIG state info */ __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ __uint32_t di_gen; /* generation number */ /* di_next_unlinked is the only non-core field in the old dinode */ xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */ /* start of the extended dinode, writable fields */ __uint32_t di_crc; /* CRC of the inode */ __uint64_t di_changecount; /* number of attribute changes */ xfs_lsn_t di_lsn; /* flush sequence */ __uint64_t di_flags2; /* more random flags */ __uint32_t di_cowextsize; /* basic cow extent size for file */ __uint8_t di_pad2[12]; /* more padding for future expansion */ /* fields only written to during inode creation */ xfs_ictimestamp_t di_crtime; /* time created */ xfs_ino_t di_ino; /* inode number */ uuid_t di_uuid; /* UUID of the filesystem */ /* structure must be padded to 64 bit alignment */ }; static inline uint xfs_log_dinode_size(int version) { if (version == 3) return sizeof(struct xfs_log_dinode); return offsetof(struct xfs_log_dinode, di_next_unlinked); } /* * Buffer Log Format defintions * * These are the physical dirty bitmap defintions for the log format structure. */ #define XFS_BLF_CHUNK 128 #define XFS_BLF_SHIFT 7 #define BIT_TO_WORD_SHIFT 5 #define NBWORD (NBBY * sizeof(unsigned int)) /* * This flag indicates that the buffer contains on disk inodes * and requires special recovery handling. */ #define XFS_BLF_INODE_BUF (1<<0) /* * This flag indicates that the buffer should not be replayed * during recovery because its blocks are being freed. */ #define XFS_BLF_CANCEL (1<<1) /* * This flag indicates that the buffer contains on disk * user or group dquots and may require special recovery handling. */ #define XFS_BLF_UDQUOT_BUF (1<<2) #define XFS_BLF_PDQUOT_BUF (1<<3) #define XFS_BLF_GDQUOT_BUF (1<<4) /* * This is the structure used to lay out a buf log item in the * log. The data map describes which 128 byte chunks of the buffer * have been logged. */ #define XFS_BLF_DATAMAP_SIZE ((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / NBWORD) typedef struct xfs_buf_log_format { unsigned short blf_type; /* buf log item type indicator */ unsigned short blf_size; /* size of this item */ unsigned short blf_flags; /* misc state */ unsigned short blf_len; /* number of blocks in this buf */ __int64_t blf_blkno; /* starting blkno of this buf */ unsigned int blf_map_size; /* used size of data bitmap in words */ unsigned int blf_data_map[XFS_BLF_DATAMAP_SIZE]; /* dirty bitmap */ } xfs_buf_log_format_t; /* * All buffers now need to tell recovery where the magic number * is so that it can verify and calculate the CRCs on the buffer correctly * once the changes have been replayed into the buffer. * * The type value is held in the upper 5 bits of the blf_flags field, which is * an unsigned 16 bit field. Hence we need to shift it 11 bits up and down. */ #define XFS_BLFT_BITS 5 #define XFS_BLFT_SHIFT 11 #define XFS_BLFT_MASK (((1 << XFS_BLFT_BITS) - 1) << XFS_BLFT_SHIFT) enum xfs_blft { XFS_BLFT_UNKNOWN_BUF = 0, XFS_BLFT_UDQUOT_BUF, XFS_BLFT_PDQUOT_BUF, XFS_BLFT_GDQUOT_BUF, XFS_BLFT_BTREE_BUF, XFS_BLFT_AGF_BUF, XFS_BLFT_AGFL_BUF, XFS_BLFT_AGI_BUF, XFS_BLFT_DINO_BUF, XFS_BLFT_SYMLINK_BUF, XFS_BLFT_DIR_BLOCK_BUF, XFS_BLFT_DIR_DATA_BUF, XFS_BLFT_DIR_FREE_BUF, XFS_BLFT_DIR_LEAF1_BUF, XFS_BLFT_DIR_LEAFN_BUF, XFS_BLFT_DA_NODE_BUF, XFS_BLFT_ATTR_LEAF_BUF, XFS_BLFT_ATTR_RMT_BUF, XFS_BLFT_SB_BUF, XFS_BLFT_RTBITMAP_BUF, XFS_BLFT_RTSUMMARY_BUF, XFS_BLFT_MAX_BUF = (1 << XFS_BLFT_BITS), }; static inline void xfs_blft_to_flags(struct xfs_buf_log_format *blf, enum xfs_blft type) { ASSERT(type > XFS_BLFT_UNKNOWN_BUF && type < XFS_BLFT_MAX_BUF); blf->blf_flags &= ~XFS_BLFT_MASK; blf->blf_flags |= ((type << XFS_BLFT_SHIFT) & XFS_BLFT_MASK); } static inline __uint16_t xfs_blft_from_flags(struct xfs_buf_log_format *blf) { return (blf->blf_flags & XFS_BLFT_MASK) >> XFS_BLFT_SHIFT; } /* * EFI/EFD log format definitions */ typedef struct xfs_extent { xfs_fsblock_t ext_start; xfs_extlen_t ext_len; } xfs_extent_t; /* * Since an xfs_extent_t has types (start:64, len: 32) * there are different alignments on 32 bit and 64 bit kernels. * So we provide the different variants for use by a * conversion routine. */ typedef struct xfs_extent_32 { __uint64_t ext_start; __uint32_t ext_len; } __attribute__((packed)) xfs_extent_32_t; typedef struct xfs_extent_64 { __uint64_t ext_start; __uint32_t ext_len; __uint32_t ext_pad; } xfs_extent_64_t; /* * This is the structure used to lay out an efi log item in the * log. The efi_extents field is a variable size array whose * size is given by efi_nextents. */ typedef struct xfs_efi_log_format { __uint16_t efi_type; /* efi log item type */ __uint16_t efi_size; /* size of this item */ __uint32_t efi_nextents; /* # extents to free */ __uint64_t efi_id; /* efi identifier */ xfs_extent_t efi_extents[1]; /* array of extents to free */ } xfs_efi_log_format_t; typedef struct xfs_efi_log_format_32 { __uint16_t efi_type; /* efi log item type */ __uint16_t efi_size; /* size of this item */ __uint32_t efi_nextents; /* # extents to free */ __uint64_t efi_id; /* efi identifier */ xfs_extent_32_t efi_extents[1]; /* array of extents to free */ } __attribute__((packed)) xfs_efi_log_format_32_t; typedef struct xfs_efi_log_format_64 { __uint16_t efi_type; /* efi log item type */ __uint16_t efi_size; /* size of this item */ __uint32_t efi_nextents; /* # extents to free */ __uint64_t efi_id; /* efi identifier */ xfs_extent_64_t efi_extents[1]; /* array of extents to free */ } xfs_efi_log_format_64_t; /* * This is the structure used to lay out an efd log item in the * log. The efd_extents array is a variable size array whose * size is given by efd_nextents; */ typedef struct xfs_efd_log_format { __uint16_t efd_type; /* efd log item type */ __uint16_t efd_size; /* size of this item */ __uint32_t efd_nextents; /* # of extents freed */ __uint64_t efd_efi_id; /* id of corresponding efi */ xfs_extent_t efd_extents[1]; /* array of extents freed */ } xfs_efd_log_format_t; typedef struct xfs_efd_log_format_32 { __uint16_t efd_type; /* efd log item type */ __uint16_t efd_size; /* size of this item */ __uint32_t efd_nextents; /* # of extents freed */ __uint64_t efd_efi_id; /* id of corresponding efi */ xfs_extent_32_t efd_extents[1]; /* array of extents freed */ } __attribute__((packed)) xfs_efd_log_format_32_t; typedef struct xfs_efd_log_format_64 { __uint16_t efd_type; /* efd log item type */ __uint16_t efd_size; /* size of this item */ __uint32_t efd_nextents; /* # of extents freed */ __uint64_t efd_efi_id; /* id of corresponding efi */ xfs_extent_64_t efd_extents[1]; /* array of extents freed */ } xfs_efd_log_format_64_t; /* * RUI/RUD (reverse mapping) log format definitions */ struct xfs_map_extent { __uint64_t me_owner; __uint64_t me_startblock; __uint64_t me_startoff; __uint32_t me_len; __uint32_t me_flags; }; /* rmap me_flags: upper bits are flags, lower byte is type code */ #define XFS_RMAP_EXTENT_MAP 1 #define XFS_RMAP_EXTENT_MAP_SHARED 2 #define XFS_RMAP_EXTENT_UNMAP 3 #define XFS_RMAP_EXTENT_UNMAP_SHARED 4 #define XFS_RMAP_EXTENT_CONVERT 5 #define XFS_RMAP_EXTENT_CONVERT_SHARED 6 #define XFS_RMAP_EXTENT_ALLOC 7 #define XFS_RMAP_EXTENT_FREE 8 #define XFS_RMAP_EXTENT_TYPE_MASK 0xFF #define XFS_RMAP_EXTENT_ATTR_FORK (1U << 31) #define XFS_RMAP_EXTENT_BMBT_BLOCK (1U << 30) #define XFS_RMAP_EXTENT_UNWRITTEN (1U << 29) #define XFS_RMAP_EXTENT_FLAGS (XFS_RMAP_EXTENT_TYPE_MASK | \ XFS_RMAP_EXTENT_ATTR_FORK | \ XFS_RMAP_EXTENT_BMBT_BLOCK | \ XFS_RMAP_EXTENT_UNWRITTEN) /* * This is the structure used to lay out an rui log item in the * log. The rui_extents field is a variable size array whose * size is given by rui_nextents. */ struct xfs_rui_log_format { __uint16_t rui_type; /* rui log item type */ __uint16_t rui_size; /* size of this item */ __uint32_t rui_nextents; /* # extents to free */ __uint64_t rui_id; /* rui identifier */ struct xfs_map_extent rui_extents[]; /* array of extents to rmap */ }; static inline size_t xfs_rui_log_format_sizeof( unsigned int nr) { return sizeof(struct xfs_rui_log_format) + nr * sizeof(struct xfs_map_extent); } /* * This is the structure used to lay out an rud log item in the * log. The rud_extents array is a variable size array whose * size is given by rud_nextents; */ struct xfs_rud_log_format { __uint16_t rud_type; /* rud log item type */ __uint16_t rud_size; /* size of this item */ __uint32_t __pad; __uint64_t rud_rui_id; /* id of corresponding rui */ }; /* * CUI/CUD (refcount update) log format definitions */ struct xfs_phys_extent { __uint64_t pe_startblock; __uint32_t pe_len; __uint32_t pe_flags; }; /* refcount pe_flags: upper bits are flags, lower byte is type code */ /* Type codes are taken directly from enum xfs_refcount_intent_type. */ #define XFS_REFCOUNT_EXTENT_TYPE_MASK 0xFF #define XFS_REFCOUNT_EXTENT_FLAGS (XFS_REFCOUNT_EXTENT_TYPE_MASK) /* * This is the structure used to lay out a cui log item in the * log. The cui_extents field is a variable size array whose * size is given by cui_nextents. */ struct xfs_cui_log_format { __uint16_t cui_type; /* cui log item type */ __uint16_t cui_size; /* size of this item */ __uint32_t cui_nextents; /* # extents to free */ __uint64_t cui_id; /* cui identifier */ struct xfs_phys_extent cui_extents[]; /* array of extents */ }; static inline size_t xfs_cui_log_format_sizeof( unsigned int nr) { return sizeof(struct xfs_cui_log_format) + nr * sizeof(struct xfs_phys_extent); } /* * This is the structure used to lay out a cud log item in the * log. The cud_extents array is a variable size array whose * size is given by cud_nextents; */ struct xfs_cud_log_format { __uint16_t cud_type; /* cud log item type */ __uint16_t cud_size; /* size of this item */ __uint32_t __pad; __uint64_t cud_cui_id; /* id of corresponding cui */ }; /* * BUI/BUD (inode block mapping) log format definitions */ /* bmbt me_flags: upper bits are flags, lower byte is type code */ /* Type codes are taken directly from enum xfs_bmap_intent_type. */ #define XFS_BMAP_EXTENT_TYPE_MASK 0xFF #define XFS_BMAP_EXTENT_ATTR_FORK (1U << 31) #define XFS_BMAP_EXTENT_UNWRITTEN (1U << 30) #define XFS_BMAP_EXTENT_FLAGS (XFS_BMAP_EXTENT_TYPE_MASK | \ XFS_BMAP_EXTENT_ATTR_FORK | \ XFS_BMAP_EXTENT_UNWRITTEN) /* * This is the structure used to lay out an bui log item in the * log. The bui_extents field is a variable size array whose * size is given by bui_nextents. */ struct xfs_bui_log_format { __uint16_t bui_type; /* bui log item type */ __uint16_t bui_size; /* size of this item */ __uint32_t bui_nextents; /* # extents to free */ __uint64_t bui_id; /* bui identifier */ struct xfs_map_extent bui_extents[]; /* array of extents to bmap */ }; static inline size_t xfs_bui_log_format_sizeof( unsigned int nr) { return sizeof(struct xfs_bui_log_format) + nr * sizeof(struct xfs_map_extent); } /* * This is the structure used to lay out an bud log item in the * log. The bud_extents array is a variable size array whose * size is given by bud_nextents; */ struct xfs_bud_log_format { __uint16_t bud_type; /* bud log item type */ __uint16_t bud_size; /* size of this item */ __uint32_t __pad; __uint64_t bud_bui_id; /* id of corresponding bui */ }; /* * Dquot Log format definitions. * * The first two fields must be the type and size fitting into * 32 bits : log_recovery code assumes that. */ typedef struct xfs_dq_logformat { __uint16_t qlf_type; /* dquot log item type */ __uint16_t qlf_size; /* size of this item */ xfs_dqid_t qlf_id; /* usr/grp/proj id : 32 bits */ __int64_t qlf_blkno; /* blkno of dquot buffer */ __int32_t qlf_len; /* len of dquot buffer */ __uint32_t qlf_boffset; /* off of dquot in buffer */ } xfs_dq_logformat_t; /* * log format struct for QUOTAOFF records. * The first two fields must be the type and size fitting into * 32 bits : log_recovery code assumes that. * We write two LI_QUOTAOFF logitems per quotaoff, the last one keeps a pointer * to the first and ensures that the first logitem is taken out of the AIL * only when the last one is securely committed. */ typedef struct xfs_qoff_logformat { unsigned short qf_type; /* quotaoff log item type */ unsigned short qf_size; /* size of this item */ unsigned int qf_flags; /* USR and/or GRP */ char qf_pad[12]; /* padding for future */ } xfs_qoff_logformat_t; /* * Disk quotas status in m_qflags, and also sb_qflags. 16 bits. */ #define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */ #define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */ #define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */ #define XFS_PQUOTA_ACCT 0x0008 /* project quota accounting ON */ #define XFS_OQUOTA_ENFD 0x0010 /* other (grp/prj) quota limits enforced */ #define XFS_OQUOTA_CHKD 0x0020 /* quotacheck run on other (grp/prj) quotas */ #define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */ /* * Conversion to and from the combined OQUOTA flag (if necessary) * is done only in xfs_sb_qflags_to_disk() and xfs_sb_qflags_from_disk() */ #define XFS_GQUOTA_ENFD 0x0080 /* group quota limits enforced */ #define XFS_GQUOTA_CHKD 0x0100 /* quotacheck run on group quotas */ #define XFS_PQUOTA_ENFD 0x0200 /* project quota limits enforced */ #define XFS_PQUOTA_CHKD 0x0400 /* quotacheck run on project quotas */ #define XFS_ALL_QUOTA_ACCT \ (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT) #define XFS_ALL_QUOTA_ENFD \ (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD | XFS_PQUOTA_ENFD) #define XFS_ALL_QUOTA_CHKD \ (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD | XFS_PQUOTA_CHKD) #define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD|\ XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD|\ XFS_PQUOTA_CHKD) /* * Inode create log item structure * * Log recovery assumes the first two entries are the type and size and they fit * in 32 bits. Also in host order (ugh) so they have to be 32 bit aligned so * decoding can be done correctly. */ struct xfs_icreate_log { __uint16_t icl_type; /* type of log format structure */ __uint16_t icl_size; /* size of log format structure */ __be32 icl_ag; /* ag being allocated in */ __be32 icl_agbno; /* start block of inode range */ __be32 icl_count; /* number of inodes to initialise */ __be32 icl_isize; /* size of inodes */ __be32 icl_length; /* length of extent to initialise */ __be32 icl_gen; /* inode generation number to use */ }; #endif /* __XFS_LOG_FORMAT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_log_rlimit.c0000644000000000000000000001127213063067171017151 0ustar /* * Copyright (c) 2013 Jie Liu. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_trans_space.h" #include "xfs_inode.h" #include "xfs_da_btree.h" #include "xfs_attr_leaf.h" #include "xfs_bmap_btree.h" /* * Calculate the maximum length in bytes that would be required for a local * attribute value as large attributes out of line are not logged. */ STATIC int xfs_log_calc_max_attrsetm_res( struct xfs_mount *mp) { int size; int nblks; size = xfs_attr_leaf_entsize_local_max(mp->m_attr_geo->blksize) - MAXNAMELEN - 1; nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); nblks += XFS_B_TO_FSB(mp, size); nblks += XFS_NEXTENTADD_SPACE_RES(mp, size, XFS_ATTR_FORK); return M_RES(mp)->tr_attrsetm.tr_logres + M_RES(mp)->tr_attrsetrt.tr_logres * nblks; } /* * Iterate over the log space reservation table to figure out and return * the maximum one in terms of the pre-calculated values which were done * at mount time. */ STATIC void xfs_log_get_max_trans_res( struct xfs_mount *mp, struct xfs_trans_res *max_resp) { struct xfs_trans_res *resp; struct xfs_trans_res *end_resp; int log_space = 0; int attr_space; attr_space = xfs_log_calc_max_attrsetm_res(mp); resp = (struct xfs_trans_res *)M_RES(mp); end_resp = (struct xfs_trans_res *)(M_RES(mp) + 1); for (; resp < end_resp; resp++) { int tmp = resp->tr_logcount > 1 ? resp->tr_logres * resp->tr_logcount : resp->tr_logres; if (log_space < tmp) { log_space = tmp; *max_resp = *resp; /* struct copy */ } } if (attr_space > log_space) { *max_resp = M_RES(mp)->tr_attrsetm; /* struct copy */ max_resp->tr_logres = attr_space; } } /* * Calculate the minimum valid log size for the given superblock configuration. * Used to calculate the minimum log size at mkfs time, and to determine if * the log is large enough or not at mount time. Returns the minimum size in * filesystem block size units. */ int xfs_log_calc_minimum_size( struct xfs_mount *mp) { struct xfs_trans_res tres = {0}; int max_logres; int min_logblks = 0; int lsunit = 0; xfs_log_get_max_trans_res(mp, &tres); max_logres = xfs_log_calc_unit_res(mp, tres.tr_logres); if (tres.tr_logcount > 1) max_logres *= tres.tr_logcount; if (xfs_sb_version_haslogv2(&mp->m_sb) && mp->m_sb.sb_logsunit > 1) lsunit = BTOBB(mp->m_sb.sb_logsunit); /* * Two factors should be taken into account for calculating the minimum * log space. * 1) The fundamental limitation is that no single transaction can be * larger than half size of the log. * * From mkfs.xfs, this is considered by the XFS_MIN_LOG_FACTOR * define, which is set to 3. That means we can definitely fit * maximally sized 2 transactions in the log. We'll use this same * value here. * * 2) If the lsunit option is specified, a transaction requires 2 LSU * for the reservation because there are two log writes that can * require padding - the transaction data and the commit record which * are written separately and both can require padding to the LSU. * Consider that we can have an active CIL reservation holding 2*LSU, * but the CIL is not over a push threshold, in this case, if we * don't have enough log space for at one new transaction, which * includes another 2*LSU in the reservation, we will run into dead * loop situation in log space grant procedure. i.e. * xlog_grant_head_wait(). * * Hence the log size needs to be able to contain two maximally sized * and padded transactions, which is (2 * (2 * LSU + maxlres)). * * Also, the log size should be a multiple of the log stripe unit, round * it up to lsunit boundary if lsunit is specified. */ if (lsunit) { min_logblks = roundup_64(BTOBB(max_logres), lsunit) + 2 * lsunit; } else min_logblks = BTOBB(max_logres) + 2 * BBSIZE; min_logblks *= XFS_MIN_LOG_FACTOR; return XFS_BB_TO_FSB(mp, min_logblks); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_quota_defs.h0000644000000000000000000001470313063067170017150 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_QUOTA_DEFS_H__ #define __XFS_QUOTA_DEFS_H__ /* * Quota definitions shared between user and kernel source trees. */ /* * Even though users may not have quota limits occupying all 64-bits, * they may need 64-bit accounting. Hence, 64-bit quota-counters, * and quota-limits. This is a waste in the common case, but hey ... */ typedef __uint64_t xfs_qcnt_t; typedef __uint16_t xfs_qwarncnt_t; /* * flags for q_flags field in the dquot. */ #define XFS_DQ_USER 0x0001 /* a user quota */ #define XFS_DQ_PROJ 0x0002 /* project quota */ #define XFS_DQ_GROUP 0x0004 /* a group quota */ #define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */ #define XFS_DQ_FREEING 0x0010 /* dquot is being torn down */ #define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP) #define XFS_DQ_FLAGS \ { XFS_DQ_USER, "USER" }, \ { XFS_DQ_PROJ, "PROJ" }, \ { XFS_DQ_GROUP, "GROUP" }, \ { XFS_DQ_DIRTY, "DIRTY" }, \ { XFS_DQ_FREEING, "FREEING" } /* * We have the possibility of all three quota types being active at once, and * hence free space modification requires modification of all three current * dquots in a single transaction. For this case we need to have a reservation * of at least 3 dquots. * * However, a chmod operation can change both UID and GID in a single * transaction, resulting in requiring {old, new} x {uid, gid} dquots to be * modified. Hence for this case we need to reserve space for at least 4 dquots. * * And in the worst case, there's a rename operation that can be modifying up to * 4 inodes with dquots attached to them. In reality, the only inodes that can * have their dquots modified are the source and destination directory inodes * due to directory name creation and removal. That can require space allocation * and/or freeing on both directory inodes, and hence all three dquots on each * inode can be modified. And if the directories are world writeable, all the * dquots can be unique and so 6 dquots can be modified.... * * And, of course, we also need to take into account the dquot log format item * used to describe each dquot. */ #define XFS_DQUOT_LOGRES(mp) \ ((sizeof(struct xfs_dq_logformat) + sizeof(struct xfs_disk_dquot)) * 6) #define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT) #define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT) #define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT) #define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT) #define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD) #define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD) #define XFS_IS_PQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_PQUOTA_ENFD) /* * Incore only flags for quotaoff - these bits get cleared when quota(s) * are in the process of getting turned off. These flags are in m_qflags but * never in sb_qflags. */ #define XFS_UQUOTA_ACTIVE 0x1000 /* uquotas are being turned off */ #define XFS_GQUOTA_ACTIVE 0x2000 /* gquotas are being turned off */ #define XFS_PQUOTA_ACTIVE 0x4000 /* pquotas are being turned off */ #define XFS_ALL_QUOTA_ACTIVE \ (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE) /* * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees * quota will be not be switched off as long as that inode lock is held. */ #define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \ XFS_GQUOTA_ACTIVE | \ XFS_PQUOTA_ACTIVE)) #define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE) #define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE) #define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE) /* * Flags to tell various functions what to do. Not all of these are meaningful * to a single function. None of these XFS_QMOPT_* flags are meant to have * persistent values (ie. their values can and will change between versions) */ #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */ #define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */ #define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */ #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */ #define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */ #define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */ #define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */ #define XFS_QMOPT_DQNEXT 0x0008000 /* return next dquot >= this ID */ /* * flags to xfs_trans_mod_dquot to indicate which field needs to be * modified. */ #define XFS_QMOPT_RES_REGBLKS 0x0010000 #define XFS_QMOPT_RES_RTBLKS 0x0020000 #define XFS_QMOPT_BCOUNT 0x0040000 #define XFS_QMOPT_ICOUNT 0x0080000 #define XFS_QMOPT_RTBCOUNT 0x0100000 #define XFS_QMOPT_DELBCOUNT 0x0200000 #define XFS_QMOPT_DELRTBCOUNT 0x0400000 #define XFS_QMOPT_RES_INOS 0x0800000 /* * flags for dqalloc. */ #define XFS_QMOPT_INHERIT 0x1000000 /* * flags to xfs_trans_mod_dquot. */ #define XFS_TRANS_DQ_RES_BLKS XFS_QMOPT_RES_REGBLKS #define XFS_TRANS_DQ_RES_RTBLKS XFS_QMOPT_RES_RTBLKS #define XFS_TRANS_DQ_RES_INOS XFS_QMOPT_RES_INOS #define XFS_TRANS_DQ_BCOUNT XFS_QMOPT_BCOUNT #define XFS_TRANS_DQ_DELBCOUNT XFS_QMOPT_DELBCOUNT #define XFS_TRANS_DQ_ICOUNT XFS_QMOPT_ICOUNT #define XFS_TRANS_DQ_RTBCOUNT XFS_QMOPT_RTBCOUNT #define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT #define XFS_QMOPT_QUOTALL \ (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA) #define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq, xfs_dqid_t id, uint type, uint flags, const char *str); extern int xfs_calc_dquots_per_chunk(unsigned int nbblks); #endif /* __XFS_QUOTA_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_refcount.c0000644000000000000000000013424613033541503016635 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_btree.h" #include "xfs_bmap.h" #include "xfs_refcount_btree.h" #include "xfs_alloc.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_bit.h" #include "xfs_refcount.h" #include "xfs_rmap.h" /* Allowable refcount adjustment amounts. */ enum xfs_refc_adjust_op { XFS_REFCOUNT_ADJUST_INCREASE = 1, XFS_REFCOUNT_ADJUST_DECREASE = -1, XFS_REFCOUNT_ADJUST_COW_ALLOC = 0, XFS_REFCOUNT_ADJUST_COW_FREE = -1, }; STATIC int __xfs_refcount_cow_alloc(struct xfs_btree_cur *rcur, xfs_agblock_t agbno, xfs_extlen_t aglen, struct xfs_defer_ops *dfops); STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur, xfs_agblock_t agbno, xfs_extlen_t aglen, struct xfs_defer_ops *dfops); /* * Look up the first record less than or equal to [bno, len] in the btree * given by cur. */ int xfs_refcount_lookup_le( struct xfs_btree_cur *cur, xfs_agblock_t bno, int *stat) { trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, XFS_LOOKUP_LE); cur->bc_rec.rc.rc_startblock = bno; cur->bc_rec.rc.rc_blockcount = 0; return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); } /* * Look up the first record greater than or equal to [bno, len] in the btree * given by cur. */ int xfs_refcount_lookup_ge( struct xfs_btree_cur *cur, xfs_agblock_t bno, int *stat) { trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, XFS_LOOKUP_GE); cur->bc_rec.rc.rc_startblock = bno; cur->bc_rec.rc.rc_blockcount = 0; return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); } /* Convert on-disk record to in-core format. */ static inline void xfs_refcount_btrec_to_irec( union xfs_btree_rec *rec, struct xfs_refcount_irec *irec) { irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock); irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount); irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount); } /* * Get the data from the pointed-to record. */ int xfs_refcount_get_rec( struct xfs_btree_cur *cur, struct xfs_refcount_irec *irec, int *stat) { union xfs_btree_rec *rec; int error; error = xfs_btree_get_rec(cur, &rec, stat); if (!error && *stat == 1) { xfs_refcount_btrec_to_irec(rec, irec); trace_xfs_refcount_get(cur->bc_mp, cur->bc_private.a.agno, irec); } return error; } /* * Update the record referred to by cur to the value given * by [bno, len, refcount]. * This either works (return 0) or gets an EFSCORRUPTED error. */ STATIC int xfs_refcount_update( struct xfs_btree_cur *cur, struct xfs_refcount_irec *irec) { union xfs_btree_rec rec; int error; trace_xfs_refcount_update(cur->bc_mp, cur->bc_private.a.agno, irec); rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock); rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount); rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount); error = xfs_btree_update(cur, &rec); if (error) trace_xfs_refcount_update_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Insert the record referred to by cur to the value given * by [bno, len, refcount]. * This either works (return 0) or gets an EFSCORRUPTED error. */ STATIC int xfs_refcount_insert( struct xfs_btree_cur *cur, struct xfs_refcount_irec *irec, int *i) { int error; trace_xfs_refcount_insert(cur->bc_mp, cur->bc_private.a.agno, irec); cur->bc_rec.rc.rc_startblock = irec->rc_startblock; cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount; cur->bc_rec.rc.rc_refcount = irec->rc_refcount; error = xfs_btree_insert(cur, i); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); out_error: if (error) trace_xfs_refcount_insert_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Remove the record referred to by cur, then set the pointer to the spot * where the record could be re-inserted, in case we want to increment or * decrement the cursor. * This either works (return 0) or gets an EFSCORRUPTED error. */ STATIC int xfs_refcount_delete( struct xfs_btree_cur *cur, int *i) { struct xfs_refcount_irec irec; int found_rec; int error; error = xfs_refcount_get_rec(cur, &irec, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); trace_xfs_refcount_delete(cur->bc_mp, cur->bc_private.a.agno, &irec); error = xfs_btree_delete(cur, i); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); if (error) goto out_error; error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec); out_error: if (error) trace_xfs_refcount_delete_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Adjusting the Reference Count * * As stated elsewhere, the reference count btree (refcbt) stores * >1 reference counts for extents of physical blocks. In this * operation, we're either raising or lowering the reference count of * some subrange stored in the tree: * * <------ adjustment range ------> * ----+ +---+-----+ +--+--------+--------- * 2 | | 3 | 4 | |17| 55 | 10 * ----+ +---+-----+ +--+--------+--------- * X axis is physical blocks number; * reference counts are the numbers inside the rectangles * * The first thing we need to do is to ensure that there are no * refcount extents crossing either boundary of the range to be * adjusted. For any extent that does cross a boundary, split it into * two extents so that we can increment the refcount of one of the * pieces later: * * <------ adjustment range ------> * ----+ +---+-----+ +--+--------+----+---- * 2 | | 3 | 2 | |17| 55 | 10 | 10 * ----+ +---+-----+ +--+--------+----+---- * * For this next step, let's assume that all the physical blocks in * the adjustment range are mapped to a file and are therefore in use * at least once. Therefore, we can infer that any gap in the * refcount tree within the adjustment range represents a physical * extent with refcount == 1: * * <------ adjustment range ------> * ----+---+---+-----+-+--+--------+----+---- * 2 |"1"| 3 | 2 |1|17| 55 | 10 | 10 * ----+---+---+-----+-+--+--------+----+---- * ^ * * For each extent that falls within the interval range, figure out * which extent is to the left or the right of that extent. Now we * have a left, current, and right extent. If the new reference count * of the center extent enables us to merge left, center, and right * into one record covering all three, do so. If the center extent is * at the left end of the range, abuts the left extent, and its new * reference count matches the left extent's record, then merge them. * If the center extent is at the right end of the range, abuts the * right extent, and the reference counts match, merge those. In the * example, we can left merge (assuming an increment operation): * * <------ adjustment range ------> * --------+---+-----+-+--+--------+----+---- * 2 | 3 | 2 |1|17| 55 | 10 | 10 * --------+---+-----+-+--+--------+----+---- * ^ * * For all other extents within the range, adjust the reference count * or delete it if the refcount falls below 2. If we were * incrementing, the end result looks like this: * * <------ adjustment range ------> * --------+---+-----+-+--+--------+----+---- * 2 | 4 | 3 |2|18| 56 | 11 | 10 * --------+---+-----+-+--+--------+----+---- * * The result of a decrement operation looks as such: * * <------ adjustment range ------> * ----+ +---+ +--+--------+----+---- * 2 | | 2 | |16| 54 | 9 | 10 * ----+ +---+ +--+--------+----+---- * DDDD 111111DD * * The blocks marked "D" are freed; the blocks marked "1" are only * referenced once and therefore the record is removed from the * refcount btree. */ /* Next block after this extent. */ static inline xfs_agblock_t xfs_refc_next( struct xfs_refcount_irec *rc) { return rc->rc_startblock + rc->rc_blockcount; } /* * Split a refcount extent that crosses agbno. */ STATIC int xfs_refcount_split_extent( struct xfs_btree_cur *cur, xfs_agblock_t agbno, bool *shape_changed) { struct xfs_refcount_irec rcext, tmp; int found_rec; int error; *shape_changed = false; error = xfs_refcount_lookup_le(cur, agbno, &found_rec); if (error) goto out_error; if (!found_rec) return 0; error = xfs_refcount_get_rec(cur, &rcext, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); if (rcext.rc_startblock == agbno || xfs_refc_next(&rcext) <= agbno) return 0; *shape_changed = true; trace_xfs_refcount_split_extent(cur->bc_mp, cur->bc_private.a.agno, &rcext, agbno); /* Establish the right extent. */ tmp = rcext; tmp.rc_startblock = agbno; tmp.rc_blockcount -= (agbno - rcext.rc_startblock); error = xfs_refcount_update(cur, &tmp); if (error) goto out_error; /* Insert the left extent. */ tmp = rcext; tmp.rc_blockcount = agbno - rcext.rc_startblock; error = xfs_refcount_insert(cur, &tmp, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); return error; out_error: trace_xfs_refcount_split_extent_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Merge the left, center, and right extents. */ STATIC int xfs_refcount_merge_center_extents( struct xfs_btree_cur *cur, struct xfs_refcount_irec *left, struct xfs_refcount_irec *center, struct xfs_refcount_irec *right, unsigned long long extlen, xfs_agblock_t *agbno, xfs_extlen_t *aglen) { int error; int found_rec; trace_xfs_refcount_merge_center_extents(cur->bc_mp, cur->bc_private.a.agno, left, center, right); /* * Make sure the center and right extents are not in the btree. * If the center extent was synthesized, the first delete call * removes the right extent and we skip the second deletion. * If center and right were in the btree, then the first delete * call removes the center and the second one removes the right * extent. */ error = xfs_refcount_lookup_ge(cur, center->rc_startblock, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); if (center->rc_refcount > 1) { error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); } /* Enlarge the left extent. */ error = xfs_refcount_lookup_le(cur, left->rc_startblock, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); left->rc_blockcount = extlen; error = xfs_refcount_update(cur, left); if (error) goto out_error; *aglen = 0; return error; out_error: trace_xfs_refcount_merge_center_extents_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Merge with the left extent. */ STATIC int xfs_refcount_merge_left_extent( struct xfs_btree_cur *cur, struct xfs_refcount_irec *left, struct xfs_refcount_irec *cleft, xfs_agblock_t *agbno, xfs_extlen_t *aglen) { int error; int found_rec; trace_xfs_refcount_merge_left_extent(cur->bc_mp, cur->bc_private.a.agno, left, cleft); /* If the extent at agbno (cleft) wasn't synthesized, remove it. */ if (cleft->rc_refcount > 1) { error = xfs_refcount_lookup_le(cur, cleft->rc_startblock, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); } /* Enlarge the left extent. */ error = xfs_refcount_lookup_le(cur, left->rc_startblock, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); left->rc_blockcount += cleft->rc_blockcount; error = xfs_refcount_update(cur, left); if (error) goto out_error; *agbno += cleft->rc_blockcount; *aglen -= cleft->rc_blockcount; return error; out_error: trace_xfs_refcount_merge_left_extent_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Merge with the right extent. */ STATIC int xfs_refcount_merge_right_extent( struct xfs_btree_cur *cur, struct xfs_refcount_irec *right, struct xfs_refcount_irec *cright, xfs_agblock_t *agbno, xfs_extlen_t *aglen) { int error; int found_rec; trace_xfs_refcount_merge_right_extent(cur->bc_mp, cur->bc_private.a.agno, cright, right); /* * If the extent ending at agbno+aglen (cright) wasn't synthesized, * remove it. */ if (cright->rc_refcount > 1) { error = xfs_refcount_lookup_le(cur, cright->rc_startblock, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); } /* Enlarge the right extent. */ error = xfs_refcount_lookup_le(cur, right->rc_startblock, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); right->rc_startblock -= cright->rc_blockcount; right->rc_blockcount += cright->rc_blockcount; error = xfs_refcount_update(cur, right); if (error) goto out_error; *aglen -= cright->rc_blockcount; return error; out_error: trace_xfs_refcount_merge_right_extent_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } #define XFS_FIND_RCEXT_SHARED 1 #define XFS_FIND_RCEXT_COW 2 /* * Find the left extent and the one after it (cleft). This function assumes * that we've already split any extent crossing agbno. */ STATIC int xfs_refcount_find_left_extents( struct xfs_btree_cur *cur, struct xfs_refcount_irec *left, struct xfs_refcount_irec *cleft, xfs_agblock_t agbno, xfs_extlen_t aglen, int flags) { struct xfs_refcount_irec tmp; int error; int found_rec; left->rc_startblock = cleft->rc_startblock = NULLAGBLOCK; error = xfs_refcount_lookup_le(cur, agbno - 1, &found_rec); if (error) goto out_error; if (!found_rec) return 0; error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); if (xfs_refc_next(&tmp) != agbno) return 0; if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2) return 0; if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1) return 0; /* We have a left extent; retrieve (or invent) the next right one */ *left = tmp; error = xfs_btree_increment(cur, 0, &found_rec); if (error) goto out_error; if (found_rec) { error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); /* if tmp starts at the end of our range, just use that */ if (tmp.rc_startblock == agbno) *cleft = tmp; else { /* * There's a gap in the refcntbt at the start of the * range we're interested in (refcount == 1) so * synthesize the implied extent and pass it back. * We assume here that the agbno/aglen range was * passed in from a data fork extent mapping and * therefore is allocated to exactly one owner. */ cleft->rc_startblock = agbno; cleft->rc_blockcount = min(aglen, tmp.rc_startblock - agbno); cleft->rc_refcount = 1; } } else { /* * No extents, so pretend that there's one covering the whole * range. */ cleft->rc_startblock = agbno; cleft->rc_blockcount = aglen; cleft->rc_refcount = 1; } trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_private.a.agno, left, cleft, agbno); return error; out_error: trace_xfs_refcount_find_left_extent_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Find the right extent and the one before it (cright). This function * assumes that we've already split any extents crossing agbno + aglen. */ STATIC int xfs_refcount_find_right_extents( struct xfs_btree_cur *cur, struct xfs_refcount_irec *right, struct xfs_refcount_irec *cright, xfs_agblock_t agbno, xfs_extlen_t aglen, int flags) { struct xfs_refcount_irec tmp; int error; int found_rec; right->rc_startblock = cright->rc_startblock = NULLAGBLOCK; error = xfs_refcount_lookup_ge(cur, agbno + aglen, &found_rec); if (error) goto out_error; if (!found_rec) return 0; error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); if (tmp.rc_startblock != agbno + aglen) return 0; if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2) return 0; if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1) return 0; /* We have a right extent; retrieve (or invent) the next left one */ *right = tmp; error = xfs_btree_decrement(cur, 0, &found_rec); if (error) goto out_error; if (found_rec) { error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); /* if tmp ends at the end of our range, just use that */ if (xfs_refc_next(&tmp) == agbno + aglen) *cright = tmp; else { /* * There's a gap in the refcntbt at the end of the * range we're interested in (refcount == 1) so * create the implied extent and pass it back. * We assume here that the agbno/aglen range was * passed in from a data fork extent mapping and * therefore is allocated to exactly one owner. */ cright->rc_startblock = max(agbno, xfs_refc_next(&tmp)); cright->rc_blockcount = right->rc_startblock - cright->rc_startblock; cright->rc_refcount = 1; } } else { /* * No extents, so pretend that there's one covering the whole * range. */ cright->rc_startblock = agbno; cright->rc_blockcount = aglen; cright->rc_refcount = 1; } trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_private.a.agno, cright, right, agbno + aglen); return error; out_error: trace_xfs_refcount_find_right_extent_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* Is this extent valid? */ static inline bool xfs_refc_valid( struct xfs_refcount_irec *rc) { return rc->rc_startblock != NULLAGBLOCK; } /* * Try to merge with any extents on the boundaries of the adjustment range. */ STATIC int xfs_refcount_merge_extents( struct xfs_btree_cur *cur, xfs_agblock_t *agbno, xfs_extlen_t *aglen, enum xfs_refc_adjust_op adjust, int flags, bool *shape_changed) { struct xfs_refcount_irec left = {0}, cleft = {0}; struct xfs_refcount_irec cright = {0}, right = {0}; int error; unsigned long long ulen; bool cequal; *shape_changed = false; /* * Find the extent just below agbno [left], just above agbno [cleft], * just below (agbno + aglen) [cright], and just above (agbno + aglen) * [right]. */ error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno, *aglen, flags); if (error) return error; error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno, *aglen, flags); if (error) return error; /* No left or right extent to merge; exit. */ if (!xfs_refc_valid(&left) && !xfs_refc_valid(&right)) return 0; cequal = (cleft.rc_startblock == cright.rc_startblock) && (cleft.rc_blockcount == cright.rc_blockcount); /* Try to merge left, cleft, and right. cleft must == cright. */ ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount + right.rc_blockcount; if (xfs_refc_valid(&left) && xfs_refc_valid(&right) && xfs_refc_valid(&cleft) && xfs_refc_valid(&cright) && cequal && left.rc_refcount == cleft.rc_refcount + adjust && right.rc_refcount == cleft.rc_refcount + adjust && ulen < MAXREFCEXTLEN) { *shape_changed = true; return xfs_refcount_merge_center_extents(cur, &left, &cleft, &right, ulen, agbno, aglen); } /* Try to merge left and cleft. */ ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount; if (xfs_refc_valid(&left) && xfs_refc_valid(&cleft) && left.rc_refcount == cleft.rc_refcount + adjust && ulen < MAXREFCEXTLEN) { *shape_changed = true; error = xfs_refcount_merge_left_extent(cur, &left, &cleft, agbno, aglen); if (error) return error; /* * If we just merged left + cleft and cleft == cright, * we no longer have a cright to merge with right. We're done. */ if (cequal) return 0; } /* Try to merge cright and right. */ ulen = (unsigned long long)right.rc_blockcount + cright.rc_blockcount; if (xfs_refc_valid(&right) && xfs_refc_valid(&cright) && right.rc_refcount == cright.rc_refcount + adjust && ulen < MAXREFCEXTLEN) { *shape_changed = true; return xfs_refcount_merge_right_extent(cur, &right, &cright, agbno, aglen); } return error; } /* * While we're adjusting the refcounts records of an extent, we have * to keep an eye on the number of extents we're dirtying -- run too * many in a single transaction and we'll exceed the transaction's * reservation and crash the fs. Each record adds 12 bytes to the * log (plus any key updates) so we'll conservatively assume 24 bytes * per record. We must also leave space for btree splits on both ends * of the range and space for the CUD and a new CUI. * * XXX: This is a pretty hand-wavy estimate. The penalty for guessing * true incorrectly is a shutdown FS; the penalty for guessing false * incorrectly is more transaction rolls than might be necessary. * Be conservative here. */ static bool xfs_refcount_still_have_space( struct xfs_btree_cur *cur) { unsigned long overhead; overhead = cur->bc_private.a.priv.refc.shape_changes * xfs_allocfree_log_count(cur->bc_mp, 1); overhead *= cur->bc_mp->m_sb.sb_blocksize; /* * Only allow 2 refcount extent updates per transaction if the * refcount continue update "error" has been injected. */ if (cur->bc_private.a.priv.refc.nr_ops > 2 && XFS_TEST_ERROR(false, cur->bc_mp, XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE, XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE)) return false; if (cur->bc_private.a.priv.refc.nr_ops == 0) return true; else if (overhead > cur->bc_tp->t_log_res) return false; return cur->bc_tp->t_log_res - overhead > cur->bc_private.a.priv.refc.nr_ops * 32; } /* * Adjust the refcounts of middle extents. At this point we should have * split extents that crossed the adjustment range; merged with adjacent * extents; and updated agbno/aglen to reflect the merges. Therefore, * all we have to do is update the extents inside [agbno, agbno + aglen]. */ STATIC int xfs_refcount_adjust_extents( struct xfs_btree_cur *cur, xfs_agblock_t *agbno, xfs_extlen_t *aglen, enum xfs_refc_adjust_op adj, struct xfs_defer_ops *dfops, struct xfs_owner_info *oinfo) { struct xfs_refcount_irec ext, tmp; int error; int found_rec, found_tmp; xfs_fsblock_t fsbno; /* Merging did all the work already. */ if (*aglen == 0) return 0; error = xfs_refcount_lookup_ge(cur, *agbno, &found_rec); if (error) goto out_error; while (*aglen > 0 && xfs_refcount_still_have_space(cur)) { error = xfs_refcount_get_rec(cur, &ext, &found_rec); if (error) goto out_error; if (!found_rec) { ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks; ext.rc_blockcount = 0; ext.rc_refcount = 0; } /* * Deal with a hole in the refcount tree; if a file maps to * these blocks and there's no refcountbt record, pretend that * there is one with refcount == 1. */ if (ext.rc_startblock != *agbno) { tmp.rc_startblock = *agbno; tmp.rc_blockcount = min(*aglen, ext.rc_startblock - *agbno); tmp.rc_refcount = 1 + adj; trace_xfs_refcount_modify_extent(cur->bc_mp, cur->bc_private.a.agno, &tmp); /* * Either cover the hole (increment) or * delete the range (decrement). */ if (tmp.rc_refcount) { error = xfs_refcount_insert(cur, &tmp, &found_tmp); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_tmp == 1, out_error); cur->bc_private.a.priv.refc.nr_ops++; } else { fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, tmp.rc_startblock); xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, tmp.rc_blockcount, oinfo); } (*agbno) += tmp.rc_blockcount; (*aglen) -= tmp.rc_blockcount; error = xfs_refcount_lookup_ge(cur, *agbno, &found_rec); if (error) goto out_error; } /* Stop if there's nothing left to modify */ if (*aglen == 0 || !xfs_refcount_still_have_space(cur)) break; /* * Adjust the reference count and either update the tree * (incr) or free the blocks (decr). */ if (ext.rc_refcount == MAXREFCOUNT) goto skip; ext.rc_refcount += adj; trace_xfs_refcount_modify_extent(cur->bc_mp, cur->bc_private.a.agno, &ext); if (ext.rc_refcount > 1) { error = xfs_refcount_update(cur, &ext); if (error) goto out_error; cur->bc_private.a.priv.refc.nr_ops++; } else if (ext.rc_refcount == 1) { error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); cur->bc_private.a.priv.refc.nr_ops++; goto advloop; } else { fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, ext.rc_startblock); xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, ext.rc_blockcount, oinfo); } skip: error = xfs_btree_increment(cur, 0, &found_rec); if (error) goto out_error; advloop: (*agbno) += ext.rc_blockcount; (*aglen) -= ext.rc_blockcount; } return error; out_error: trace_xfs_refcount_modify_extent_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* Adjust the reference count of a range of AG blocks. */ STATIC int xfs_refcount_adjust( struct xfs_btree_cur *cur, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *new_agbno, xfs_extlen_t *new_aglen, enum xfs_refc_adjust_op adj, struct xfs_defer_ops *dfops, struct xfs_owner_info *oinfo) { bool shape_changed; int shape_changes = 0; int error; *new_agbno = agbno; *new_aglen = aglen; if (adj == XFS_REFCOUNT_ADJUST_INCREASE) trace_xfs_refcount_increase(cur->bc_mp, cur->bc_private.a.agno, agbno, aglen); else trace_xfs_refcount_decrease(cur->bc_mp, cur->bc_private.a.agno, agbno, aglen); /* * Ensure that no rcextents cross the boundary of the adjustment range. */ error = xfs_refcount_split_extent(cur, agbno, &shape_changed); if (error) goto out_error; if (shape_changed) shape_changes++; error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed); if (error) goto out_error; if (shape_changed) shape_changes++; /* * Try to merge with the left or right extents of the range. */ error = xfs_refcount_merge_extents(cur, new_agbno, new_aglen, adj, XFS_FIND_RCEXT_SHARED, &shape_changed); if (error) goto out_error; if (shape_changed) shape_changes++; if (shape_changes) cur->bc_private.a.priv.refc.shape_changes++; /* Now that we've taken care of the ends, adjust the middle extents */ error = xfs_refcount_adjust_extents(cur, new_agbno, new_aglen, adj, dfops, oinfo); if (error) goto out_error; return 0; out_error: trace_xfs_refcount_adjust_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* Clean up after calling xfs_refcount_finish_one. */ void xfs_refcount_finish_one_cleanup( struct xfs_trans *tp, struct xfs_btree_cur *rcur, int error) { struct xfs_buf *agbp; if (rcur == NULL) return; agbp = rcur->bc_private.a.agbp; xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); if (error) xfs_trans_brelse(tp, agbp); } /* * Process one of the deferred refcount operations. We pass back the * btree cursor to maintain our lock on the btree between calls. * This saves time and eliminates a buffer deadlock between the * superblock and the AGF because we'll always grab them in the same * order. */ int xfs_refcount_finish_one( struct xfs_trans *tp, struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb, xfs_extlen_t *new_len, struct xfs_btree_cur **pcur) { struct xfs_mount *mp = tp->t_mountp; struct xfs_btree_cur *rcur; struct xfs_buf *agbp = NULL; int error = 0; xfs_agnumber_t agno; xfs_agblock_t bno; xfs_agblock_t new_agbno; unsigned long nr_ops = 0; int shape_changes = 0; agno = XFS_FSB_TO_AGNO(mp, startblock); ASSERT(agno != NULLAGNUMBER); bno = XFS_FSB_TO_AGBNO(mp, startblock); trace_xfs_refcount_deferred(mp, XFS_FSB_TO_AGNO(mp, startblock), type, XFS_FSB_TO_AGBNO(mp, startblock), blockcount); if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REFCOUNT_FINISH_ONE, XFS_RANDOM_REFCOUNT_FINISH_ONE)) return -EIO; /* * If we haven't gotten a cursor or the cursor AG doesn't match * the startblock, get one now. */ rcur = *pcur; if (rcur != NULL && rcur->bc_private.a.agno != agno) { nr_ops = rcur->bc_private.a.priv.refc.nr_ops; shape_changes = rcur->bc_private.a.priv.refc.shape_changes; xfs_refcount_finish_one_cleanup(tp, rcur, 0); rcur = NULL; *pcur = NULL; } if (rcur == NULL) { error = xfs_alloc_read_agf(tp->t_mountp, tp, agno, XFS_ALLOC_FLAG_FREEING, &agbp); if (error) return error; if (!agbp) return -EFSCORRUPTED; rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, dfops); if (!rcur) { error = -ENOMEM; goto out_cur; } rcur->bc_private.a.priv.refc.nr_ops = nr_ops; rcur->bc_private.a.priv.refc.shape_changes = shape_changes; } *pcur = rcur; switch (type) { case XFS_REFCOUNT_INCREASE: error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno, new_len, XFS_REFCOUNT_ADJUST_INCREASE, dfops, NULL); *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno); break; case XFS_REFCOUNT_DECREASE: error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno, new_len, XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL); *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno); break; case XFS_REFCOUNT_ALLOC_COW: *new_fsb = startblock + blockcount; *new_len = 0; error = __xfs_refcount_cow_alloc(rcur, bno, blockcount, dfops); break; case XFS_REFCOUNT_FREE_COW: *new_fsb = startblock + blockcount; *new_len = 0; error = __xfs_refcount_cow_free(rcur, bno, blockcount, dfops); break; default: ASSERT(0); error = -EFSCORRUPTED; } if (!error && *new_len > 0) trace_xfs_refcount_finish_one_leftover(mp, agno, type, bno, blockcount, new_agbno, *new_len); return error; out_cur: xfs_trans_brelse(tp, agbp); return error; } /* * Record a refcount intent for later processing. */ static int __xfs_refcount_add( struct xfs_mount *mp, struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount) { struct xfs_refcount_intent *ri; trace_xfs_refcount_defer(mp, XFS_FSB_TO_AGNO(mp, startblock), type, XFS_FSB_TO_AGBNO(mp, startblock), blockcount); ri = kmem_alloc(sizeof(struct xfs_refcount_intent), KM_SLEEP | KM_NOFS); INIT_LIST_HEAD(&ri->ri_list); ri->ri_type = type; ri->ri_startblock = startblock; ri->ri_blockcount = blockcount; xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list); return 0; } /* * Increase the reference count of the blocks backing a file's extent. */ int xfs_refcount_increase_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *PREV) { if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_INCREASE, PREV->br_startblock, PREV->br_blockcount); } /* * Decrease the reference count of the blocks backing a file's extent. */ int xfs_refcount_decrease_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *PREV) { if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_DECREASE, PREV->br_startblock, PREV->br_blockcount); } /* * Given an AG extent, find the lowest-numbered run of shared blocks * within that range and return the range in fbno/flen. If * find_end_of_shared is set, return the longest contiguous extent of * shared blocks; if not, just return the first extent we find. If no * shared blocks are found, fbno and flen will be set to NULLAGBLOCK * and 0, respectively. */ int xfs_refcount_find_shared( struct xfs_btree_cur *cur, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_end_of_shared) { struct xfs_refcount_irec tmp; int i; int have; int error; trace_xfs_refcount_find_shared(cur->bc_mp, cur->bc_private.a.agno, agbno, aglen); /* By default, skip the whole range */ *fbno = NULLAGBLOCK; *flen = 0; /* Try to find a refcount extent that crosses the start */ error = xfs_refcount_lookup_le(cur, agbno, &have); if (error) goto out_error; if (!have) { /* No left extent, look at the next one */ error = xfs_btree_increment(cur, 0, &have); if (error) goto out_error; if (!have) goto done; } error = xfs_refcount_get_rec(cur, &tmp, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); /* If the extent ends before the start, look at the next one */ if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) { error = xfs_btree_increment(cur, 0, &have); if (error) goto out_error; if (!have) goto done; error = xfs_refcount_get_rec(cur, &tmp, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); } /* If the extent starts after the range we want, bail out */ if (tmp.rc_startblock >= agbno + aglen) goto done; /* We found the start of a shared extent! */ if (tmp.rc_startblock < agbno) { tmp.rc_blockcount -= (agbno - tmp.rc_startblock); tmp.rc_startblock = agbno; } *fbno = tmp.rc_startblock; *flen = min(tmp.rc_blockcount, agbno + aglen - *fbno); if (!find_end_of_shared) goto done; /* Otherwise, find the end of this shared extent */ while (*fbno + *flen < agbno + aglen) { error = xfs_btree_increment(cur, 0, &have); if (error) goto out_error; if (!have) break; error = xfs_refcount_get_rec(cur, &tmp, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); if (tmp.rc_startblock >= agbno + aglen || tmp.rc_startblock != *fbno + *flen) break; *flen = min(*flen + tmp.rc_blockcount, agbno + aglen - *fbno); } done: trace_xfs_refcount_find_shared_result(cur->bc_mp, cur->bc_private.a.agno, *fbno, *flen); out_error: if (error) trace_xfs_refcount_find_shared_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Recovering CoW Blocks After a Crash * * Due to the way that the copy on write mechanism works, there's a window of * opportunity in which we can lose track of allocated blocks during a crash. * Because CoW uses delayed allocation in the in-core CoW fork, writeback * causes blocks to be allocated and stored in the CoW fork. The blocks are * no longer in the free space btree but are not otherwise recorded anywhere * until the write completes and the blocks are mapped into the file. A crash * in between allocation and remapping results in the replacement blocks being * lost. This situation is exacerbated by the CoW extent size hint because * allocations can hang around for long time. * * However, there is a place where we can record these allocations before they * become mappings -- the reference count btree. The btree does not record * extents with refcount == 1, so we can record allocations with a refcount of * 1. Blocks being used for CoW writeout cannot be shared, so there should be * no conflict with shared block records. These mappings should be created * when we allocate blocks to the CoW fork and deleted when they're removed * from the CoW fork. * * Minor nit: records for in-progress CoW allocations and records for shared * extents must never be merged, to preserve the property that (except for CoW * allocations) there are no refcount btree entries with refcount == 1. The * only time this could potentially happen is when unsharing a block that's * adjacent to CoW allocations, so we must be careful to avoid this. * * At mount time we recover lost CoW allocations by searching the refcount * btree for these refcount == 1 mappings. These represent CoW allocations * that were in progress at the time the filesystem went down, so we can free * them to get the space back. * * This mechanism is superior to creating EFIs for unmapped CoW extents for * several reasons -- first, EFIs pin the tail of the log and would have to be * periodically relogged to avoid filling up the log. Second, CoW completions * will have to file an EFD and create new EFIs for whatever remains in the * CoW fork; this partially takes care of (1) but extent-size reservations * will have to periodically relog even if there's no writeout in progress. * This can happen if the CoW extent size hint is set, which you really want. * Third, EFIs cannot currently be automatically relogged into newer * transactions to advance the log tail. Fourth, stuffing the log full of * EFIs places an upper bound on the number of CoW allocations that can be * held filesystem-wide at any given time. Recording them in the refcount * btree doesn't require us to maintain any state in memory and doesn't pin * the log. */ /* * Adjust the refcounts of CoW allocations. These allocations are "magic" * in that they're not referenced anywhere else in the filesystem, so we * stash them in the refcount btree with a refcount of 1 until either file * remapping (or CoW cancellation) happens. */ STATIC int xfs_refcount_adjust_cow_extents( struct xfs_btree_cur *cur, xfs_agblock_t agbno, xfs_extlen_t aglen, enum xfs_refc_adjust_op adj, struct xfs_defer_ops *dfops, struct xfs_owner_info *oinfo) { struct xfs_refcount_irec ext, tmp; int error; int found_rec, found_tmp; if (aglen == 0) return 0; /* Find any overlapping refcount records */ error = xfs_refcount_lookup_ge(cur, agbno, &found_rec); if (error) goto out_error; error = xfs_refcount_get_rec(cur, &ext, &found_rec); if (error) goto out_error; if (!found_rec) { ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks + XFS_REFC_COW_START; ext.rc_blockcount = 0; ext.rc_refcount = 0; } switch (adj) { case XFS_REFCOUNT_ADJUST_COW_ALLOC: /* Adding a CoW reservation, there should be nothing here. */ XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, ext.rc_startblock >= agbno + aglen, out_error); tmp.rc_startblock = agbno; tmp.rc_blockcount = aglen; tmp.rc_refcount = 1; trace_xfs_refcount_modify_extent(cur->bc_mp, cur->bc_private.a.agno, &tmp); error = xfs_refcount_insert(cur, &tmp, &found_tmp); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_tmp == 1, out_error); break; case XFS_REFCOUNT_ADJUST_COW_FREE: /* Removing a CoW reservation, there should be one extent. */ XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, ext.rc_startblock == agbno, out_error); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, ext.rc_blockcount == aglen, out_error); XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, ext.rc_refcount == 1, out_error); ext.rc_refcount = 0; trace_xfs_refcount_modify_extent(cur->bc_mp, cur->bc_private.a.agno, &ext); error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); break; default: ASSERT(0); } return error; out_error: trace_xfs_refcount_modify_extent_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Add or remove refcount btree entries for CoW reservations. */ STATIC int xfs_refcount_adjust_cow( struct xfs_btree_cur *cur, xfs_agblock_t agbno, xfs_extlen_t aglen, enum xfs_refc_adjust_op adj, struct xfs_defer_ops *dfops) { bool shape_changed; int error; agbno += XFS_REFC_COW_START; /* * Ensure that no rcextents cross the boundary of the adjustment range. */ error = xfs_refcount_split_extent(cur, agbno, &shape_changed); if (error) goto out_error; error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed); if (error) goto out_error; /* * Try to merge with the left or right extents of the range. */ error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj, XFS_FIND_RCEXT_COW, &shape_changed); if (error) goto out_error; /* Now that we've taken care of the ends, adjust the middle extents */ error = xfs_refcount_adjust_cow_extents(cur, agbno, aglen, adj, dfops, NULL); if (error) goto out_error; return 0; out_error: trace_xfs_refcount_adjust_cow_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Record a CoW allocation in the refcount btree. */ STATIC int __xfs_refcount_cow_alloc( struct xfs_btree_cur *rcur, xfs_agblock_t agbno, xfs_extlen_t aglen, struct xfs_defer_ops *dfops) { int error; trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_private.a.agno, agbno, aglen); /* Add refcount btree reservation */ error = xfs_refcount_adjust_cow(rcur, agbno, aglen, XFS_REFCOUNT_ADJUST_COW_ALLOC, dfops); if (error) return error; /* Add rmap entry */ if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { error = xfs_rmap_alloc_extent(rcur->bc_mp, dfops, rcur->bc_private.a.agno, agbno, aglen, XFS_RMAP_OWN_COW); if (error) return error; } return error; } /* * Remove a CoW allocation from the refcount btree. */ STATIC int __xfs_refcount_cow_free( struct xfs_btree_cur *rcur, xfs_agblock_t agbno, xfs_extlen_t aglen, struct xfs_defer_ops *dfops) { int error; trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_private.a.agno, agbno, aglen); /* Remove refcount btree reservation */ error = xfs_refcount_adjust_cow(rcur, agbno, aglen, XFS_REFCOUNT_ADJUST_COW_FREE, dfops); if (error) return error; /* Remove rmap entry */ if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { error = xfs_rmap_free_extent(rcur->bc_mp, dfops, rcur->bc_private.a.agno, agbno, aglen, XFS_RMAP_OWN_COW); if (error) return error; } return error; } /* Record a CoW staging extent in the refcount btree. */ int xfs_refcount_alloc_cow_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, xfs_extlen_t len) { if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_ALLOC_COW, fsb, len); } /* Forget a CoW staging event in the refcount btree. */ int xfs_refcount_free_cow_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, xfs_extlen_t len) { if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_FREE_COW, fsb, len); } struct xfs_refcount_recovery { struct list_head rr_list; struct xfs_refcount_irec rr_rrec; }; /* Stuff an extent on the recovery list. */ STATIC int xfs_refcount_recover_extent( struct xfs_btree_cur *cur, union xfs_btree_rec *rec, void *priv) { struct list_head *debris = priv; struct xfs_refcount_recovery *rr; if (be32_to_cpu(rec->refc.rc_refcount) != 1) return -EFSCORRUPTED; rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), KM_SLEEP); xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec); list_add_tail(&rr->rr_list, debris); return 0; } /* Find and remove leftover CoW reservations. */ int xfs_refcount_recover_cow_leftovers( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_trans *tp; struct xfs_btree_cur *cur; struct xfs_buf *agbp; struct xfs_refcount_recovery *rr, *n; struct list_head debris; union xfs_btree_irec low; union xfs_btree_irec high; struct xfs_defer_ops dfops; xfs_fsblock_t fsb; xfs_agblock_t agbno; int error; if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START) return -EOPNOTSUPP; error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) return error; cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); /* Find all the leftover CoW staging extents. */ INIT_LIST_HEAD(&debris); memset(&low, 0, sizeof(low)); memset(&high, 0, sizeof(high)); low.rc.rc_startblock = XFS_REFC_COW_START; high.rc.rc_startblock = -1U; error = xfs_btree_query_range(cur, &low, &high, xfs_refcount_recover_extent, &debris); if (error) goto out_cursor; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); xfs_buf_relse(agbp); /* Now iterate the list to free the leftovers */ list_for_each_entry(rr, &debris, rr_list) { /* Set up transaction. */ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); if (error) goto out_free; trace_xfs_refcount_recover_extent(mp, agno, &rr->rr_rrec); /* Free the orphan record */ xfs_defer_init(&dfops, &fsb); agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START; fsb = XFS_AGB_TO_FSB(mp, agno, agbno); error = xfs_refcount_free_cow_extent(mp, &dfops, fsb, rr->rr_rrec.rc_blockcount); if (error) goto out_defer; /* Free the block. */ xfs_bmap_add_free(mp, &dfops, fsb, rr->rr_rrec.rc_blockcount, NULL); error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out_defer; error = xfs_trans_commit(tp); if (error) goto out_free; } out_free: /* Free the leftover list */ list_for_each_entry_safe(rr, n, &debris, rr_list) { list_del(&rr->rr_list); kmem_free(rr); } return error; out_cursor: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); xfs_buf_relse(agbp); goto out_free; out_defer: xfs_defer_cancel(&dfops); xfs_trans_cancel(tp); goto out_free; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_refcount.h0000644000000000000000000000515213033541503016633 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __XFS_REFCOUNT_H__ #define __XFS_REFCOUNT_H__ extern int xfs_refcount_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, int *stat); extern int xfs_refcount_lookup_ge(struct xfs_btree_cur *cur, xfs_agblock_t bno, int *stat); extern int xfs_refcount_get_rec(struct xfs_btree_cur *cur, struct xfs_refcount_irec *irec, int *stat); enum xfs_refcount_intent_type { XFS_REFCOUNT_INCREASE = 1, XFS_REFCOUNT_DECREASE, XFS_REFCOUNT_ALLOC_COW, XFS_REFCOUNT_FREE_COW, }; struct xfs_refcount_intent { struct list_head ri_list; enum xfs_refcount_intent_type ri_type; xfs_fsblock_t ri_startblock; xfs_extlen_t ri_blockcount; }; extern int xfs_refcount_increase_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); extern int xfs_refcount_decrease_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp, struct xfs_btree_cur *rcur, int error); extern int xfs_refcount_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb, xfs_extlen_t *new_len, struct xfs_btree_cur **pcur); extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_end_of_shared); extern int xfs_refcount_alloc_cow_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, xfs_extlen_t len); extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, xfs_extlen_t len); extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp, xfs_agnumber_t agno); #endif /* __XFS_REFCOUNT_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_refcount_btree.c0000644000000000000000000002603213033541503020007 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_btree.h" #include "xfs_bmap.h" #include "xfs_refcount_btree.h" #include "xfs_alloc.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_bit.h" #include "xfs_rmap.h" static struct xfs_btree_cur * xfs_refcountbt_dup_cursor( struct xfs_btree_cur *cur) { return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agbp, cur->bc_private.a.agno, cur->bc_private.a.dfops); } STATIC void xfs_refcountbt_set_root( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr, int inc) { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); ASSERT(ptr->s != 0); agf->agf_refcount_root = ptr->s; be32_add_cpu(&agf->agf_refcount_level, inc); pag->pagf_refcount_level += inc; xfs_perag_put(pag); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_ROOT | XFS_AGF_REFCOUNT_LEVEL); } STATIC int xfs_refcountbt_alloc_block( struct xfs_btree_cur *cur, union xfs_btree_ptr *start, union xfs_btree_ptr *new, int *stat) { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); struct xfs_alloc_arg args; /* block allocation args */ int error; /* error return value */ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); memset(&args, 0, sizeof(args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; args.type = XFS_ALLOCTYPE_NEAR_BNO; args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, xfs_refc_block(args.mp)); args.firstblock = args.fsbno; xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); args.minlen = args.maxlen = args.prod = 1; args.resv = XFS_AG_RESV_METADATA; error = xfs_alloc_vextent(&args); if (error) goto out_error; trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, args.agbno, 1); if (args.fsbno == NULLFSBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } ASSERT(args.agno == cur->bc_private.a.agno); ASSERT(args.len == 1); new->s = cpu_to_be32(args.agbno); be32_add_cpu(&agf->agf_refcount_blocks, 1); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; out_error: XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } STATIC int xfs_refcountbt_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { struct xfs_mount *mp = cur->bc_mp; struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); struct xfs_owner_info oinfo; int error; trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); be32_add_cpu(&agf->agf_refcount_blocks, -1); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); error = xfs_free_extent(cur->bc_tp, fsbno, 1, &oinfo, XFS_AG_RESV_METADATA); if (error) return error; return error; } STATIC int xfs_refcountbt_get_minrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_refc_mnr[level != 0]; } STATIC int xfs_refcountbt_get_maxrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_refc_mxr[level != 0]; } STATIC void xfs_refcountbt_init_key_from_rec( union xfs_btree_key *key, union xfs_btree_rec *rec) { key->refc.rc_startblock = rec->refc.rc_startblock; } STATIC void xfs_refcountbt_init_high_key_from_rec( union xfs_btree_key *key, union xfs_btree_rec *rec) { __u32 x; x = be32_to_cpu(rec->refc.rc_startblock); x += be32_to_cpu(rec->refc.rc_blockcount) - 1; key->refc.rc_startblock = cpu_to_be32(x); } STATIC void xfs_refcountbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) { rec->refc.rc_startblock = cpu_to_be32(cur->bc_rec.rc.rc_startblock); rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount); rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount); } STATIC void xfs_refcountbt_init_ptr_from_cur( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); ASSERT(agf->agf_refcount_root != 0); ptr->s = agf->agf_refcount_root; } STATIC __int64_t xfs_refcountbt_key_diff( struct xfs_btree_cur *cur, union xfs_btree_key *key) { struct xfs_refcount_irec *rec = &cur->bc_rec.rc; struct xfs_refcount_key *kp = &key->refc; return (__int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock; } STATIC __int64_t xfs_refcountbt_diff_two_keys( struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2) { return (__int64_t)be32_to_cpu(k1->refc.rc_startblock) - be32_to_cpu(k2->refc.rc_startblock); } STATIC bool xfs_refcountbt_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_perag *pag = bp->b_pag; unsigned int level; if (block->bb_magic != cpu_to_be32(XFS_REFC_CRC_MAGIC)) return false; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; level = be16_to_cpu(block->bb_level); if (pag && pag->pagf_init) { if (level >= pag->pagf_refcount_level) return false; } else if (level >= mp->m_refc_maxlevels) return false; return xfs_btree_sblock_verify(bp, mp->m_refc_mxr[level != 0]); } STATIC void xfs_refcountbt_read_verify( struct xfs_buf *bp) { if (!xfs_btree_sblock_verify_crc(bp)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_refcountbt_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_verifier_error(bp); } } STATIC void xfs_refcountbt_write_verify( struct xfs_buf *bp) { if (!xfs_refcountbt_verify(bp)) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } xfs_btree_sblock_calc_crc(bp); } const struct xfs_buf_ops xfs_refcountbt_buf_ops = { .name = "xfs_refcountbt", .verify_read = xfs_refcountbt_read_verify, .verify_write = xfs_refcountbt_write_verify, }; #if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_refcountbt_keys_inorder( struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2) { return be32_to_cpu(k1->refc.rc_startblock) < be32_to_cpu(k2->refc.rc_startblock); } STATIC int xfs_refcountbt_recs_inorder( struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2) { return be32_to_cpu(r1->refc.rc_startblock) + be32_to_cpu(r1->refc.rc_blockcount) <= be32_to_cpu(r2->refc.rc_startblock); } #endif static const struct xfs_btree_ops xfs_refcountbt_ops = { .rec_len = sizeof(struct xfs_refcount_rec), .key_len = sizeof(struct xfs_refcount_key), .dup_cursor = xfs_refcountbt_dup_cursor, .set_root = xfs_refcountbt_set_root, .alloc_block = xfs_refcountbt_alloc_block, .free_block = xfs_refcountbt_free_block, .get_minrecs = xfs_refcountbt_get_minrecs, .get_maxrecs = xfs_refcountbt_get_maxrecs, .init_key_from_rec = xfs_refcountbt_init_key_from_rec, .init_high_key_from_rec = xfs_refcountbt_init_high_key_from_rec, .init_rec_from_cur = xfs_refcountbt_init_rec_from_cur, .init_ptr_from_cur = xfs_refcountbt_init_ptr_from_cur, .key_diff = xfs_refcountbt_key_diff, .buf_ops = &xfs_refcountbt_buf_ops, .diff_two_keys = xfs_refcountbt_diff_two_keys, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_refcountbt_keys_inorder, .recs_inorder = xfs_refcountbt_recs_inorder, #endif }; /* * Allocate a new refcount btree cursor. */ struct xfs_btree_cur * xfs_refcountbt_init_cursor( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, struct xfs_defer_ops *dfops) { struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); struct xfs_btree_cur *cur; ASSERT(agno != NULLAGNUMBER); ASSERT(agno < mp->m_sb.sb_agcount); cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); cur->bc_tp = tp; cur->bc_mp = mp; cur->bc_btnum = XFS_BTNUM_REFC; cur->bc_blocklog = mp->m_sb.sb_blocklog; cur->bc_ops = &xfs_refcountbt_ops; cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; cur->bc_private.a.dfops = dfops; cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; cur->bc_private.a.priv.refc.nr_ops = 0; cur->bc_private.a.priv.refc.shape_changes = 0; return cur; } /* * Calculate the number of records in a refcount btree block. */ int xfs_refcountbt_maxrecs( struct xfs_mount *mp, int blocklen, bool leaf) { blocklen -= XFS_REFCOUNT_BLOCK_LEN; if (leaf) return blocklen / sizeof(struct xfs_refcount_rec); return blocklen / (sizeof(struct xfs_refcount_key) + sizeof(xfs_refcount_ptr_t)); } /* Compute the maximum height of a refcount btree. */ void xfs_refcountbt_compute_maxlevels( struct xfs_mount *mp) { mp->m_refc_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_refc_mnr, mp->m_sb.sb_agblocks); } /* Calculate the refcount btree size for some records. */ xfs_extlen_t xfs_refcountbt_calc_size( struct xfs_mount *mp, unsigned long long len) { return xfs_btree_calc_size(mp, mp->m_refc_mnr, len); } /* * Calculate the maximum refcount btree size. */ xfs_extlen_t xfs_refcountbt_max_size( struct xfs_mount *mp) { /* Bail out if we're uninitialized, which can happen in mkfs. */ if (mp->m_refc_mxr[0] == 0) return 0; return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); } /* * Figure out how many blocks to reserve and how many are used by this btree. */ int xfs_refcountbt_calc_reserves( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used) { struct xfs_buf *agbp; struct xfs_agf *agf; xfs_extlen_t tree_len; int error; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; *ask += xfs_refcountbt_max_size(mp); error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) return error; agf = XFS_BUF_TO_AGF(agbp); tree_len = be32_to_cpu(agf->agf_refcount_blocks); xfs_buf_relse(agbp); *used += tree_len; return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_refcount_btree.h0000644000000000000000000000472013033541503020014 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __XFS_REFCOUNT_BTREE_H__ #define __XFS_REFCOUNT_BTREE_H__ /* * Reference Count Btree on-disk structures */ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; /* * Btree block header size */ #define XFS_REFCOUNT_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN /* * Record, key, and pointer address macros for btree blocks. * * (note that some of these may appear unused, but they are used in userspace) */ #define XFS_REFCOUNT_REC_ADDR(block, index) \ ((struct xfs_refcount_rec *) \ ((char *)(block) + \ XFS_REFCOUNT_BLOCK_LEN + \ (((index) - 1) * sizeof(struct xfs_refcount_rec)))) #define XFS_REFCOUNT_KEY_ADDR(block, index) \ ((struct xfs_refcount_key *) \ ((char *)(block) + \ XFS_REFCOUNT_BLOCK_LEN + \ ((index) - 1) * sizeof(struct xfs_refcount_key))) #define XFS_REFCOUNT_PTR_ADDR(block, index, maxrecs) \ ((xfs_refcount_ptr_t *) \ ((char *)(block) + \ XFS_REFCOUNT_BLOCK_LEN + \ (maxrecs) * sizeof(struct xfs_refcount_key) + \ ((index) - 1) * sizeof(xfs_refcount_ptr_t))) extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, struct xfs_defer_ops *dfops); extern int xfs_refcountbt_maxrecs(struct xfs_mount *mp, int blocklen, bool leaf); extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, unsigned long long len); extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); #endif /* __XFS_REFCOUNT_BTREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_rmap.c0000644000000000000000000017432213033541503015746 0ustar /* * Copyright (c) 2014 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_btree.h" #include "xfs_trans.h" #include "xfs_alloc.h" #include "xfs_rmap.h" #include "xfs_rmap_btree.h" #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_bmap.h" #include "xfs_inode.h" /* * Lookup the first record less than or equal to [bno, len, owner, offset] * in the btree given by cur. */ int xfs_rmap_lookup_le( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags, int *stat) { cur->bc_rec.r.rm_startblock = bno; cur->bc_rec.r.rm_blockcount = len; cur->bc_rec.r.rm_owner = owner; cur->bc_rec.r.rm_offset = offset; cur->bc_rec.r.rm_flags = flags; return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); } /* * Lookup the record exactly matching [bno, len, owner, offset] * in the btree given by cur. */ int xfs_rmap_lookup_eq( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags, int *stat) { cur->bc_rec.r.rm_startblock = bno; cur->bc_rec.r.rm_blockcount = len; cur->bc_rec.r.rm_owner = owner; cur->bc_rec.r.rm_offset = offset; cur->bc_rec.r.rm_flags = flags; return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); } /* * Update the record referred to by cur to the value given * by [bno, len, owner, offset]. * This either works (return 0) or gets an EFSCORRUPTED error. */ STATIC int xfs_rmap_update( struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec) { union xfs_btree_rec rec; int error; trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno, irec->rm_startblock, irec->rm_blockcount, irec->rm_owner, irec->rm_offset, irec->rm_flags); rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock); rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount); rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner); rec.rmap.rm_offset = cpu_to_be64( xfs_rmap_irec_offset_pack(irec)); error = xfs_btree_update(cur, &rec); if (error) trace_xfs_rmap_update_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } int xfs_rmap_insert( struct xfs_btree_cur *rcur, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags) { int i; int error; trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno, len, owner, offset, flags); error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done); rcur->bc_rec.r.rm_startblock = agbno; rcur->bc_rec.r.rm_blockcount = len; rcur->bc_rec.r.rm_owner = owner; rcur->bc_rec.r.rm_offset = offset; rcur->bc_rec.r.rm_flags = flags; error = xfs_btree_insert(rcur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); done: if (error) trace_xfs_rmap_insert_error(rcur->bc_mp, rcur->bc_private.a.agno, error, _RET_IP_); return error; } STATIC int xfs_rmap_delete( struct xfs_btree_cur *rcur, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags) { int i; int error; trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno, len, owner, offset, flags); error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); error = xfs_btree_delete(rcur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); done: if (error) trace_xfs_rmap_delete_error(rcur->bc_mp, rcur->bc_private.a.agno, error, _RET_IP_); return error; } static int xfs_rmap_btrec_to_irec( union xfs_btree_rec *rec, struct xfs_rmap_irec *irec) { irec->rm_flags = 0; irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock); irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount); irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner); return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset), irec); } /* * Get the data from the pointed-to record. */ int xfs_rmap_get_rec( struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat) { union xfs_btree_rec *rec; int error; error = xfs_btree_get_rec(cur, &rec, stat); if (error || !*stat) return error; return xfs_rmap_btrec_to_irec(rec, irec); } struct xfs_find_left_neighbor_info { struct xfs_rmap_irec high; struct xfs_rmap_irec *irec; int *stat; }; /* For each rmap given, figure out if it matches the key we want. */ STATIC int xfs_rmap_find_left_neighbor_helper( struct xfs_btree_cur *cur, struct xfs_rmap_irec *rec, void *priv) { struct xfs_find_left_neighbor_info *info = priv; trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, cur->bc_private.a.agno, rec->rm_startblock, rec->rm_blockcount, rec->rm_owner, rec->rm_offset, rec->rm_flags); if (rec->rm_owner != info->high.rm_owner) return XFS_BTREE_QUERY_RANGE_CONTINUE; if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) return XFS_BTREE_QUERY_RANGE_CONTINUE; *info->irec = *rec; *info->stat = 1; return XFS_BTREE_QUERY_RANGE_ABORT; } /* * Find the record to the left of the given extent, being careful only to * return a match with the same owner and adjacent physical and logical * block ranges. */ int xfs_rmap_find_left_neighbor( struct xfs_btree_cur *cur, xfs_agblock_t bno, uint64_t owner, uint64_t offset, unsigned int flags, struct xfs_rmap_irec *irec, int *stat) { struct xfs_find_left_neighbor_info info; int error; *stat = 0; if (bno == 0) return 0; info.high.rm_startblock = bno - 1; info.high.rm_owner = owner; if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) { if (offset == 0) return 0; info.high.rm_offset = offset - 1; } else info.high.rm_offset = 0; info.high.rm_flags = flags; info.high.rm_blockcount = 0; info.irec = irec; info.stat = stat; trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, cur->bc_private.a.agno, bno, 0, owner, offset, flags); error = xfs_rmap_query_range(cur, &info.high, &info.high, xfs_rmap_find_left_neighbor_helper, &info); if (error == XFS_BTREE_QUERY_RANGE_ABORT) error = 0; if (*stat) trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, irec->rm_startblock, irec->rm_blockcount, irec->rm_owner, irec->rm_offset, irec->rm_flags); return error; } /* For each rmap given, figure out if it matches the key we want. */ STATIC int xfs_rmap_lookup_le_range_helper( struct xfs_btree_cur *cur, struct xfs_rmap_irec *rec, void *priv) { struct xfs_find_left_neighbor_info *info = priv; trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, cur->bc_private.a.agno, rec->rm_startblock, rec->rm_blockcount, rec->rm_owner, rec->rm_offset, rec->rm_flags); if (rec->rm_owner != info->high.rm_owner) return XFS_BTREE_QUERY_RANGE_CONTINUE; if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && (rec->rm_offset > info->high.rm_offset || rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) return XFS_BTREE_QUERY_RANGE_CONTINUE; *info->irec = *rec; *info->stat = 1; return XFS_BTREE_QUERY_RANGE_ABORT; } /* * Find the record to the left of the given extent, being careful only to * return a match with the same owner and overlapping physical and logical * block ranges. This is the overlapping-interval version of * xfs_rmap_lookup_le. */ int xfs_rmap_lookup_le_range( struct xfs_btree_cur *cur, xfs_agblock_t bno, uint64_t owner, uint64_t offset, unsigned int flags, struct xfs_rmap_irec *irec, int *stat) { struct xfs_find_left_neighbor_info info; int error; info.high.rm_startblock = bno; info.high.rm_owner = owner; if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) info.high.rm_offset = offset; else info.high.rm_offset = 0; info.high.rm_flags = flags; info.high.rm_blockcount = 0; *stat = 0; info.irec = irec; info.stat = stat; trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_private.a.agno, bno, 0, owner, offset, flags); error = xfs_rmap_query_range(cur, &info.high, &info.high, xfs_rmap_lookup_le_range_helper, &info); if (error == XFS_BTREE_QUERY_RANGE_ABORT) error = 0; if (*stat) trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, cur->bc_private.a.agno, irec->rm_startblock, irec->rm_blockcount, irec->rm_owner, irec->rm_offset, irec->rm_flags); return error; } /* * Find the extent in the rmap btree and remove it. * * The record we find should always be an exact match for the extent that we're * looking for, since we insert them into the btree without modification. * * Special Case #1: when growing the filesystem, we "free" an extent when * growing the last AG. This extent is new space and so it is not tracked as * used space in the btree. The growfs code will pass in an owner of * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this * extent. We verify that - the extent lookup result in a record that does not * overlap. * * Special Case #2: EFIs do not record the owner of the extent, so when * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap * btree to ignore the owner (i.e. wildcard match) so we don't trigger * corruption checks during log recovery. */ STATIC int xfs_rmap_unmap( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool unwritten, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = cur->bc_mp; struct xfs_rmap_irec ltrec; uint64_t ltoff; int error = 0; int i; uint64_t owner; uint64_t offset; unsigned int flags; bool ignore_off; xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || (flags & XFS_RMAP_BMBT_BLOCK); if (unwritten) flags |= XFS_RMAP_UNWRITTEN; trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); /* * We should always have a left record because there's a static record * for the AG headers at rm_startblock == 0 created by mkfs/growfs that * will not ever be removed from the tree. */ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); error = xfs_rmap_get_rec(cur, <rec, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, cur->bc_private.a.agno, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags); ltoff = ltrec.rm_offset; /* * For growfs, the incoming extent must be beyond the left record we * just found as it is new space and won't be used by anyone. This is * just a corruption check as we don't actually do anything with this * extent. Note that we need to use >= instead of > because it might * be the case that the "left" extent goes all the way to EOFS. */ if (owner == XFS_RMAP_OWN_NULL) { XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock + ltrec.rm_blockcount, out_error); goto out_done; } /* Make sure the unwritten flag matches. */ XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); /* Make sure the extent we found covers the entire freeing range. */ XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && ltrec.rm_startblock + ltrec.rm_blockcount >= bno + len, out_error); /* Make sure the owner matches what we expect to find in the tree. */ XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner || XFS_RMAP_NON_INODE_OWNER(owner), out_error); /* Check the offset, if necessary. */ if (!XFS_RMAP_NON_INODE_OWNER(owner)) { if (flags & XFS_RMAP_BMBT_BLOCK) { XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK, out_error); } else { XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error); XFS_WANT_CORRUPTED_GOTO(mp, ltoff + ltrec.rm_blockcount >= offset + len, out_error); } } if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { /* exact match, simply remove the record from rmap tree */ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags); error = xfs_btree_delete(cur, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); } else if (ltrec.rm_startblock == bno) { /* * overlap left hand side of extent: move the start, trim the * length and update the current record. * * ltbno ltlen * Orig: |oooooooooooooooooooo| * Freeing: |fffffffff| * Result: |rrrrrrrrrr| * bno len */ ltrec.rm_startblock += len; ltrec.rm_blockcount -= len; if (!ignore_off) ltrec.rm_offset += len; error = xfs_rmap_update(cur, <rec); if (error) goto out_error; } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { /* * overlap right hand side of extent: trim the length and update * the current record. * * ltbno ltlen * Orig: |oooooooooooooooooooo| * Freeing: |fffffffff| * Result: |rrrrrrrrrr| * bno len */ ltrec.rm_blockcount -= len; error = xfs_rmap_update(cur, <rec); if (error) goto out_error; } else { /* * overlap middle of extent: trim the length of the existing * record to the length of the new left-extent size, increment * the insertion position so we can insert a new record * containing the remaining right-extent space. * * ltbno ltlen * Orig: |oooooooooooooooooooo| * Freeing: |fffffffff| * Result: |rrrrr| |rrrr| * bno len */ xfs_extlen_t orig_len = ltrec.rm_blockcount; ltrec.rm_blockcount = bno - ltrec.rm_startblock; error = xfs_rmap_update(cur, <rec); if (error) goto out_error; error = xfs_btree_increment(cur, 0, &i); if (error) goto out_error; cur->bc_rec.r.rm_startblock = bno + len; cur->bc_rec.r.rm_blockcount = orig_len - len - ltrec.rm_blockcount; cur->bc_rec.r.rm_owner = ltrec.rm_owner; if (ignore_off) cur->bc_rec.r.rm_offset = 0; else cur->bc_rec.r.rm_offset = offset + len; cur->bc_rec.r.rm_flags = flags; trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, cur->bc_rec.r.rm_startblock, cur->bc_rec.r.rm_blockcount, cur->bc_rec.r.rm_owner, cur->bc_rec.r.rm_offset, cur->bc_rec.r.rm_flags); error = xfs_btree_insert(cur, &i); if (error) goto out_error; } out_done: trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); out_error: if (error) trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Remove a reference to an extent in the rmap btree. */ int xfs_rmap_free( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = tp->t_mountp; struct xfs_btree_cur *cur; int error; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); error = xfs_rmap_unmap(cur, bno, len, false, oinfo); if (error) goto out_error; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; out_error: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } /* * A mergeable rmap must have the same owner and the same values for * the unwritten, attr_fork, and bmbt flags. The startblock and * offset are checked separately. */ static bool xfs_rmap_is_mergeable( struct xfs_rmap_irec *irec, uint64_t owner, unsigned int flags) { if (irec->rm_owner == XFS_RMAP_OWN_NULL) return false; if (irec->rm_owner != owner) return false; if ((flags & XFS_RMAP_UNWRITTEN) ^ (irec->rm_flags & XFS_RMAP_UNWRITTEN)) return false; if ((flags & XFS_RMAP_ATTR_FORK) ^ (irec->rm_flags & XFS_RMAP_ATTR_FORK)) return false; if ((flags & XFS_RMAP_BMBT_BLOCK) ^ (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) return false; return true; } /* * When we allocate a new block, the first thing we do is add a reference to * the extent in the rmap btree. This takes the form of a [agbno, length, * owner, offset] record. Flags are encoded in the high bits of the offset * field. */ STATIC int xfs_rmap_map( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool unwritten, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = cur->bc_mp; struct xfs_rmap_irec ltrec; struct xfs_rmap_irec gtrec; int have_gt; int have_lt; int error = 0; int i; uint64_t owner; uint64_t offset; unsigned int flags = 0; bool ignore_off; xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); ASSERT(owner != 0); ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || (flags & XFS_RMAP_BMBT_BLOCK); if (unwritten) flags |= XFS_RMAP_UNWRITTEN; trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); /* * For the initial lookup, look for an exact match or the left-adjacent * record for our insertion point. This will also give us the record for * start block contiguity tests. */ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &have_lt); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); error = xfs_rmap_get_rec(cur, <rec, &have_lt); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, cur->bc_private.a.agno, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags); if (!xfs_rmap_is_mergeable(<rec, owner, flags)) have_lt = 0; XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 0 || ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error); /* * Increment the cursor to see if we have a right-adjacent record to our * insertion point. This will give us the record for end block * contiguity tests. */ error = xfs_btree_increment(cur, 0, &have_gt); if (error) goto out_error; if (have_gt) { error = xfs_rmap_get_rec(cur, >rec, &have_gt); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock, out_error); trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, gtrec.rm_offset, gtrec.rm_flags); if (!xfs_rmap_is_mergeable(>rec, owner, flags)) have_gt = 0; } /* * Note: cursor currently points one record to the right of ltrec, even * if there is no record in the tree to the right. */ if (have_lt && ltrec.rm_startblock + ltrec.rm_blockcount == bno && (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { /* * left edge contiguous, merge into left record. * * ltbno ltlen * orig: |ooooooooo| * adding: |aaaaaaaaa| * result: |rrrrrrrrrrrrrrrrrrr| * bno len */ ltrec.rm_blockcount += len; if (have_gt && bno + len == gtrec.rm_startblock && (ignore_off || offset + len == gtrec.rm_offset) && (unsigned long)ltrec.rm_blockcount + len + gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { /* * right edge also contiguous, delete right record * and merge into left record. * * ltbno ltlen gtbno gtlen * orig: |ooooooooo| |ooooooooo| * adding: |aaaaaaaaa| * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| */ ltrec.rm_blockcount += gtrec.rm_blockcount; trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, gtrec.rm_offset, gtrec.rm_flags); error = xfs_btree_delete(cur, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); } /* point the cursor back to the left record and update */ error = xfs_btree_decrement(cur, 0, &have_gt); if (error) goto out_error; error = xfs_rmap_update(cur, <rec); if (error) goto out_error; } else if (have_gt && bno + len == gtrec.rm_startblock && (ignore_off || offset + len == gtrec.rm_offset)) { /* * right edge contiguous, merge into right record. * * gtbno gtlen * Orig: |ooooooooo| * adding: |aaaaaaaaa| * Result: |rrrrrrrrrrrrrrrrrrr| * bno len */ gtrec.rm_startblock = bno; gtrec.rm_blockcount += len; if (!ignore_off) gtrec.rm_offset = offset; error = xfs_rmap_update(cur, >rec); if (error) goto out_error; } else { /* * no contiguous edge with identical owner, insert * new record at current cursor position. */ cur->bc_rec.r.rm_startblock = bno; cur->bc_rec.r.rm_blockcount = len; cur->bc_rec.r.rm_owner = owner; cur->bc_rec.r.rm_offset = offset; cur->bc_rec.r.rm_flags = flags; trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, owner, offset, flags); error = xfs_btree_insert(cur, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); } trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); out_error: if (error) trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Add a reference to an extent in the rmap btree. */ int xfs_rmap_alloc( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = tp->t_mountp; struct xfs_btree_cur *cur; int error; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); error = xfs_rmap_map(cur, bno, len, false, oinfo); if (error) goto out_error; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; out_error: xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } #define RMAP_LEFT_CONTIG (1 << 0) #define RMAP_RIGHT_CONTIG (1 << 1) #define RMAP_LEFT_FILLING (1 << 2) #define RMAP_RIGHT_FILLING (1 << 3) #define RMAP_LEFT_VALID (1 << 6) #define RMAP_RIGHT_VALID (1 << 7) #define LEFT r[0] #define RIGHT r[1] #define PREV r[2] #define NEW r[3] /* * Convert an unwritten extent to a real extent or vice versa. * Does not handle overlapping extents. */ STATIC int xfs_rmap_convert( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool unwritten, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = cur->bc_mp; struct xfs_rmap_irec r[4]; /* neighbor extent entries */ /* left is 0, right is 1, prev is 2 */ /* new is 3 */ uint64_t owner; uint64_t offset; uint64_t new_endoff; unsigned int oldext; unsigned int newext; unsigned int flags = 0; int i; int state = 0; int error; xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; new_endoff = offset + len; trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); /* * For the initial lookup, look for an exact match or the left-adjacent * record for our insertion point. This will also give us the record for * start block contiguity tests. */ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_rmap_get_rec(cur, &PREV, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, cur->bc_private.a.agno, PREV.rm_startblock, PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset, PREV.rm_flags); ASSERT(PREV.rm_offset <= offset); ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); newext = ~oldext & XFS_RMAP_UNWRITTEN; /* * Set flags determining what part of the previous oldext allocation * extent is being replaced by a newext allocation. */ if (PREV.rm_offset == offset) state |= RMAP_LEFT_FILLING; if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) state |= RMAP_RIGHT_FILLING; /* * Decrement the cursor to see if we have a left-adjacent record to our * insertion point. This will give us the record for end block * contiguity tests. */ error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; if (i) { state |= RMAP_LEFT_VALID; error = xfs_rmap_get_rec(cur, &LEFT, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); XFS_WANT_CORRUPTED_GOTO(mp, LEFT.rm_startblock + LEFT.rm_blockcount <= bno, done); trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, LEFT.rm_startblock, LEFT.rm_blockcount, LEFT.rm_owner, LEFT.rm_offset, LEFT.rm_flags); if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && LEFT.rm_offset + LEFT.rm_blockcount == offset && xfs_rmap_is_mergeable(&LEFT, owner, newext)) state |= RMAP_LEFT_CONTIG; } /* * Increment the cursor to see if we have a right-adjacent record to our * insertion point. This will give us the record for end block * contiguity tests. */ error = xfs_btree_increment(cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_increment(cur, 0, &i); if (error) goto done; if (i) { state |= RMAP_RIGHT_VALID; error = xfs_rmap_get_rec(cur, &RIGHT, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, done); trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, RIGHT.rm_flags); if (bno + len == RIGHT.rm_startblock && offset + len == RIGHT.rm_offset && xfs_rmap_is_mergeable(&RIGHT, owner, newext)) state |= RMAP_RIGHT_CONTIG; } /* check that left + prev + right is not too long */ if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && (unsigned long)LEFT.rm_blockcount + len + RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) state &= ~RMAP_RIGHT_CONTIG; trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, _RET_IP_); /* reset the cursor back to PREV */ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); /* * Switch out based on the FILLING and CONTIG state bits. */ switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The left and right neighbors are both contiguous with new. */ error = xfs_btree_increment(cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, RIGHT.rm_flags); error = xfs_btree_delete(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, PREV.rm_startblock, PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset, PREV.rm_flags); error = xfs_btree_delete(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW = LEFT; NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The left neighbor is contiguous, the right is not. */ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, PREV.rm_startblock, PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset, PREV.rm_flags); error = xfs_btree_delete(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW = LEFT; NEW.rm_blockcount += PREV.rm_blockcount; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The right neighbor is contiguous, the left is not. */ error = xfs_btree_increment(cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, RIGHT.rm_flags); error = xfs_btree_delete(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW = PREV; NEW.rm_blockcount = len + RIGHT.rm_blockcount; NEW.rm_flags = newext; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: /* * Setting all of a previous oldext extent to newext. * Neither the left nor right neighbors are contiguous with * the new one. */ NEW = PREV; NEW.rm_flags = newext; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is contiguous. */ NEW = PREV; NEW.rm_offset += len; NEW.rm_startblock += len; NEW.rm_blockcount -= len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; NEW = LEFT; NEW.rm_blockcount += len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING: /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is not contiguous. */ NEW = PREV; NEW.rm_startblock += len; NEW.rm_offset += len; NEW.rm_blockcount -= len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; NEW.rm_startblock = bno; NEW.rm_owner = owner; NEW.rm_offset = offset; NEW.rm_blockcount = len; NEW.rm_flags = newext; cur->bc_rec.r = NEW; trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, owner, offset, newext); error = xfs_btree_insert(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); break; case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is contiguous with the new allocation. */ NEW = PREV; NEW.rm_blockcount -= len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; error = xfs_btree_increment(cur, 0, &i); if (error) goto done; NEW = RIGHT; NEW.rm_offset = offset; NEW.rm_startblock = bno; NEW.rm_blockcount += len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_RIGHT_FILLING: /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is not contiguous. */ NEW = PREV; NEW.rm_blockcount -= len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, oldext, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); NEW.rm_startblock = bno; NEW.rm_owner = owner; NEW.rm_offset = offset; NEW.rm_blockcount = len; NEW.rm_flags = newext; cur->bc_rec.r = NEW; trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, owner, offset, newext); error = xfs_btree_insert(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); break; case 0: /* * Setting the middle part of a previous oldext extent to * newext. Contiguity is impossible here. * One extent becomes three extents. */ /* new right extent - oldext */ NEW.rm_startblock = bno + len; NEW.rm_owner = owner; NEW.rm_offset = new_endoff; NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - new_endoff; NEW.rm_flags = PREV.rm_flags; error = xfs_rmap_update(cur, &NEW); if (error) goto done; /* new left extent - oldext */ NEW = PREV; NEW.rm_blockcount = offset - PREV.rm_offset; cur->bc_rec.r = NEW; trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); error = xfs_btree_insert(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); /* * Reset the cursor to the position of the new extent * we are about to insert as we can't trust it after * the previous insert. */ error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, oldext, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); /* new middle extent - newext */ cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; cur->bc_rec.r.rm_flags |= newext; trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, owner, offset, newext); error = xfs_btree_insert(cur, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); break; case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: case RMAP_LEFT_CONTIG: case RMAP_RIGHT_CONTIG: /* * These cases are all impossible. */ ASSERT(0); } trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); done: if (error) trace_xfs_rmap_convert_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Convert an unwritten extent to a real extent or vice versa. If there is no * possibility of overlapping extents, delegate to the simpler convert * function. */ STATIC int xfs_rmap_convert_shared( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool unwritten, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = cur->bc_mp; struct xfs_rmap_irec r[4]; /* neighbor extent entries */ /* left is 0, right is 1, prev is 2 */ /* new is 3 */ uint64_t owner; uint64_t offset; uint64_t new_endoff; unsigned int oldext; unsigned int newext; unsigned int flags = 0; int i; int state = 0; int error; xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; new_endoff = offset + len; trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); /* * For the initial lookup, look for and exact match or the left-adjacent * record for our insertion point. This will also give us the record for * start block contiguity tests. */ error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, &PREV, &i); XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); ASSERT(PREV.rm_offset <= offset); ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); newext = ~oldext & XFS_RMAP_UNWRITTEN; /* * Set flags determining what part of the previous oldext allocation * extent is being replaced by a newext allocation. */ if (PREV.rm_offset == offset) state |= RMAP_LEFT_FILLING; if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) state |= RMAP_RIGHT_FILLING; /* Is there a left record that abuts our range? */ error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, &LEFT, &i); if (error) goto done; if (i) { state |= RMAP_LEFT_VALID; XFS_WANT_CORRUPTED_GOTO(mp, LEFT.rm_startblock + LEFT.rm_blockcount <= bno, done); if (xfs_rmap_is_mergeable(&LEFT, owner, newext)) state |= RMAP_LEFT_CONTIG; } /* Is there a right record that abuts our range? */ error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, newext, &i); if (error) goto done; if (i) { state |= RMAP_RIGHT_VALID; error = xfs_rmap_get_rec(cur, &RIGHT, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, done); trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, RIGHT.rm_flags); if (xfs_rmap_is_mergeable(&RIGHT, owner, newext)) state |= RMAP_RIGHT_CONTIG; } /* check that left + prev + right is not too long */ if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && (unsigned long)LEFT.rm_blockcount + len + RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) state &= ~RMAP_RIGHT_CONTIG; trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, _RET_IP_); /* * Switch out based on the FILLING and CONTIG state bits. */ switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The left and right neighbors are both contiguous with new. */ error = xfs_rmap_delete(cur, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, RIGHT.rm_flags); if (error) goto done; error = xfs_rmap_delete(cur, PREV.rm_startblock, PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset, PREV.rm_flags); if (error) goto done; NEW = LEFT; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The left neighbor is contiguous, the right is not. */ error = xfs_rmap_delete(cur, PREV.rm_startblock, PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset, PREV.rm_flags); if (error) goto done; NEW = LEFT; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_blockcount += PREV.rm_blockcount; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: /* * Setting all of a previous oldext extent to newext. * The right neighbor is contiguous, the left is not. */ error = xfs_rmap_delete(cur, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, RIGHT.rm_flags); if (error) goto done; NEW = PREV; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_blockcount += RIGHT.rm_blockcount; NEW.rm_flags = RIGHT.rm_flags; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: /* * Setting all of a previous oldext extent to newext. * Neither the left nor right neighbors are contiguous with * the new one. */ NEW = PREV; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_flags = newext; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is contiguous. */ NEW = PREV; error = xfs_rmap_delete(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; NEW.rm_offset += len; NEW.rm_startblock += len; NEW.rm_blockcount -= len; error = xfs_rmap_insert(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; NEW = LEFT; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_blockcount += len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; break; case RMAP_LEFT_FILLING: /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is not contiguous. */ NEW = PREV; error = xfs_rmap_delete(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; NEW.rm_offset += len; NEW.rm_startblock += len; NEW.rm_blockcount -= len; error = xfs_rmap_insert(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); if (error) goto done; break; case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is contiguous with the new allocation. */ NEW = PREV; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_blockcount = offset - NEW.rm_offset; error = xfs_rmap_update(cur, &NEW); if (error) goto done; NEW = RIGHT; error = xfs_rmap_delete(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; NEW.rm_offset = offset; NEW.rm_startblock = bno; NEW.rm_blockcount += len; error = xfs_rmap_insert(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; break; case RMAP_RIGHT_FILLING: /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is not contiguous. */ NEW = PREV; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_blockcount -= len; error = xfs_rmap_update(cur, &NEW); if (error) goto done; error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); if (error) goto done; break; case 0: /* * Setting the middle part of a previous oldext extent to * newext. Contiguity is impossible here. * One extent becomes three extents. */ /* new right extent - oldext */ NEW.rm_startblock = bno + len; NEW.rm_owner = owner; NEW.rm_offset = new_endoff; NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - new_endoff; NEW.rm_flags = PREV.rm_flags; error = xfs_rmap_insert(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; /* new left extent - oldext */ NEW = PREV; error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); NEW.rm_blockcount = offset - NEW.rm_offset; error = xfs_rmap_update(cur, &NEW); if (error) goto done; /* new middle extent - newext */ NEW.rm_startblock = bno; NEW.rm_blockcount = len; NEW.rm_owner = owner; NEW.rm_offset = offset; NEW.rm_flags = newext; error = xfs_rmap_insert(cur, NEW.rm_startblock, NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, NEW.rm_flags); if (error) goto done; break; case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: case RMAP_LEFT_CONTIG: case RMAP_RIGHT_CONTIG: /* * These cases are all impossible. */ ASSERT(0); } trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); done: if (error) trace_xfs_rmap_convert_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } #undef NEW #undef LEFT #undef RIGHT #undef PREV /* * Find an extent in the rmap btree and unmap it. For rmap extent types that * can overlap (data fork rmaps on reflink filesystems) we must be careful * that the prev/next records in the btree might belong to another owner. * Therefore we must use delete+insert to alter any of the key fields. * * For every other situation there can only be one owner for a given extent, * so we can call the regular _free function. */ STATIC int xfs_rmap_unmap_shared( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool unwritten, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = cur->bc_mp; struct xfs_rmap_irec ltrec; uint64_t ltoff; int error = 0; int i; uint64_t owner; uint64_t offset; unsigned int flags; xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); if (unwritten) flags |= XFS_RMAP_UNWRITTEN; trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); /* * We should always have a left record because there's a static record * for the AG headers at rm_startblock == 0 created by mkfs/growfs that * will not ever be removed from the tree. */ error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, <rec, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); ltoff = ltrec.rm_offset; /* Make sure the extent we found covers the entire freeing range. */ XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && ltrec.rm_startblock + ltrec.rm_blockcount >= bno + len, out_error); /* Make sure the owner matches what we expect to find in the tree. */ XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error); /* Make sure the unwritten flag matches. */ XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); /* Check the offset. */ XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error); XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount, out_error); if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { /* Exact match, simply remove the record from rmap tree. */ error = xfs_rmap_delete(cur, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags); if (error) goto out_error; } else if (ltrec.rm_startblock == bno) { /* * Overlap left hand side of extent: move the start, trim the * length and update the current record. * * ltbno ltlen * Orig: |oooooooooooooooooooo| * Freeing: |fffffffff| * Result: |rrrrrrrrrr| * bno len */ /* Delete prev rmap. */ error = xfs_rmap_delete(cur, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags); if (error) goto out_error; /* Add an rmap at the new offset. */ ltrec.rm_startblock += len; ltrec.rm_blockcount -= len; ltrec.rm_offset += len; error = xfs_rmap_insert(cur, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags); if (error) goto out_error; } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { /* * Overlap right hand side of extent: trim the length and * update the current record. * * ltbno ltlen * Orig: |oooooooooooooooooooo| * Freeing: |fffffffff| * Result: |rrrrrrrrrr| * bno len */ error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); ltrec.rm_blockcount -= len; error = xfs_rmap_update(cur, <rec); if (error) goto out_error; } else { /* * Overlap middle of extent: trim the length of the existing * record to the length of the new left-extent size, increment * the insertion position so we can insert a new record * containing the remaining right-extent space. * * ltbno ltlen * Orig: |oooooooooooooooooooo| * Freeing: |fffffffff| * Result: |rrrrr| |rrrr| * bno len */ xfs_extlen_t orig_len = ltrec.rm_blockcount; /* Shrink the left side of the rmap */ error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); ltrec.rm_blockcount = bno - ltrec.rm_startblock; error = xfs_rmap_update(cur, <rec); if (error) goto out_error; /* Add an rmap at the new offset */ error = xfs_rmap_insert(cur, bno + len, orig_len - len - ltrec.rm_blockcount, ltrec.rm_owner, offset + len, ltrec.rm_flags); if (error) goto out_error; } trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); out_error: if (error) trace_xfs_rmap_unmap_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } /* * Find an extent in the rmap btree and map it. For rmap extent types that * can overlap (data fork rmaps on reflink filesystems) we must be careful * that the prev/next records in the btree might belong to another owner. * Therefore we must use delete+insert to alter any of the key fields. * * For every other situation there can only be one owner for a given extent, * so we can call the regular _alloc function. */ STATIC int xfs_rmap_map_shared( struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool unwritten, struct xfs_owner_info *oinfo) { struct xfs_mount *mp = cur->bc_mp; struct xfs_rmap_irec ltrec; struct xfs_rmap_irec gtrec; int have_gt; int have_lt; int error = 0; int i; uint64_t owner; uint64_t offset; unsigned int flags = 0; xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); if (unwritten) flags |= XFS_RMAP_UNWRITTEN; trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); /* Is there a left record that abuts our range? */ error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, <rec, &have_lt); if (error) goto out_error; if (have_lt && !xfs_rmap_is_mergeable(<rec, owner, flags)) have_lt = 0; /* Is there a right record that abuts our range? */ error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, flags, &have_gt); if (error) goto out_error; if (have_gt) { error = xfs_rmap_get_rec(cur, >rec, &have_gt); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, gtrec.rm_offset, gtrec.rm_flags); if (!xfs_rmap_is_mergeable(>rec, owner, flags)) have_gt = 0; } if (have_lt && ltrec.rm_startblock + ltrec.rm_blockcount == bno && ltrec.rm_offset + ltrec.rm_blockcount == offset) { /* * Left edge contiguous, merge into left record. * * ltbno ltlen * orig: |ooooooooo| * adding: |aaaaaaaaa| * result: |rrrrrrrrrrrrrrrrrrr| * bno len */ ltrec.rm_blockcount += len; if (have_gt && bno + len == gtrec.rm_startblock && offset + len == gtrec.rm_offset) { /* * Right edge also contiguous, delete right record * and merge into left record. * * ltbno ltlen gtbno gtlen * orig: |ooooooooo| |ooooooooo| * adding: |aaaaaaaaa| * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| */ ltrec.rm_blockcount += gtrec.rm_blockcount; error = xfs_rmap_delete(cur, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, gtrec.rm_offset, gtrec.rm_flags); if (error) goto out_error; } /* Point the cursor back to the left record and update. */ error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset, ltrec.rm_flags, &i); if (error) goto out_error; XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); error = xfs_rmap_update(cur, <rec); if (error) goto out_error; } else if (have_gt && bno + len == gtrec.rm_startblock && offset + len == gtrec.rm_offset) { /* * Right edge contiguous, merge into right record. * * gtbno gtlen * Orig: |ooooooooo| * adding: |aaaaaaaaa| * Result: |rrrrrrrrrrrrrrrrrrr| * bno len */ /* Delete the old record. */ error = xfs_rmap_delete(cur, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, gtrec.rm_offset, gtrec.rm_flags); if (error) goto out_error; /* Move the start and re-add it. */ gtrec.rm_startblock = bno; gtrec.rm_blockcount += len; gtrec.rm_offset = offset; error = xfs_rmap_insert(cur, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, gtrec.rm_offset, gtrec.rm_flags); if (error) goto out_error; } else { /* * No contiguous edge with identical owner, insert * new record at current cursor position. */ error = xfs_rmap_insert(cur, bno, len, owner, offset, flags); if (error) goto out_error; } trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, unwritten, oinfo); out_error: if (error) trace_xfs_rmap_map_error(cur->bc_mp, cur->bc_private.a.agno, error, _RET_IP_); return error; } struct xfs_rmap_query_range_info { xfs_rmap_query_range_fn fn; void *priv; }; /* Format btree record and pass to our callback. */ STATIC int xfs_rmap_query_range_helper( struct xfs_btree_cur *cur, union xfs_btree_rec *rec, void *priv) { struct xfs_rmap_query_range_info *query = priv; struct xfs_rmap_irec irec; int error; error = xfs_rmap_btrec_to_irec(rec, &irec); if (error) return error; return query->fn(cur, &irec, query->priv); } /* Find all rmaps between two keys. */ int xfs_rmap_query_range( struct xfs_btree_cur *cur, struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec, xfs_rmap_query_range_fn fn, void *priv) { union xfs_btree_irec low_brec; union xfs_btree_irec high_brec; struct xfs_rmap_query_range_info query; low_brec.r = *low_rec; high_brec.r = *high_rec; query.priv = priv; query.fn = fn; return xfs_btree_query_range(cur, &low_brec, &high_brec, xfs_rmap_query_range_helper, &query); } /* Clean up after calling xfs_rmap_finish_one. */ void xfs_rmap_finish_one_cleanup( struct xfs_trans *tp, struct xfs_btree_cur *rcur, int error) { struct xfs_buf *agbp; if (rcur == NULL) return; agbp = rcur->bc_private.a.agbp; xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); if (error) xfs_trans_brelse(tp, agbp); } /* * Process one of the deferred rmap operations. We pass back the * btree cursor to maintain our lock on the rmapbt between calls. * This saves time and eliminates a buffer deadlock between the * superblock and the AGF because we'll always grab them in the same * order. */ int xfs_rmap_finish_one( struct xfs_trans *tp, enum xfs_rmap_intent_type type, __uint64_t owner, int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state, struct xfs_btree_cur **pcur) { struct xfs_mount *mp = tp->t_mountp; struct xfs_btree_cur *rcur; struct xfs_buf *agbp = NULL; int error = 0; xfs_agnumber_t agno; struct xfs_owner_info oinfo; xfs_agblock_t bno; bool unwritten; agno = XFS_FSB_TO_AGNO(mp, startblock); ASSERT(agno != NULLAGNUMBER); bno = XFS_FSB_TO_AGBNO(mp, startblock); trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork, startoff, blockcount, state); if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE, XFS_RANDOM_RMAP_FINISH_ONE)) return -EIO; /* * If we haven't gotten a cursor or the cursor AG doesn't match * the startblock, get one now. */ rcur = *pcur; if (rcur != NULL && rcur->bc_private.a.agno != agno) { xfs_rmap_finish_one_cleanup(tp, rcur, 0); rcur = NULL; *pcur = NULL; } if (rcur == NULL) { /* * Refresh the freelist before we start changing the * rmapbt, because a shape change could cause us to * allocate blocks. */ error = xfs_free_extent_fix_freelist(tp, agno, &agbp); if (error) return error; if (!agbp) return -EFSCORRUPTED; rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); if (!rcur) { error = -ENOMEM; goto out_cur; } } *pcur = rcur; xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff); unwritten = state == XFS_EXT_UNWRITTEN; bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock); switch (type) { case XFS_RMAP_ALLOC: case XFS_RMAP_MAP: error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); break; case XFS_RMAP_MAP_SHARED: error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten, &oinfo); break; case XFS_RMAP_FREE: case XFS_RMAP_UNMAP: error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, &oinfo); break; case XFS_RMAP_UNMAP_SHARED: error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten, &oinfo); break; case XFS_RMAP_CONVERT: error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, &oinfo); break; case XFS_RMAP_CONVERT_SHARED: error = xfs_rmap_convert_shared(rcur, bno, blockcount, !unwritten, &oinfo); break; default: ASSERT(0); error = -EFSCORRUPTED; } return error; out_cur: xfs_trans_brelse(tp, agbp); return error; } /* * Don't defer an rmap if we aren't an rmap filesystem. */ static bool xfs_rmap_update_is_needed( struct xfs_mount *mp, int whichfork) { return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK; } /* * Record a rmap intent; the list is kept sorted first by AG and then by * increasing age. */ static int __xfs_rmap_add( struct xfs_mount *mp, struct xfs_defer_ops *dfops, enum xfs_rmap_intent_type type, __uint64_t owner, int whichfork, struct xfs_bmbt_irec *bmap) { struct xfs_rmap_intent *ri; trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock), type, XFS_FSB_TO_AGBNO(mp, bmap->br_startblock), owner, whichfork, bmap->br_startoff, bmap->br_blockcount, bmap->br_state); ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS); INIT_LIST_HEAD(&ri->ri_list); ri->ri_type = type; ri->ri_owner = owner; ri->ri_whichfork = whichfork; ri->ri_bmap = *bmap; xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); return 0; } /* Map an extent into a file. */ int xfs_rmap_map_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *PREV) { if (!xfs_rmap_update_is_needed(mp, whichfork)) return 0; return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino, whichfork, PREV); } /* Unmap an extent out of a file. */ int xfs_rmap_unmap_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *PREV) { if (!xfs_rmap_update_is_needed(mp, whichfork)) return 0; return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino, whichfork, PREV); } /* Convert a data fork extent from unwritten to real or vice versa. */ int xfs_rmap_convert_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *PREV) { if (!xfs_rmap_update_is_needed(mp, whichfork)) return 0; return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino, whichfork, PREV); } /* Schedule the creation of an rmap for non-file data. */ int xfs_rmap_alloc_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, __uint64_t owner) { struct xfs_bmbt_irec bmap; if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) return 0; bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); bmap.br_blockcount = len; bmap.br_startoff = 0; bmap.br_state = XFS_EXT_NORM; return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap); } /* Schedule the deletion of an rmap for non-file data. */ int xfs_rmap_free_extent( struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, __uint64_t owner) { struct xfs_bmbt_irec bmap; if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) return 0; bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); bmap.br_blockcount = len; bmap.br_startoff = 0; bmap.br_state = XFS_EXT_NORM; return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_rmap.h0000644000000000000000000001441213033541503015744 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __XFS_RMAP_H__ #define __XFS_RMAP_H__ static inline void xfs_rmap_ag_owner( struct xfs_owner_info *oi, uint64_t owner) { oi->oi_owner = owner; oi->oi_offset = 0; oi->oi_flags = 0; } static inline void xfs_rmap_ino_bmbt_owner( struct xfs_owner_info *oi, xfs_ino_t ino, int whichfork) { oi->oi_owner = ino; oi->oi_offset = 0; oi->oi_flags = XFS_OWNER_INFO_BMBT_BLOCK; if (whichfork == XFS_ATTR_FORK) oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; } static inline void xfs_rmap_ino_owner( struct xfs_owner_info *oi, xfs_ino_t ino, int whichfork, xfs_fileoff_t offset) { oi->oi_owner = ino; oi->oi_offset = offset; oi->oi_flags = 0; if (whichfork == XFS_ATTR_FORK) oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; } static inline void xfs_rmap_skip_owner_update( struct xfs_owner_info *oi) { oi->oi_owner = XFS_RMAP_OWN_UNKNOWN; } /* Reverse mapping functions. */ struct xfs_buf; static inline __u64 xfs_rmap_irec_offset_pack( const struct xfs_rmap_irec *irec) { __u64 x; x = XFS_RMAP_OFF(irec->rm_offset); if (irec->rm_flags & XFS_RMAP_ATTR_FORK) x |= XFS_RMAP_OFF_ATTR_FORK; if (irec->rm_flags & XFS_RMAP_BMBT_BLOCK) x |= XFS_RMAP_OFF_BMBT_BLOCK; if (irec->rm_flags & XFS_RMAP_UNWRITTEN) x |= XFS_RMAP_OFF_UNWRITTEN; return x; } static inline int xfs_rmap_irec_offset_unpack( __u64 offset, struct xfs_rmap_irec *irec) { if (offset & ~(XFS_RMAP_OFF_MASK | XFS_RMAP_OFF_FLAGS)) return -EFSCORRUPTED; irec->rm_offset = XFS_RMAP_OFF(offset); if (offset & XFS_RMAP_OFF_ATTR_FORK) irec->rm_flags |= XFS_RMAP_ATTR_FORK; if (offset & XFS_RMAP_OFF_BMBT_BLOCK) irec->rm_flags |= XFS_RMAP_BMBT_BLOCK; if (offset & XFS_RMAP_OFF_UNWRITTEN) irec->rm_flags |= XFS_RMAP_UNWRITTEN; return 0; } static inline void xfs_owner_info_unpack( struct xfs_owner_info *oinfo, uint64_t *owner, uint64_t *offset, unsigned int *flags) { unsigned int r = 0; *owner = oinfo->oi_owner; *offset = oinfo->oi_offset; if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK) r |= XFS_RMAP_ATTR_FORK; if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK) r |= XFS_RMAP_BMBT_BLOCK; *flags = r; } static inline void xfs_owner_info_pack( struct xfs_owner_info *oinfo, uint64_t owner, uint64_t offset, unsigned int flags) { oinfo->oi_owner = owner; oinfo->oi_offset = XFS_RMAP_OFF(offset); oinfo->oi_flags = 0; if (flags & XFS_RMAP_ATTR_FORK) oinfo->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; if (flags & XFS_RMAP_BMBT_BLOCK) oinfo->oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; } int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags, int *stat); int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags, int *stat); int xfs_rmap_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags); int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat); typedef int (*xfs_rmap_query_range_fn)( struct xfs_btree_cur *cur, struct xfs_rmap_irec *rec, void *priv); int xfs_rmap_query_range(struct xfs_btree_cur *cur, struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec, xfs_rmap_query_range_fn fn, void *priv); enum xfs_rmap_intent_type { XFS_RMAP_MAP, XFS_RMAP_MAP_SHARED, XFS_RMAP_UNMAP, XFS_RMAP_UNMAP_SHARED, XFS_RMAP_CONVERT, XFS_RMAP_CONVERT_SHARED, XFS_RMAP_ALLOC, XFS_RMAP_FREE, }; struct xfs_rmap_intent { struct list_head ri_list; enum xfs_rmap_intent_type ri_type; __uint64_t ri_owner; int ri_whichfork; struct xfs_bmbt_irec ri_bmap; }; /* functions for updating the rmapbt based on bmbt map/unmap operations */ int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap); int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap); int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap); int xfs_rmap_alloc_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, __uint64_t owner); int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, __uint64_t owner); void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp, struct xfs_btree_cur *rcur, int error); int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type, __uint64_t owner, int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state, struct xfs_btree_cur **pcur); int xfs_rmap_find_left_neighbor(struct xfs_btree_cur *cur, xfs_agblock_t bno, uint64_t owner, uint64_t offset, unsigned int flags, struct xfs_rmap_irec *irec, int *stat); int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_agblock_t bno, uint64_t owner, uint64_t offset, unsigned int flags, struct xfs_rmap_irec *irec, int *stat); #endif /* __XFS_RMAP_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_rmap_btree.c0000644000000000000000000003644613033541503017133 0ustar /* * Copyright (c) 2014 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_alloc.h" #include "xfs_btree.h" #include "xfs_rmap.h" #include "xfs_rmap_btree.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_ag_resv.h" /* * Reverse map btree. * * This is a per-ag tree used to track the owner(s) of a given extent. With * reflink it is possible for there to be multiple owners, which is a departure * from classic XFS. Owner records for data extents are inserted when the * extent is mapped and removed when an extent is unmapped. Owner records for * all other block types (i.e. metadata) are inserted when an extent is * allocated and removed when an extent is freed. There can only be one owner * of a metadata extent, usually an inode or some other metadata structure like * an AG btree. * * The rmap btree is part of the free space management, so blocks for the tree * are sourced from the agfl. Hence we need transaction reservation support for * this tree so that the freelist is always large enough. This also impacts on * the minimum space we need to leave free in the AG. * * The tree is ordered by [ag block, owner, offset]. This is a large key size, * but it is the only way to enforce unique keys when a block can be owned by * multiple files at any offset. There's no need to order/search by extent * size for online updating/management of the tree. It is intended that most * reverse lookups will be to find the owner(s) of a particular block, or to * try to recover tree and file data from corrupt primary metadata. */ static struct xfs_btree_cur * xfs_rmapbt_dup_cursor( struct xfs_btree_cur *cur) { return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agbp, cur->bc_private.a.agno); } STATIC void xfs_rmapbt_set_root( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr, int inc) { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); int btnum = cur->bc_btnum; struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); ASSERT(ptr->s != 0); agf->agf_roots[btnum] = ptr->s; be32_add_cpu(&agf->agf_levels[btnum], inc); pag->pagf_levels[btnum] += inc; xfs_perag_put(pag); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); } STATIC int xfs_rmapbt_alloc_block( struct xfs_btree_cur *cur, union xfs_btree_ptr *start, union xfs_btree_ptr *new, int *stat) { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); int error; xfs_agblock_t bno; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); /* Allocate the new block from the freelist. If we can't, give up. */ error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp, &bno, 1); if (error) { XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } trace_xfs_rmapbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, bno, 1); if (bno == NULLAGBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } xfs_extent_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1, false); xfs_trans_agbtree_delta(cur->bc_tp, 1); new->s = cpu_to_be32(bno); be32_add_cpu(&agf->agf_rmap_blocks, 1); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 1; return 0; } STATIC int xfs_rmapbt_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); xfs_agblock_t bno; int error; bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp)); trace_xfs_rmapbt_free_block(cur->bc_mp, cur->bc_private.a.agno, bno, 1); be32_add_cpu(&agf->agf_rmap_blocks, -1); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS); error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); if (error) return error; xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, XFS_EXTENT_BUSY_SKIP_DISCARD); xfs_trans_agbtree_delta(cur->bc_tp, -1); return 0; } STATIC int xfs_rmapbt_get_minrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_rmap_mnr[level != 0]; } STATIC int xfs_rmapbt_get_maxrecs( struct xfs_btree_cur *cur, int level) { return cur->bc_mp->m_rmap_mxr[level != 0]; } STATIC void xfs_rmapbt_init_key_from_rec( union xfs_btree_key *key, union xfs_btree_rec *rec) { key->rmap.rm_startblock = rec->rmap.rm_startblock; key->rmap.rm_owner = rec->rmap.rm_owner; key->rmap.rm_offset = rec->rmap.rm_offset; } /* * The high key for a reverse mapping record can be computed by shifting * the startblock and offset to the highest value that would still map * to that record. In practice this means that we add blockcount-1 to * the startblock for all records, and if the record is for a data/attr * fork mapping, we add blockcount-1 to the offset too. */ STATIC void xfs_rmapbt_init_high_key_from_rec( union xfs_btree_key *key, union xfs_btree_rec *rec) { __uint64_t off; int adj; adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1; key->rmap.rm_startblock = rec->rmap.rm_startblock; be32_add_cpu(&key->rmap.rm_startblock, adj); key->rmap.rm_owner = rec->rmap.rm_owner; key->rmap.rm_offset = rec->rmap.rm_offset; if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rmap.rm_owner)) || XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rmap.rm_offset))) return; off = be64_to_cpu(key->rmap.rm_offset); off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK); key->rmap.rm_offset = cpu_to_be64(off); } STATIC void xfs_rmapbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) { rec->rmap.rm_startblock = cpu_to_be32(cur->bc_rec.r.rm_startblock); rec->rmap.rm_blockcount = cpu_to_be32(cur->bc_rec.r.rm_blockcount); rec->rmap.rm_owner = cpu_to_be64(cur->bc_rec.r.rm_owner); rec->rmap.rm_offset = cpu_to_be64( xfs_rmap_irec_offset_pack(&cur->bc_rec.r)); } STATIC void xfs_rmapbt_init_ptr_from_cur( struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr) { struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); ASSERT(agf->agf_roots[cur->bc_btnum] != 0); ptr->s = agf->agf_roots[cur->bc_btnum]; } STATIC __int64_t xfs_rmapbt_key_diff( struct xfs_btree_cur *cur, union xfs_btree_key *key) { struct xfs_rmap_irec *rec = &cur->bc_rec.r; struct xfs_rmap_key *kp = &key->rmap; __u64 x, y; __int64_t d; d = (__int64_t)be32_to_cpu(kp->rm_startblock) - rec->rm_startblock; if (d) return d; x = be64_to_cpu(kp->rm_owner); y = rec->rm_owner; if (x > y) return 1; else if (y > x) return -1; x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset)); y = rec->rm_offset; if (x > y) return 1; else if (y > x) return -1; return 0; } STATIC __int64_t xfs_rmapbt_diff_two_keys( struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2) { struct xfs_rmap_key *kp1 = &k1->rmap; struct xfs_rmap_key *kp2 = &k2->rmap; __int64_t d; __u64 x, y; d = (__int64_t)be32_to_cpu(kp1->rm_startblock) - be32_to_cpu(kp2->rm_startblock); if (d) return d; x = be64_to_cpu(kp1->rm_owner); y = be64_to_cpu(kp2->rm_owner); if (x > y) return 1; else if (y > x) return -1; x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset)); y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset)); if (x > y) return 1; else if (y > x) return -1; return 0; } static bool xfs_rmapbt_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_perag *pag = bp->b_pag; unsigned int level; /* * magic number and level verification * * During growfs operations, we can't verify the exact level or owner as * the perag is not fully initialised and hence not attached to the * buffer. In this case, check against the maximum tree depth. * * Similarly, during log recovery we will have a perag structure * attached, but the agf information will not yet have been initialised * from the on disk AGF. Again, we can only check against maximum limits * in this case. */ if (block->bb_magic != cpu_to_be32(XFS_RMAP_CRC_MAGIC)) return false; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; level = be16_to_cpu(block->bb_level); if (pag && pag->pagf_init) { if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi]) return false; } else if (level >= mp->m_rmap_maxlevels) return false; return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]); } static void xfs_rmapbt_read_verify( struct xfs_buf *bp) { if (!xfs_btree_sblock_verify_crc(bp)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_rmapbt_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_verifier_error(bp); } } static void xfs_rmapbt_write_verify( struct xfs_buf *bp) { if (!xfs_rmapbt_verify(bp)) { trace_xfs_btree_corrupt(bp, _RET_IP_); xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } xfs_btree_sblock_calc_crc(bp); } const struct xfs_buf_ops xfs_rmapbt_buf_ops = { .name = "xfs_rmapbt", .verify_read = xfs_rmapbt_read_verify, .verify_write = xfs_rmapbt_write_verify, }; #if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_rmapbt_keys_inorder( struct xfs_btree_cur *cur, union xfs_btree_key *k1, union xfs_btree_key *k2) { __uint32_t x; __uint32_t y; __uint64_t a; __uint64_t b; x = be32_to_cpu(k1->rmap.rm_startblock); y = be32_to_cpu(k2->rmap.rm_startblock); if (x < y) return 1; else if (x > y) return 0; a = be64_to_cpu(k1->rmap.rm_owner); b = be64_to_cpu(k2->rmap.rm_owner); if (a < b) return 1; else if (a > b) return 0; a = XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset)); b = XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset)); if (a <= b) return 1; return 0; } STATIC int xfs_rmapbt_recs_inorder( struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2) { __uint32_t x; __uint32_t y; __uint64_t a; __uint64_t b; x = be32_to_cpu(r1->rmap.rm_startblock); y = be32_to_cpu(r2->rmap.rm_startblock); if (x < y) return 1; else if (x > y) return 0; a = be64_to_cpu(r1->rmap.rm_owner); b = be64_to_cpu(r2->rmap.rm_owner); if (a < b) return 1; else if (a > b) return 0; a = XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset)); b = XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset)); if (a <= b) return 1; return 0; } #endif /* DEBUG */ static const struct xfs_btree_ops xfs_rmapbt_ops = { .rec_len = sizeof(struct xfs_rmap_rec), .key_len = 2 * sizeof(struct xfs_rmap_key), .dup_cursor = xfs_rmapbt_dup_cursor, .set_root = xfs_rmapbt_set_root, .alloc_block = xfs_rmapbt_alloc_block, .free_block = xfs_rmapbt_free_block, .get_minrecs = xfs_rmapbt_get_minrecs, .get_maxrecs = xfs_rmapbt_get_maxrecs, .init_key_from_rec = xfs_rmapbt_init_key_from_rec, .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec, .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur, .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur, .key_diff = xfs_rmapbt_key_diff, .buf_ops = &xfs_rmapbt_buf_ops, .diff_two_keys = xfs_rmapbt_diff_two_keys, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_rmapbt_keys_inorder, .recs_inorder = xfs_rmapbt_recs_inorder, #endif }; /* * Allocate a new allocation btree cursor. */ struct xfs_btree_cur * xfs_rmapbt_init_cursor( struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno) { struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); struct xfs_btree_cur *cur; cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); cur->bc_tp = tp; cur->bc_mp = mp; /* Overlapping btree; 2 keys per pointer. */ cur->bc_btnum = XFS_BTNUM_RMAP; cur->bc_flags = XFS_BTREE_CRC_BLOCKS | XFS_BTREE_OVERLAPPING; cur->bc_blocklog = mp->m_sb.sb_blocklog; cur->bc_ops = &xfs_rmapbt_ops; cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; return cur; } /* * Calculate number of records in an rmap btree block. */ int xfs_rmapbt_maxrecs( struct xfs_mount *mp, int blocklen, int leaf) { blocklen -= XFS_RMAP_BLOCK_LEN; if (leaf) return blocklen / sizeof(struct xfs_rmap_rec); return blocklen / (2 * sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); } /* Compute the maximum height of an rmap btree. */ void xfs_rmapbt_compute_maxlevels( struct xfs_mount *mp) { /* * On a non-reflink filesystem, the maximum number of rmap * records is the number of blocks in the AG, hence the max * rmapbt height is log_$maxrecs($agblocks). However, with * reflink each AG block can have up to 2^32 (per the refcount * record format) owners, which means that theoretically we * could face up to 2^64 rmap records. * * That effectively means that the max rmapbt height must be * XFS_BTREE_MAXLEVELS. "Fortunately" we'll run out of AG * blocks to feed the rmapbt long before the rmapbt reaches * maximum height. The reflink code uses ag_resv_critical to * disallow reflinking when less than 10% of the per-AG metadata * block reservation since the fallback is a regular file copy. */ if (xfs_sb_version_hasreflink(&mp->m_sb)) mp->m_rmap_maxlevels = XFS_BTREE_MAXLEVELS; else mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_rmap_mnr, mp->m_sb.sb_agblocks); } /* Calculate the refcount btree size for some records. */ xfs_extlen_t xfs_rmapbt_calc_size( struct xfs_mount *mp, unsigned long long len) { return xfs_btree_calc_size(mp, mp->m_rmap_mnr, len); } /* * Calculate the maximum refcount btree size. */ xfs_extlen_t xfs_rmapbt_max_size( struct xfs_mount *mp) { /* Bail out if we're uninitialized, which can happen in mkfs. */ if (mp->m_rmap_mxr[0] == 0) return 0; return xfs_rmapbt_calc_size(mp, mp->m_sb.sb_agblocks); } /* * Figure out how many blocks to reserve and how many are used by this btree. */ int xfs_rmapbt_calc_reserves( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used) { struct xfs_buf *agbp; struct xfs_agf *agf; xfs_extlen_t pool_len; xfs_extlen_t tree_len; int error; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; /* Reserve 1% of the AG or enough for 1 block per record. */ pool_len = max(mp->m_sb.sb_agblocks / 100, xfs_rmapbt_max_size(mp)); *ask += pool_len; error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) return error; agf = XFS_BUF_TO_AGF(agbp); tree_len = be32_to_cpu(agf->agf_rmap_blocks); xfs_buf_relse(agbp); *used += tree_len; return error; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_rmap_btree.h0000644000000000000000000000456113033541503017131 0ustar /* * Copyright (c) 2014 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_RMAP_BTREE_H__ #define __XFS_RMAP_BTREE_H__ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; /* rmaps only exist on crc enabled filesystems */ #define XFS_RMAP_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN /* * Record, key, and pointer address macros for btree blocks. * * (note that some of these may appear unused, but they are used in userspace) */ #define XFS_RMAP_REC_ADDR(block, index) \ ((struct xfs_rmap_rec *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ (((index) - 1) * sizeof(struct xfs_rmap_rec)))) #define XFS_RMAP_KEY_ADDR(block, index) \ ((struct xfs_rmap_key *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ ((index) - 1) * 2 * sizeof(struct xfs_rmap_key))) #define XFS_RMAP_HIGH_KEY_ADDR(block, index) \ ((struct xfs_rmap_key *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ sizeof(struct xfs_rmap_key) + \ ((index) - 1) * 2 * sizeof(struct xfs_rmap_key))) #define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \ ((xfs_rmap_ptr_t *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ (maxrecs) * 2 * sizeof(struct xfs_rmap_key) + \ ((index) - 1) * sizeof(xfs_rmap_ptr_t))) struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *bp, xfs_agnumber_t agno); int xfs_rmapbt_maxrecs(struct xfs_mount *mp, int blocklen, int leaf); extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp); extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp, unsigned long long len); extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp); extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); #endif /* __XFS_RMAP_BTREE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_rtbitmap.c0000644000000000000000000006225513063067171016641 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_btree.h" #include "xfs_alloc.h" #include "xfs_trans.h" #include "xfs_trans_space.h" #include "xfs_trace.h" /* * Realtime allocator bitmap functions shared with userspace. */ /* * Real time buffers need verifiers to avoid runtime warnings during IO. * We don't have anything to verify, however, so these are just dummy * operations. */ static void xfs_rtbuf_verify_read( struct xfs_buf *bp) { return; } static void xfs_rtbuf_verify_write( struct xfs_buf *bp) { return; } const struct xfs_buf_ops xfs_rtbuf_ops = { .name = "rtbuf", .verify_read = xfs_rtbuf_verify_read, .verify_write = xfs_rtbuf_verify_write, }; /* * Get a buffer for the bitmap or summary file block specified. * The buffer is returned read and locked. */ static int xfs_rtbuf_get( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t block, /* block number in bitmap or summary */ int issum, /* is summary not bitmap */ xfs_buf_t **bpp) /* output: buffer for the block */ { xfs_buf_t *bp; /* block buffer, result */ xfs_inode_t *ip; /* bitmap or summary inode */ xfs_bmbt_irec_t map; int nmap = 1; int error; /* error value */ ip = issum ? mp->m_rsumip : mp->m_rbmip; error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK); if (error) return error; ASSERT(map.br_startblock != NULLFSBLOCK); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, map.br_startblock), mp->m_bsize, 0, &bp, &xfs_rtbuf_ops); if (error) return error; xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF : XFS_BLFT_RTBITMAP_BUF); *bpp = bp; return 0; } /* * Searching backward from start to limit, find the first block whose * allocated/free state is different from start's. */ int xfs_rtfind_back( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* starting block to look at */ xfs_rtblock_t limit, /* last block to look at */ xfs_rtblock_t *rtblock) /* out: start block found */ { xfs_rtword_t *b; /* current word in buffer */ int bit; /* bit number in the word */ xfs_rtblock_t block; /* bitmap block number */ xfs_buf_t *bp; /* buf for the block */ xfs_rtword_t *bufp; /* starting word in buffer */ int error; /* error value */ xfs_rtblock_t firstbit; /* first useful bit in the word */ xfs_rtblock_t i; /* current bit number rel. to start */ xfs_rtblock_t len; /* length of inspected area */ xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t want; /* mask for "good" values */ xfs_rtword_t wdiff; /* difference from wanted value */ int word; /* word number in the buffer */ /* * Compute and read in starting bitmap block for starting block. */ block = XFS_BITTOBLOCK(mp, start); error = xfs_rtbuf_get(mp, tp, block, 0, &bp); if (error) { return error; } bufp = bp->b_addr; /* * Get the first word's index & point to it. */ word = XFS_BITTOWORD(mp, start); b = &bufp[word]; bit = (int)(start & (XFS_NBWORD - 1)); len = start - limit + 1; /* * Compute match value, based on the bit at start: if 1 (free) * then all-ones, else all-zeroes. */ want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; /* * If the starting position is not word-aligned, deal with the * partial word. */ if (bit < XFS_NBWORD - 1) { /* * Calculate first (leftmost) bit number to look at, * and mask for all the relevant bits in this word. */ firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0); mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) << firstbit; /* * Calculate the difference between the value there * and what we're looking for. */ if ((wdiff = (*b ^ want) & mask)) { /* * Different. Mark where we are and return. */ xfs_trans_brelse(tp, bp); i = bit - XFS_RTHIBIT(wdiff); *rtblock = start - i + 1; return 0; } i = bit - firstbit + 1; /* * Go on to previous block if that's where the previous word is * and we need the previous word. */ if (--word == -1 && i < len) { /* * If done with this block, get the previous one. */ xfs_trans_brelse(tp, bp); error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); if (error) { return error; } bufp = bp->b_addr; word = XFS_BLOCKWMASK(mp); b = &bufp[word]; } else { /* * Go on to the previous word in the buffer. */ b--; } } else { /* * Starting on a word boundary, no partial word. */ i = 0; } /* * Loop over whole words in buffers. When we use up one buffer * we move on to the previous one. */ while (len - i >= XFS_NBWORD) { /* * Compute difference between actual and desired value. */ if ((wdiff = *b ^ want)) { /* * Different, mark where we are and return. */ xfs_trans_brelse(tp, bp); i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); *rtblock = start - i + 1; return 0; } i += XFS_NBWORD; /* * Go on to previous block if that's where the previous word is * and we need the previous word. */ if (--word == -1 && i < len) { /* * If done with this block, get the previous one. */ xfs_trans_brelse(tp, bp); error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); if (error) { return error; } bufp = bp->b_addr; word = XFS_BLOCKWMASK(mp); b = &bufp[word]; } else { /* * Go on to the previous word in the buffer. */ b--; } } /* * If not ending on a word boundary, deal with the last * (partial) word. */ if (len - i) { /* * Calculate first (leftmost) bit number to look at, * and mask for all the relevant bits in this word. */ firstbit = XFS_NBWORD - (len - i); mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit; /* * Compute difference between actual and desired value. */ if ((wdiff = (*b ^ want) & mask)) { /* * Different, mark where we are and return. */ xfs_trans_brelse(tp, bp); i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); *rtblock = start - i + 1; return 0; } else i = len; } /* * No match, return that we scanned the whole area. */ xfs_trans_brelse(tp, bp); *rtblock = start - i + 1; return 0; } /* * Searching forward from start to limit, find the first block whose * allocated/free state is different from start's. */ int xfs_rtfind_forw( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* starting block to look at */ xfs_rtblock_t limit, /* last block to look at */ xfs_rtblock_t *rtblock) /* out: start block found */ { xfs_rtword_t *b; /* current word in buffer */ int bit; /* bit number in the word */ xfs_rtblock_t block; /* bitmap block number */ xfs_buf_t *bp; /* buf for the block */ xfs_rtword_t *bufp; /* starting word in buffer */ int error; /* error value */ xfs_rtblock_t i; /* current bit number rel. to start */ xfs_rtblock_t lastbit; /* last useful bit in the word */ xfs_rtblock_t len; /* length of inspected area */ xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t want; /* mask for "good" values */ xfs_rtword_t wdiff; /* difference from wanted value */ int word; /* word number in the buffer */ /* * Compute and read in starting bitmap block for starting block. */ block = XFS_BITTOBLOCK(mp, start); error = xfs_rtbuf_get(mp, tp, block, 0, &bp); if (error) { return error; } bufp = bp->b_addr; /* * Get the first word's index & point to it. */ word = XFS_BITTOWORD(mp, start); b = &bufp[word]; bit = (int)(start & (XFS_NBWORD - 1)); len = limit - start + 1; /* * Compute match value, based on the bit at start: if 1 (free) * then all-ones, else all-zeroes. */ want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; /* * If the starting position is not word-aligned, deal with the * partial word. */ if (bit) { /* * Calculate last (rightmost) bit number to look at, * and mask for all the relevant bits in this word. */ lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; /* * Calculate the difference between the value there * and what we're looking for. */ if ((wdiff = (*b ^ want) & mask)) { /* * Different. Mark where we are and return. */ xfs_trans_brelse(tp, bp); i = XFS_RTLOBIT(wdiff) - bit; *rtblock = start + i - 1; return 0; } i = lastbit - bit; /* * Go on to next block if that's where the next word is * and we need the next word. */ if (++word == XFS_BLOCKWSIZE(mp) && i < len) { /* * If done with this block, get the previous one. */ xfs_trans_brelse(tp, bp); error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error) { return error; } b = bufp = bp->b_addr; word = 0; } else { /* * Go on to the previous word in the buffer. */ b++; } } else { /* * Starting on a word boundary, no partial word. */ i = 0; } /* * Loop over whole words in buffers. When we use up one buffer * we move on to the next one. */ while (len - i >= XFS_NBWORD) { /* * Compute difference between actual and desired value. */ if ((wdiff = *b ^ want)) { /* * Different, mark where we are and return. */ xfs_trans_brelse(tp, bp); i += XFS_RTLOBIT(wdiff); *rtblock = start + i - 1; return 0; } i += XFS_NBWORD; /* * Go on to next block if that's where the next word is * and we need the next word. */ if (++word == XFS_BLOCKWSIZE(mp) && i < len) { /* * If done with this block, get the next one. */ xfs_trans_brelse(tp, bp); error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error) { return error; } b = bufp = bp->b_addr; word = 0; } else { /* * Go on to the next word in the buffer. */ b++; } } /* * If not ending on a word boundary, deal with the last * (partial) word. */ if ((lastbit = len - i)) { /* * Calculate mask for all the relevant bits in this word. */ mask = ((xfs_rtword_t)1 << lastbit) - 1; /* * Compute difference between actual and desired value. */ if ((wdiff = (*b ^ want) & mask)) { /* * Different, mark where we are and return. */ xfs_trans_brelse(tp, bp); i += XFS_RTLOBIT(wdiff); *rtblock = start + i - 1; return 0; } else i = len; } /* * No match, return that we scanned the whole area. */ xfs_trans_brelse(tp, bp); *rtblock = start + i - 1; return 0; } /* * Read and/or modify the summary information for a given extent size, * bitmap block combination. * Keeps track of a current summary block, so we don't keep reading * it from the buffer cache. * * Summary information is returned in *sum if specified. * If no delta is specified, returns summary only. */ int xfs_rtmodify_summary_int( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ int log, /* log2 of extent size */ xfs_rtblock_t bbno, /* bitmap block number */ int delta, /* change to make to summary info */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb, /* in/out: summary block number */ xfs_suminfo_t *sum) /* out: summary info for this block */ { xfs_buf_t *bp; /* buffer for the summary block */ int error; /* error value */ xfs_fsblock_t sb; /* summary fsblock */ int so; /* index into the summary file */ xfs_suminfo_t *sp; /* pointer to returned data */ /* * Compute entry number in the summary file. */ so = XFS_SUMOFFS(mp, log, bbno); /* * Compute the block number in the summary file. */ sb = XFS_SUMOFFSTOBLOCK(mp, so); /* * If we have an old buffer, and the block number matches, use that. */ if (*rbpp && *rsb == sb) bp = *rbpp; /* * Otherwise we have to get the buffer. */ else { /* * If there was an old one, get rid of it first. */ if (*rbpp) xfs_trans_brelse(tp, *rbpp); error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); if (error) { return error; } /* * Remember this buffer and block for the next call. */ *rbpp = bp; *rsb = sb; } /* * Point to the summary information, modify/log it, and/or copy it out. */ sp = XFS_SUMPTR(mp, bp, so); if (delta) { uint first = (uint)((char *)sp - (char *)bp->b_addr); *sp += delta; xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1); } if (sum) *sum = *sp; return 0; } int xfs_rtmodify_summary( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ int log, /* log2 of extent size */ xfs_rtblock_t bbno, /* bitmap block number */ int delta, /* change to make to summary info */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb) /* in/out: summary block number */ { return xfs_rtmodify_summary_int(mp, tp, log, bbno, delta, rbpp, rsb, NULL); } /* * Set the given range of bitmap bits to the given value. * Do whatever I/O and logging is required. */ int xfs_rtmodify_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* starting block to modify */ xfs_extlen_t len, /* length of extent to modify */ int val) /* 1 for free, 0 for allocated */ { xfs_rtword_t *b; /* current word in buffer */ int bit; /* bit number in the word */ xfs_rtblock_t block; /* bitmap block number */ xfs_buf_t *bp; /* buf for the block */ xfs_rtword_t *bufp; /* starting word in buffer */ int error; /* error value */ xfs_rtword_t *first; /* first used word in the buffer */ int i; /* current bit number rel. to start */ int lastbit; /* last useful bit in word */ xfs_rtword_t mask; /* mask o frelevant bits for value */ int word; /* word number in the buffer */ /* * Compute starting bitmap block number. */ block = XFS_BITTOBLOCK(mp, start); /* * Read the bitmap block, and point to its data. */ error = xfs_rtbuf_get(mp, tp, block, 0, &bp); if (error) { return error; } bufp = bp->b_addr; /* * Compute the starting word's address, and starting bit. */ word = XFS_BITTOWORD(mp, start); first = b = &bufp[word]; bit = (int)(start & (XFS_NBWORD - 1)); /* * 0 (allocated) => all zeroes; 1 (free) => all ones. */ val = -val; /* * If not starting on a word boundary, deal with the first * (partial) word. */ if (bit) { /* * Compute first bit not changed and mask of relevant bits. */ lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; /* * Set/clear the active bits. */ if (val) *b |= mask; else *b &= ~mask; i = lastbit - bit; /* * Go on to the next block if that's where the next word is * and we need the next word. */ if (++word == XFS_BLOCKWSIZE(mp) && i < len) { /* * Log the changed part of this block. * Get the next one. */ xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), (uint)((char *)b - (char *)bufp)); error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error) { return error; } first = b = bufp = bp->b_addr; word = 0; } else { /* * Go on to the next word in the buffer */ b++; } } else { /* * Starting on a word boundary, no partial word. */ i = 0; } /* * Loop over whole words in buffers. When we use up one buffer * we move on to the next one. */ while (len - i >= XFS_NBWORD) { /* * Set the word value correctly. */ *b = val; i += XFS_NBWORD; /* * Go on to the next block if that's where the next word is * and we need the next word. */ if (++word == XFS_BLOCKWSIZE(mp) && i < len) { /* * Log the changed part of this block. * Get the next one. */ xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), (uint)((char *)b - (char *)bufp)); error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error) { return error; } first = b = bufp = bp->b_addr; word = 0; } else { /* * Go on to the next word in the buffer */ b++; } } /* * If not ending on a word boundary, deal with the last * (partial) word. */ if ((lastbit = len - i)) { /* * Compute a mask of relevant bits. */ bit = 0; mask = ((xfs_rtword_t)1 << lastbit) - 1; /* * Set/clear the active bits. */ if (val) *b |= mask; else *b &= ~mask; b++; } /* * Log any remaining changed bytes. */ if (b > first) xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), (uint)((char *)b - (char *)bufp - 1)); return 0; } /* * Mark an extent specified by start and len freed. * Updates all the summary information as well as the bitmap. */ int xfs_rtfree_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* starting block to free */ xfs_extlen_t len, /* length to free */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb) /* in/out: summary block number */ { xfs_rtblock_t end; /* end of the freed extent */ int error; /* error value */ xfs_rtblock_t postblock; /* first block freed > end */ xfs_rtblock_t preblock; /* first block freed < start */ end = start + len - 1; /* * Modify the bitmap to mark this extent freed. */ error = xfs_rtmodify_range(mp, tp, start, len, 1); if (error) { return error; } /* * Assume we're freeing out of the middle of an allocated extent. * We need to find the beginning and end of the extent so we can * properly update the summary. */ error = xfs_rtfind_back(mp, tp, start, 0, &preblock); if (error) { return error; } /* * Find the next allocated block (end of allocated extent). */ error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, &postblock); if (error) return error; /* * If there are blocks not being freed at the front of the * old extent, add summary data for them to be allocated. */ if (preblock < start) { error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(start - preblock), XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); if (error) { return error; } } /* * If there are blocks not being freed at the end of the * old extent, add summary data for them to be allocated. */ if (postblock > end) { error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(postblock - end), XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb); if (error) { return error; } } /* * Increment the summary information corresponding to the entire * (new) free extent. */ error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(postblock + 1 - preblock), XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); return error; } /* * Check that the given range is either all allocated (val = 0) or * all free (val = 1). */ int xfs_rtcheck_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ int val, /* 1 for free, 0 for allocated */ xfs_rtblock_t *new, /* out: first block not matching */ int *stat) /* out: 1 for matches, 0 for not */ { xfs_rtword_t *b; /* current word in buffer */ int bit; /* bit number in the word */ xfs_rtblock_t block; /* bitmap block number */ xfs_buf_t *bp; /* buf for the block */ xfs_rtword_t *bufp; /* starting word in buffer */ int error; /* error value */ xfs_rtblock_t i; /* current bit number rel. to start */ xfs_rtblock_t lastbit; /* last useful bit in word */ xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t wdiff; /* difference from wanted value */ int word; /* word number in the buffer */ /* * Compute starting bitmap block number */ block = XFS_BITTOBLOCK(mp, start); /* * Read the bitmap block. */ error = xfs_rtbuf_get(mp, tp, block, 0, &bp); if (error) { return error; } bufp = bp->b_addr; /* * Compute the starting word's address, and starting bit. */ word = XFS_BITTOWORD(mp, start); b = &bufp[word]; bit = (int)(start & (XFS_NBWORD - 1)); /* * 0 (allocated) => all zero's; 1 (free) => all one's. */ val = -val; /* * If not starting on a word boundary, deal with the first * (partial) word. */ if (bit) { /* * Compute first bit not examined. */ lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); /* * Mask of relevant bits. */ mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; /* * Compute difference between actual and desired value. */ if ((wdiff = (*b ^ val) & mask)) { /* * Different, compute first wrong bit and return. */ xfs_trans_brelse(tp, bp); i = XFS_RTLOBIT(wdiff) - bit; *new = start + i; *stat = 0; return 0; } i = lastbit - bit; /* * Go on to next block if that's where the next word is * and we need the next word. */ if (++word == XFS_BLOCKWSIZE(mp) && i < len) { /* * If done with this block, get the next one. */ xfs_trans_brelse(tp, bp); error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error) { return error; } b = bufp = bp->b_addr; word = 0; } else { /* * Go on to the next word in the buffer. */ b++; } } else { /* * Starting on a word boundary, no partial word. */ i = 0; } /* * Loop over whole words in buffers. When we use up one buffer * we move on to the next one. */ while (len - i >= XFS_NBWORD) { /* * Compute difference between actual and desired value. */ if ((wdiff = *b ^ val)) { /* * Different, compute first wrong bit and return. */ xfs_trans_brelse(tp, bp); i += XFS_RTLOBIT(wdiff); *new = start + i; *stat = 0; return 0; } i += XFS_NBWORD; /* * Go on to next block if that's where the next word is * and we need the next word. */ if (++word == XFS_BLOCKWSIZE(mp) && i < len) { /* * If done with this block, get the next one. */ xfs_trans_brelse(tp, bp); error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error) { return error; } b = bufp = bp->b_addr; word = 0; } else { /* * Go on to the next word in the buffer. */ b++; } } /* * If not ending on a word boundary, deal with the last * (partial) word. */ if ((lastbit = len - i)) { /* * Mask of relevant bits. */ mask = ((xfs_rtword_t)1 << lastbit) - 1; /* * Compute difference between actual and desired value. */ if ((wdiff = (*b ^ val) & mask)) { /* * Different, compute first wrong bit and return. */ xfs_trans_brelse(tp, bp); i += XFS_RTLOBIT(wdiff); *new = start + i; *stat = 0; return 0; } else i = len; } /* * Successful, return. */ xfs_trans_brelse(tp, bp); *new = start + i; *stat = 1; return 0; } #ifdef DEBUG /* * Check that the given extent (block range) is allocated already. */ STATIC int /* error */ xfs_rtcheck_alloc_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t bno, /* starting block number of extent */ xfs_extlen_t len) /* length of extent */ { xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ int stat; int error; error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat); if (error) return error; ASSERT(stat); return 0; } #else #define xfs_rtcheck_alloc_range(m,t,b,l) (0) #endif /* * Free an extent in the realtime subvolume. Length is expressed in * realtime extents, as is the block number. */ int /* error */ xfs_rtfree_extent( xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t bno, /* starting block number to free */ xfs_extlen_t len) /* length of extent freed */ { int error; /* error value */ xfs_mount_t *mp; /* file system mount structure */ xfs_fsblock_t sb; /* summary file block number */ xfs_buf_t *sumbp = NULL; /* summary file block buffer */ mp = tp->t_mountp; ASSERT(mp->m_rbmip->i_itemp != NULL); ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); error = xfs_rtcheck_alloc_range(mp, tp, bno, len); if (error) return error; /* * Free the range of realtime blocks. */ error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb); if (error) { return error; } /* * Mark more blocks free in the superblock. */ xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len); /* * If we've now freed all the blocks, reset the file sequence * number to 0. */ if (tp->t_frextents_delta + mp->m_sb.sb_frextents == mp->m_sb.sb_rextents) { if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; *(__uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0; xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); } return 0; } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_sb.c0000644000000000000000000006415013063067171015417 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_ialloc.h" #include "xfs_alloc.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_rmap_btree.h" #include "xfs_bmap.h" #include "xfs_refcount_btree.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. */ /* * Reference counting access wrappers to the perag structures. * Because we never free per-ag structures, the only thing we * have to protect against changes is the tree structure itself. */ struct xfs_perag * xfs_perag_get( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_perag *pag; int ref = 0; rcu_read_lock(); pag = radix_tree_lookup(&mp->m_perag_tree, agno); if (pag) { ASSERT(atomic_read(&pag->pag_ref) >= 0); ref = atomic_inc_return(&pag->pag_ref); } rcu_read_unlock(); trace_xfs_perag_get(mp, agno, ref, _RET_IP_); return pag; } /* * search from @first to find the next perag with the given tag set. */ struct xfs_perag * xfs_perag_get_tag( struct xfs_mount *mp, xfs_agnumber_t first, int tag) { struct xfs_perag *pag; int found; int ref; rcu_read_lock(); found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, (void **)&pag, first, 1, tag); if (found <= 0) { rcu_read_unlock(); return NULL; } ref = atomic_inc_return(&pag->pag_ref); rcu_read_unlock(); trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_); return pag; } void xfs_perag_put( struct xfs_perag *pag) { int ref; ASSERT(atomic_read(&pag->pag_ref) > 0); ref = atomic_dec_return(&pag->pag_ref); trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); } /* * Check the validity of the SB found. */ STATIC int xfs_mount_validate_sb( xfs_mount_t *mp, xfs_sb_t *sbp, bool check_inprogress, bool check_version) { if (sbp->sb_magicnum != XFS_SB_MAGIC) { xfs_warn(mp, "bad magic number"); return -EWRONGFS; } if (!xfs_sb_good_version(sbp)) { xfs_warn(mp, "bad version"); return -EWRONGFS; } /* * Version 5 superblock feature mask validation. Reject combinations the * kernel cannot support up front before checking anything else. For * write validation, we don't need to check feature masks. */ if (check_version && XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) { if (xfs_sb_has_compat_feature(sbp, XFS_SB_FEAT_COMPAT_UNKNOWN)) { xfs_warn(mp, "Superblock has unknown compatible features (0x%x) enabled.", (sbp->sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN)); xfs_warn(mp, "Using a more recent kernel is recommended."); } if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) { xfs_alert(mp, "Superblock has unknown read-only compatible features (0x%x) enabled.", (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_UNKNOWN)); if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { xfs_warn(mp, "Attempted to mount read-only compatible filesystem read-write."); xfs_warn(mp, "Filesystem can only be safely mounted read only."); return -EINVAL; } } if (xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_UNKNOWN)) { xfs_warn(mp, "Superblock has unknown incompatible features (0x%x) enabled.", (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_UNKNOWN)); xfs_warn(mp, "Filesystem can not be safely mounted by this kernel."); return -EINVAL; } } else if (xfs_sb_version_hascrc(sbp)) { /* * We can't read verify the sb LSN because the read verifier is * called before the log is allocated and processed. We know the * log is set up before write verifier (!check_version) calls, * so just check it here. */ if (!xfs_log_check_lsn(mp, sbp->sb_lsn)) return -EFSCORRUPTED; } if (xfs_sb_version_has_pquotino(sbp)) { if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) { xfs_notice(mp, "Version 5 of Super block has XFS_OQUOTA bits."); return -EFSCORRUPTED; } } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD | XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) { xfs_notice(mp, "Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits."); return -EFSCORRUPTED; } /* * Full inode chunks must be aligned to inode chunk size when * sparse inodes are enabled to support the sparse chunk * allocation algorithm and prevent overlapping inode records. */ if (xfs_sb_version_hassparseinodes(sbp)) { uint32_t align; align = XFS_INODES_PER_CHUNK * sbp->sb_inodesize >> sbp->sb_blocklog; if (sbp->sb_inoalignmt != align) { xfs_warn(mp, "Inode block alignment (%u) must match chunk size (%u) for sparse inodes.", sbp->sb_inoalignmt, align); return -EINVAL; } } if (unlikely( sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { xfs_warn(mp, "filesystem is marked as having an external log; " "specify logdev on the mount command line."); return -EINVAL; } if (unlikely( sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { xfs_warn(mp, "filesystem is marked as having an internal log; " "do not specify logdev on the mount command line."); return -EINVAL; } /* * More sanity checking. Most of these were stolen directly from * xfs_repair. */ if (unlikely( sbp->sb_agcount <= 0 || sbp->sb_sectsize < XFS_MIN_SECTORSIZE || sbp->sb_sectsize > XFS_MAX_SECTORSIZE || sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG || sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG || sbp->sb_sectsize != (1 << sbp->sb_sectlog) || sbp->sb_blocksize < XFS_MIN_BLOCKSIZE || sbp->sb_blocksize > XFS_MAX_BLOCKSIZE || sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || sbp->sb_blocksize != (1 << sbp->sb_blocklog) || sbp->sb_dirblklog > XFS_MAX_BLOCKSIZE_LOG || sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || sbp->sb_inodelog < XFS_DINODE_MIN_LOG || sbp->sb_inodelog > XFS_DINODE_MAX_LOG || sbp->sb_inodesize != (1 << sbp->sb_inodelog) || sbp->sb_logsunit > XLOG_MAX_RECORD_BSIZE || sbp->sb_inopblock != howmany(sbp->sb_blocksize,sbp->sb_inodesize) || (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) || (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */) || sbp->sb_dblocks == 0 || sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp) || sbp->sb_shared_vn != 0)) { xfs_notice(mp, "SB sanity check failed"); return -EFSCORRUPTED; } /* * Currently only very few inode sizes are supported. */ switch (sbp->sb_inodesize) { case 256: case 512: case 1024: case 2048: break; default: xfs_warn(mp, "inode size of %d bytes not supported", sbp->sb_inodesize); return -ENOSYS; } if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { xfs_warn(mp, "file system too large to be mounted on this system."); return -EFBIG; } return 0; } void xfs_sb_quota_from_disk(struct xfs_sb *sbp) { /* * older mkfs doesn't initialize quota inodes to NULLFSINO. This * leads to in-core values having two different values for a quota * inode to be invalid: 0 and NULLFSINO. Change it to a single value * NULLFSINO. * * Note that this change affect only the in-core values. These * values are not written back to disk unless any quota information * is written to the disk. Even in that case, sb_pquotino field is * not written to disk unless the superblock supports pquotino. */ if (sbp->sb_uquotino == 0) sbp->sb_uquotino = NULLFSINO; if (sbp->sb_gquotino == 0) sbp->sb_gquotino = NULLFSINO; if (sbp->sb_pquotino == 0) sbp->sb_pquotino = NULLFSINO; /* * We need to do these manipilations only if we are working * with an older version of on-disk superblock. */ if (xfs_sb_version_has_pquotino(sbp)) return; if (sbp->sb_qflags & XFS_OQUOTA_ENFD) sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD; if (sbp->sb_qflags & XFS_OQUOTA_CHKD) sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); if (sbp->sb_qflags & XFS_PQUOTA_ACCT && sbp->sb_gquotino != NULLFSINO) { /* * In older version of superblock, on-disk superblock only * has sb_gquotino, and in-core superblock has both sb_gquotino * and sb_pquotino. But, only one of them is supported at any * point of time. So, if PQUOTA is set in disk superblock, * copy over sb_gquotino to sb_pquotino. The NULLFSINO test * above is to make sure we don't do this twice and wipe them * both out! */ sbp->sb_pquotino = sbp->sb_gquotino; sbp->sb_gquotino = NULLFSINO; } } static void __xfs_sb_from_disk( struct xfs_sb *to, xfs_dsb_t *from, bool convert_xquota) { to->sb_magicnum = be32_to_cpu(from->sb_magicnum); to->sb_blocksize = be32_to_cpu(from->sb_blocksize); to->sb_dblocks = be64_to_cpu(from->sb_dblocks); to->sb_rblocks = be64_to_cpu(from->sb_rblocks); to->sb_rextents = be64_to_cpu(from->sb_rextents); memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid)); to->sb_logstart = be64_to_cpu(from->sb_logstart); to->sb_rootino = be64_to_cpu(from->sb_rootino); to->sb_rbmino = be64_to_cpu(from->sb_rbmino); to->sb_rsumino = be64_to_cpu(from->sb_rsumino); to->sb_rextsize = be32_to_cpu(from->sb_rextsize); to->sb_agblocks = be32_to_cpu(from->sb_agblocks); to->sb_agcount = be32_to_cpu(from->sb_agcount); to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks); to->sb_logblocks = be32_to_cpu(from->sb_logblocks); to->sb_versionnum = be16_to_cpu(from->sb_versionnum); to->sb_sectsize = be16_to_cpu(from->sb_sectsize); to->sb_inodesize = be16_to_cpu(from->sb_inodesize); to->sb_inopblock = be16_to_cpu(from->sb_inopblock); memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname)); to->sb_blocklog = from->sb_blocklog; to->sb_sectlog = from->sb_sectlog; to->sb_inodelog = from->sb_inodelog; to->sb_inopblog = from->sb_inopblog; to->sb_agblklog = from->sb_agblklog; to->sb_rextslog = from->sb_rextslog; to->sb_inprogress = from->sb_inprogress; to->sb_imax_pct = from->sb_imax_pct; to->sb_icount = be64_to_cpu(from->sb_icount); to->sb_ifree = be64_to_cpu(from->sb_ifree); to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks); to->sb_frextents = be64_to_cpu(from->sb_frextents); to->sb_uquotino = be64_to_cpu(from->sb_uquotino); to->sb_gquotino = be64_to_cpu(from->sb_gquotino); to->sb_qflags = be16_to_cpu(from->sb_qflags); to->sb_flags = from->sb_flags; to->sb_shared_vn = from->sb_shared_vn; to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt); to->sb_unit = be32_to_cpu(from->sb_unit); to->sb_width = be32_to_cpu(from->sb_width); to->sb_dirblklog = from->sb_dirblklog; to->sb_logsectlog = from->sb_logsectlog; to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize); to->sb_logsunit = be32_to_cpu(from->sb_logsunit); to->sb_features2 = be32_to_cpu(from->sb_features2); to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2); to->sb_features_compat = be32_to_cpu(from->sb_features_compat); to->sb_features_ro_compat = be32_to_cpu(from->sb_features_ro_compat); to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat); to->sb_features_log_incompat = be32_to_cpu(from->sb_features_log_incompat); /* crc is only used on disk, not in memory; just init to 0 here. */ to->sb_crc = 0; to->sb_spino_align = be32_to_cpu(from->sb_spino_align); to->sb_pquotino = be64_to_cpu(from->sb_pquotino); to->sb_lsn = be64_to_cpu(from->sb_lsn); /* * sb_meta_uuid is only on disk if it differs from sb_uuid and the * feature flag is set; if not set we keep it only in memory. */ if (xfs_sb_version_hasmetauuid(to)) uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); else uuid_copy(&to->sb_meta_uuid, &from->sb_uuid); /* Convert on-disk flags to in-memory flags? */ if (convert_xquota) xfs_sb_quota_from_disk(to); } void xfs_sb_from_disk( struct xfs_sb *to, xfs_dsb_t *from) { __xfs_sb_from_disk(to, from, true); } static void xfs_sb_quota_to_disk( struct xfs_dsb *to, struct xfs_sb *from) { __uint16_t qflags = from->sb_qflags; to->sb_uquotino = cpu_to_be64(from->sb_uquotino); if (xfs_sb_version_has_pquotino(from)) { to->sb_qflags = cpu_to_be16(from->sb_qflags); to->sb_gquotino = cpu_to_be64(from->sb_gquotino); to->sb_pquotino = cpu_to_be64(from->sb_pquotino); return; } /* * The in-core version of sb_qflags do not have XFS_OQUOTA_* * flags, whereas the on-disk version does. So, convert incore * XFS_{PG}QUOTA_* flags to on-disk XFS_OQUOTA_* flags. */ qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD | XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD); if (from->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD)) qflags |= XFS_OQUOTA_ENFD; if (from->sb_qflags & (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) qflags |= XFS_OQUOTA_CHKD; to->sb_qflags = cpu_to_be16(qflags); /* * GQUOTINO and PQUOTINO cannot be used together in versions * of superblock that do not have pquotino. from->sb_flags * tells us which quota is active and should be copied to * disk. If neither are active, we should NULL the inode. * * In all cases, the separate pquotino must remain 0 because it * it beyond the "end" of the valid non-pquotino superblock. */ if (from->sb_qflags & XFS_GQUOTA_ACCT) to->sb_gquotino = cpu_to_be64(from->sb_gquotino); else if (from->sb_qflags & XFS_PQUOTA_ACCT) to->sb_gquotino = cpu_to_be64(from->sb_pquotino); else { /* * We can't rely on just the fields being logged to tell us * that it is safe to write NULLFSINO - we should only do that * if quotas are not actually enabled. Hence only write * NULLFSINO if both in-core quota inodes are NULL. */ if (from->sb_gquotino == NULLFSINO && from->sb_pquotino == NULLFSINO) to->sb_gquotino = cpu_to_be64(NULLFSINO); } to->sb_pquotino = 0; } void xfs_sb_to_disk( struct xfs_dsb *to, struct xfs_sb *from) { xfs_sb_quota_to_disk(to, from); to->sb_magicnum = cpu_to_be32(from->sb_magicnum); to->sb_blocksize = cpu_to_be32(from->sb_blocksize); to->sb_dblocks = cpu_to_be64(from->sb_dblocks); to->sb_rblocks = cpu_to_be64(from->sb_rblocks); to->sb_rextents = cpu_to_be64(from->sb_rextents); memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid)); to->sb_logstart = cpu_to_be64(from->sb_logstart); to->sb_rootino = cpu_to_be64(from->sb_rootino); to->sb_rbmino = cpu_to_be64(from->sb_rbmino); to->sb_rsumino = cpu_to_be64(from->sb_rsumino); to->sb_rextsize = cpu_to_be32(from->sb_rextsize); to->sb_agblocks = cpu_to_be32(from->sb_agblocks); to->sb_agcount = cpu_to_be32(from->sb_agcount); to->sb_rbmblocks = cpu_to_be32(from->sb_rbmblocks); to->sb_logblocks = cpu_to_be32(from->sb_logblocks); to->sb_versionnum = cpu_to_be16(from->sb_versionnum); to->sb_sectsize = cpu_to_be16(from->sb_sectsize); to->sb_inodesize = cpu_to_be16(from->sb_inodesize); to->sb_inopblock = cpu_to_be16(from->sb_inopblock); memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname)); to->sb_blocklog = from->sb_blocklog; to->sb_sectlog = from->sb_sectlog; to->sb_inodelog = from->sb_inodelog; to->sb_inopblog = from->sb_inopblog; to->sb_agblklog = from->sb_agblklog; to->sb_rextslog = from->sb_rextslog; to->sb_inprogress = from->sb_inprogress; to->sb_imax_pct = from->sb_imax_pct; to->sb_icount = cpu_to_be64(from->sb_icount); to->sb_ifree = cpu_to_be64(from->sb_ifree); to->sb_fdblocks = cpu_to_be64(from->sb_fdblocks); to->sb_frextents = cpu_to_be64(from->sb_frextents); to->sb_flags = from->sb_flags; to->sb_shared_vn = from->sb_shared_vn; to->sb_inoalignmt = cpu_to_be32(from->sb_inoalignmt); to->sb_unit = cpu_to_be32(from->sb_unit); to->sb_width = cpu_to_be32(from->sb_width); to->sb_dirblklog = from->sb_dirblklog; to->sb_logsectlog = from->sb_logsectlog; to->sb_logsectsize = cpu_to_be16(from->sb_logsectsize); to->sb_logsunit = cpu_to_be32(from->sb_logsunit); /* * We need to ensure that bad_features2 always matches features2. * Hence we enforce that here rather than having to remember to do it * everywhere else that updates features2. */ from->sb_bad_features2 = from->sb_features2; to->sb_features2 = cpu_to_be32(from->sb_features2); to->sb_bad_features2 = cpu_to_be32(from->sb_bad_features2); if (xfs_sb_version_hascrc(from)) { to->sb_features_compat = cpu_to_be32(from->sb_features_compat); to->sb_features_ro_compat = cpu_to_be32(from->sb_features_ro_compat); to->sb_features_incompat = cpu_to_be32(from->sb_features_incompat); to->sb_features_log_incompat = cpu_to_be32(from->sb_features_log_incompat); to->sb_spino_align = cpu_to_be32(from->sb_spino_align); to->sb_lsn = cpu_to_be64(from->sb_lsn); if (xfs_sb_version_hasmetauuid(from)) uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); } } static int xfs_sb_verify( struct xfs_buf *bp, bool check_version) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_sb sb; /* * Use call variant which doesn't convert quota flags from disk * format, because xfs_mount_validate_sb checks the on-disk flags. */ __xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp), false); /* * Only check the in progress field for the primary superblock as * mkfs.xfs doesn't clear it from secondary superblocks. */ return xfs_mount_validate_sb(mp, &sb, bp->b_maps[0].bm_bn == XFS_SB_DADDR, check_version); } /* * If the superblock has the CRC feature bit set or the CRC field is non-null, * check that the CRC is valid. We check the CRC field is non-null because a * single bit error could clear the feature bit and unused parts of the * superblock are supposed to be zero. Hence a non-null crc field indicates that * we've potentially lost a feature bit and we should check it anyway. * * However, past bugs (i.e. in growfs) left non-zeroed regions beyond the * last field in V4 secondary superblocks. So for secondary superblocks, * we are more forgiving, and ignore CRC failures if the primary doesn't * indicate that the fs version is V5. */ static void xfs_sb_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp); int error; /* * open code the version check to avoid needing to convert the entire * superblock from disk order just to check the version number */ if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC) && (((be16_to_cpu(dsb->sb_versionnum) & XFS_SB_VERSION_NUMBITS) == XFS_SB_VERSION_5) || dsb->sb_crc != 0)) { if (!xfs_buf_verify_cksum(bp, XFS_SB_CRC_OFF)) { /* Only fail bad secondaries on a known V5 filesystem */ if (bp->b_bn == XFS_SB_DADDR || xfs_sb_version_hascrc(&mp->m_sb)) { error = -EFSBADCRC; goto out_error; } } } error = xfs_sb_verify(bp, true); out_error: if (error) { xfs_buf_ioerror(bp, error); if (error == -EFSCORRUPTED || error == -EFSBADCRC) xfs_verifier_error(bp); } } /* * We may be probed for a filesystem match, so we may not want to emit * messages when the superblock buffer is not actually an XFS superblock. * If we find an XFS superblock, then run a normal, noisy mount because we are * really going to mount it and want to know about errors. */ static void xfs_sb_quiet_read_verify( struct xfs_buf *bp) { struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp); if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) { /* XFS filesystem, verify noisily! */ xfs_sb_read_verify(bp); return; } /* quietly fail */ xfs_buf_ioerror(bp, -EWRONGFS); } static void xfs_sb_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; int error; error = xfs_sb_verify(bp, false); if (error) { xfs_buf_ioerror(bp, error); xfs_verifier_error(bp); return; } if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (bip) XFS_BUF_TO_SBP(bp)->sb_lsn = cpu_to_be64(bip->bli_item.li_lsn); xfs_buf_update_cksum(bp, XFS_SB_CRC_OFF); } const struct xfs_buf_ops xfs_sb_buf_ops = { .name = "xfs_sb", .verify_read = xfs_sb_read_verify, .verify_write = xfs_sb_write_verify, }; const struct xfs_buf_ops xfs_sb_quiet_buf_ops = { .name = "xfs_sb_quiet", .verify_read = xfs_sb_quiet_read_verify, .verify_write = xfs_sb_write_verify, }; /* * xfs_mount_common * * Mount initialization code establishing various mount * fields from the superblock associated with the given * mount structure */ void xfs_sb_mount_common( struct xfs_mount *mp, struct xfs_sb *sbp) { mp->m_agfrotor = mp->m_agirotor = 0; spin_lock_init(&mp->m_agirotor_lock); mp->m_maxagi = mp->m_sb.sb_agcount; mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG; mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT; mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog; mp->m_blockmask = sbp->sb_blocksize - 1; mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; mp->m_blockwmask = mp->m_blockwsize - 1; mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2; mp->m_alloc_mnr[1] = mp->m_alloc_mxr[1] / 2; mp->m_inobt_mxr[0] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_inobt_mxr[1] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 0); mp->m_inobt_mnr[0] = mp->m_inobt_mxr[0] / 2; mp->m_inobt_mnr[1] = mp->m_inobt_mxr[1] / 2; mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 0); mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2; mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2; mp->m_rmap_mxr[0] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_rmap_mxr[1] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 0); mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2; mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2; mp->m_refc_mxr[0] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, true); mp->m_refc_mxr[1] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, false); mp->m_refc_mnr[0] = mp->m_refc_mxr[0] / 2; mp->m_refc_mnr[1] = mp->m_refc_mxr[1] / 2; mp->m_bsize = XFS_FSB_TO_BB(mp, 1); mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK, sbp->sb_inopblock); mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog; if (sbp->sb_spino_align) mp->m_ialloc_min_blks = sbp->sb_spino_align; else mp->m_ialloc_min_blks = mp->m_ialloc_blks; mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); mp->m_ag_max_usable = xfs_alloc_ag_max_usable(mp); } /* * xfs_initialize_perag_data * * Read in each per-ag structure so we can count up the number of * allocated inodes, free inodes and used filesystem blocks as this * information is no longer persistent in the superblock. Once we have * this information, write it into the in-core superblock structure. */ int xfs_initialize_perag_data( struct xfs_mount *mp, xfs_agnumber_t agcount) { xfs_agnumber_t index; xfs_perag_t *pag; xfs_sb_t *sbp = &mp->m_sb; uint64_t ifree = 0; uint64_t ialloc = 0; uint64_t bfree = 0; uint64_t bfreelst = 0; uint64_t btree = 0; int error; for (index = 0; index < agcount; index++) { /* * read the agf, then the agi. This gets us * all the information we need and populates the * per-ag structures for us. */ error = xfs_alloc_pagf_init(mp, NULL, index, 0); if (error) return error; error = xfs_ialloc_pagi_init(mp, NULL, index); if (error) return error; pag = xfs_perag_get(mp, index); ifree += pag->pagi_freecount; ialloc += pag->pagi_count; bfree += pag->pagf_freeblks; bfreelst += pag->pagf_flcount; btree += pag->pagf_btreeblks; xfs_perag_put(pag); } /* Overwrite incore superblock counters with just-read data */ spin_lock(&mp->m_sb_lock); sbp->sb_ifree = ifree; sbp->sb_icount = ialloc; sbp->sb_fdblocks = bfree + bfreelst + btree; spin_unlock(&mp->m_sb_lock); xfs_reinit_percpu_counters(mp); return 0; } /* * xfs_log_sb() can be used to copy arbitrary changes to the in-core superblock * into the superblock buffer to be logged. It does not provide the higher * level of locking that is needed to protect the in-core superblock from * concurrent access. */ void xfs_log_sb( struct xfs_trans *tp) { struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *bp = xfs_trans_getsb(tp, mp, 0); mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount); mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree); mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks); xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb)); } /* * xfs_sync_sb * * Sync the superblock to disk. * * Note that the caller is responsible for checking the frozen state of the * filesystem. This procedure uses the non-blocking transaction allocator and * thus will allow modifications to a frozen fs. This is required because this * code can be called during the process of freezing where use of the high-level * allocator would deadlock. */ int xfs_sync_sb( struct xfs_mount *mp, bool wait) { struct xfs_trans *tp; int error; error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, XFS_TRANS_NO_WRITECOUNT, &tp); if (error) return error; xfs_log_sb(tp); if (wait) xfs_trans_set_sync(tp); return xfs_trans_commit(tp); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_sb.h0000644000000000000000000000275213063067170015423 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_SB_H__ #define __XFS_SB_H__ /* * perag get/put wrappers for ref counting */ extern struct xfs_perag *xfs_perag_get(struct xfs_mount *, xfs_agnumber_t); extern struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *, xfs_agnumber_t, int tag); extern void xfs_perag_put(struct xfs_perag *pag); extern int xfs_initialize_perag_data(struct xfs_mount *, xfs_agnumber_t); extern void xfs_log_sb(struct xfs_trans *tp); extern int xfs_sync_sb(struct xfs_mount *mp, bool wait); extern void xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp); extern void xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from); extern void xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from); extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp); #endif /* __XFS_SB_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_shared.h0000644000000000000000000001233213063067170016260 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_SHARED_H__ #define __XFS_SHARED_H__ /* * Definitions shared between kernel and userspace that don't fit into any other * header file that is shared with userspace. */ struct xfs_ifork; struct xfs_buf; struct xfs_buf_ops; struct xfs_mount; struct xfs_trans; struct xfs_inode; /* * Buffer verifier operations are widely used, including userspace tools */ extern const struct xfs_buf_ops xfs_agf_buf_ops; extern const struct xfs_buf_ops xfs_agi_buf_ops; extern const struct xfs_buf_ops xfs_agf_buf_ops; extern const struct xfs_buf_ops xfs_agfl_buf_ops; extern const struct xfs_buf_ops xfs_allocbt_buf_ops; extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; extern const struct xfs_buf_ops xfs_refcountbt_buf_ops; extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; extern const struct xfs_buf_ops xfs_bmbt_buf_ops; extern const struct xfs_buf_ops xfs_da3_node_buf_ops; extern const struct xfs_buf_ops xfs_dquot_buf_ops; extern const struct xfs_buf_ops xfs_symlink_buf_ops; extern const struct xfs_buf_ops xfs_agi_buf_ops; extern const struct xfs_buf_ops xfs_inobt_buf_ops; extern const struct xfs_buf_ops xfs_inode_buf_ops; extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; extern const struct xfs_buf_ops xfs_dquot_buf_ops; extern const struct xfs_buf_ops xfs_dquot_buf_ra_ops; extern const struct xfs_buf_ops xfs_sb_buf_ops; extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops; extern const struct xfs_buf_ops xfs_symlink_buf_ops; extern const struct xfs_buf_ops xfs_rtbuf_ops; /* * This structure is used to track log items associated with * a transaction. It points to the log item and keeps some * flags to track the state of the log item. It also tracks * the amount of space needed to log the item it describes * once we get to commit processing (see xfs_trans_commit()). */ struct xfs_log_item_desc { struct xfs_log_item *lid_item; struct list_head lid_trans; unsigned char lid_flags; }; #define XFS_LID_DIRTY 0x1 /* log size calculation functions */ int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes); int xfs_log_calc_minimum_size(struct xfs_mount *); /* * Values for t_flags. */ #define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */ #define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */ #define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */ #define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ #define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ #define XFS_TRANS_NOFS 0x80 /* pass KM_NOFS to kmem_alloc */ /* * Field values for xfs_trans_mod_sb. */ #define XFS_TRANS_SB_ICOUNT 0x00000001 #define XFS_TRANS_SB_IFREE 0x00000002 #define XFS_TRANS_SB_FDBLOCKS 0x00000004 #define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008 #define XFS_TRANS_SB_FREXTENTS 0x00000010 #define XFS_TRANS_SB_RES_FREXTENTS 0x00000020 #define XFS_TRANS_SB_DBLOCKS 0x00000040 #define XFS_TRANS_SB_AGCOUNT 0x00000080 #define XFS_TRANS_SB_IMAXPCT 0x00000100 #define XFS_TRANS_SB_REXTSIZE 0x00000200 #define XFS_TRANS_SB_RBMBLOCKS 0x00000400 #define XFS_TRANS_SB_RBLOCKS 0x00000800 #define XFS_TRANS_SB_REXTENTS 0x00001000 #define XFS_TRANS_SB_REXTSLOG 0x00002000 /* * Here we centralize the specification of XFS meta-data buffer reference count * values. This determines how hard the buffer cache tries to hold onto the * buffer. */ #define XFS_AGF_REF 4 #define XFS_AGI_REF 4 #define XFS_AGFL_REF 3 #define XFS_INO_BTREE_REF 3 #define XFS_ALLOC_BTREE_REF 2 #define XFS_BMAP_BTREE_REF 2 #define XFS_RMAP_BTREE_REF 2 #define XFS_DIR_BTREE_REF 2 #define XFS_INO_REF 2 #define XFS_ATTR_BTREE_REF 1 #define XFS_DQUOT_REF 1 #define XFS_REFC_BTREE_REF 1 /* * Flags for xfs_trans_ichgtime(). */ #define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ #define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ #define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */ /* * Symlink decoding/encoding functions */ int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, uint32_t size, struct xfs_buf *bp); bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset, uint32_t size, struct xfs_buf *bp); void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_inode *ip, struct xfs_ifork *ifp); #endif /* __XFS_SHARED_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_symlink_remote.c0000644000000000000000000001174613063067171020057 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * Copyright (c) 2012-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_shared.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" /* * Each contiguous block has a header, so it is not just a simple pathlen * to FSB conversion. */ int xfs_symlink_blocks( struct xfs_mount *mp, int pathlen) { int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize); return (pathlen + buflen - 1) / buflen; } int xfs_symlink_hdr_set( struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, uint32_t size, struct xfs_buf *bp) { struct xfs_dsymlink_hdr *dsl = bp->b_addr; if (!xfs_sb_version_hascrc(&mp->m_sb)) return 0; memset(dsl, 0, sizeof(struct xfs_dsymlink_hdr)); dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC); dsl->sl_offset = cpu_to_be32(offset); dsl->sl_bytes = cpu_to_be32(size); uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid); dsl->sl_owner = cpu_to_be64(ino); dsl->sl_blkno = cpu_to_be64(bp->b_bn); bp->b_ops = &xfs_symlink_buf_ops; return sizeof(struct xfs_dsymlink_hdr); } /* * Checking of the symlink header is split into two parts. the verifier does * CRC, location and bounds checking, the unpacking function checks the path * parameters and owner. */ bool xfs_symlink_hdr_ok( xfs_ino_t ino, uint32_t offset, uint32_t size, struct xfs_buf *bp) { struct xfs_dsymlink_hdr *dsl = bp->b_addr; if (offset != be32_to_cpu(dsl->sl_offset)) return false; if (size != be32_to_cpu(dsl->sl_bytes)) return false; if (ino != be64_to_cpu(dsl->sl_owner)) return false; /* ok */ return true; } static bool xfs_symlink_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_dsymlink_hdr *dsl = bp->b_addr; if (!xfs_sb_version_hascrc(&mp->m_sb)) return false; if (dsl->sl_magic != cpu_to_be32(XFS_SYMLINK_MAGIC)) return false; if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid)) return false; if (bp->b_bn != be64_to_cpu(dsl->sl_blkno)) return false; if (be32_to_cpu(dsl->sl_offset) + be32_to_cpu(dsl->sl_bytes) >= MAXPATHLEN) return false; if (dsl->sl_owner == 0) return false; if (!xfs_log_check_lsn(mp, be64_to_cpu(dsl->sl_lsn))) return false; return true; } static void xfs_symlink_read_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; /* no verification of non-crc buffers */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (!xfs_buf_verify_cksum(bp, XFS_SYMLINK_CRC_OFF)) xfs_buf_ioerror(bp, -EFSBADCRC); else if (!xfs_symlink_verify(bp)) xfs_buf_ioerror(bp, -EFSCORRUPTED); if (bp->b_error) xfs_verifier_error(bp); } static void xfs_symlink_write_verify( struct xfs_buf *bp) { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_buf_log_item *bip = bp->b_fspriv; /* no verification of non-crc buffers */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return; if (!xfs_symlink_verify(bp)) { xfs_buf_ioerror(bp, -EFSCORRUPTED); xfs_verifier_error(bp); return; } if (bip) { struct xfs_dsymlink_hdr *dsl = bp->b_addr; dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn); } xfs_buf_update_cksum(bp, XFS_SYMLINK_CRC_OFF); } const struct xfs_buf_ops xfs_symlink_buf_ops = { .name = "xfs_symlink", .verify_read = xfs_symlink_read_verify, .verify_write = xfs_symlink_write_verify, }; void xfs_symlink_local_to_remote( struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_inode *ip, struct xfs_ifork *ifp) { struct xfs_mount *mp = ip->i_mount; char *buf; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF); if (!xfs_sb_version_hascrc(&mp->m_sb)) { bp->b_ops = NULL; memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); return; } /* * As this symlink fits in an inode literal area, it must also fit in * the smallest buffer the filesystem supports. */ ASSERT(BBTOB(bp->b_length) >= ifp->if_bytes + sizeof(struct xfs_dsymlink_hdr)); bp->b_ops = &xfs_symlink_buf_ops; buf = bp->b_addr; buf += xfs_symlink_hdr_set(mp, ip->i_ino, 0, ifp->if_bytes, bp); memcpy(buf, ifp->if_u1.if_data, ifp->if_bytes); xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) + ifp->if_bytes - 1); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_trans_resv.c0000644000000000000000000007263613063067171017211 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * Copyright (C) 2010 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs_priv.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_bmap_btree.h" #include "xfs_ialloc.h" #include "xfs_trans.h" #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_quota_defs.h" /* * A buffer has a format structure overhead in the log in addition * to the data, so we need to take this into account when reserving * space in a transaction for a buffer. Round the space required up * to a multiple of 128 bytes so that we don't change the historical * reservation that has been used for this overhead. */ STATIC uint xfs_buf_log_overhead(void) { return round_up(sizeof(struct xlog_op_header) + sizeof(struct xfs_buf_log_format), 128); } /* * Calculate out transaction log reservation per item in bytes. * * The nbufs argument is used to indicate the number of items that * will be changed in a transaction. size is used to tell how many * bytes should be reserved per item. */ STATIC uint xfs_calc_buf_res( uint nbufs, uint size) { return nbufs * (size + xfs_buf_log_overhead()); } /* * Per-extent log reservation for the btree changes involved in freeing or * allocating an extent. In classic XFS there were two trees that will be * modified (bnobt + cntbt). With rmap enabled, there are three trees * (rmapbt). With reflink, there are four trees (refcountbt). The number of * blocks reserved is based on the formula: * * num trees * ((2 blocks/level * max depth) - 1) * * Keep in mind that max depth is calculated separately for each type of tree. */ uint xfs_allocfree_log_count( struct xfs_mount *mp, uint num_ops) { uint blocks; blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1); if (xfs_sb_version_hasreflink(&mp->m_sb)) blocks += num_ops * (2 * mp->m_refc_maxlevels - 1); return blocks; } /* * Logging inodes is really tricksy. They are logged in memory format, * which means that what we write into the log doesn't directly translate into * the amount of space they use on disk. * * Case in point - btree format forks in memory format use more space than the * on-disk format. In memory, the buffer contains a normal btree block header so * the btree code can treat it as though it is just another generic buffer. * However, when we write it to the inode fork, we don't write all of this * header as it isn't needed. e.g. the root is only ever in the inode, so * there's no need for sibling pointers which would waste 16 bytes of space. * * Hence when we have an inode with a maximally sized btree format fork, then * amount of information we actually log is greater than the size of the inode * on disk. Hence we need an inode reservation function that calculates all this * correctly. So, we log: * * - 4 log op headers for object * - for the ilf, the inode core and 2 forks * - inode log format object * - the inode core * - two inode forks containing bmap btree root blocks. * - the btree data contained by both forks will fit into the inode size, * hence when combined with the inode core above, we have a total of the * actual inode size. * - the BMBT headers need to be accounted separately, as they are * additional to the records and pointers that fit inside the inode * forks. */ STATIC uint xfs_calc_inode_res( struct xfs_mount *mp, uint ninodes) { return ninodes * (4 * sizeof(struct xlog_op_header) + sizeof(struct xfs_inode_log_format) + mp->m_sb.sb_inodesize + 2 * XFS_BMBT_BLOCK_LEN(mp)); } /* * The free inode btree is a conditional feature and the log reservation * requirements differ slightly from that of the traditional inode allocation * btree. The finobt tracks records for inode chunks with at least one free * inode. A record can be removed from the tree for an inode allocation * or free and thus the finobt reservation is unconditional across: * * - inode allocation * - inode free * - inode chunk allocation * * The 'modify' param indicates to include the record modification scenario. The * 'alloc' param indicates to include the reservation for free space btree * modifications on behalf of finobt modifications. This is required only for * transactions that do not already account for free space btree modifications. * * the free inode btree: max depth * block size * the allocation btrees: 2 trees * (max depth - 1) * block size * the free inode btree entry: block size */ STATIC uint xfs_calc_finobt_res( struct xfs_mount *mp, int alloc, int modify) { uint res; if (!xfs_sb_version_hasfinobt(&mp->m_sb)) return 0; res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)); if (alloc) res += xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); if (modify) res += (uint)XFS_FSB_TO_B(mp, 1); return res; } /* * Various log reservation values. * * These are based on the size of the file system block because that is what * most transactions manipulate. Each adds in an additional 128 bytes per * item logged to try to account for the overhead of the transaction mechanism. * * Note: Most of the reservations underestimate the number of allocation * groups into which they could free extents in the xfs_defer_finish() call. * This is because the number in the worst case is quite high and quite * unusual. In order to fix this we need to change xfs_defer_finish() to free * extents in only a single AG at a time. This will require changes to the * EFI code as well, however, so that the EFI for the extents not freed is * logged again in each transaction. See SGI PV #261917. * * Reservation functions here avoid a huge stack in xfs_trans_init due to * register overflow from temporaries in the calculations. */ /* * In a write transaction we can allocate a maximum of 2 * extents. This gives: * the inode getting the new extents: inode size * the inode's bmap btree: max depth * block size * the agfs of the ags from which the extents are allocated: 2 * sector * the superblock free block counter: sector size * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size * And the bmap_finish transaction can free bmap blocks in a join: * the agfs of the ags containing the blocks: 2 * sector size * the agfls of the ags containing the blocks: 2 * sector size * the super block free block counter: sector size * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size */ STATIC uint xfs_calc_write_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + MAX((xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } /* * In truncating a file we free up to two extents at once. We can modify: * the inode being truncated: inode size * the inode's bmap btree: (max depth + 1) * block size * And the bmap_finish transaction can free the blocks and bmap blocks: * the agf for each of the ags: 4 * sector size * the agfl for each of the ags: 4 * sector size * the super block to reflect the freed blocks: sector size * worst case split in allocation btrees per extent assuming 4 extents: * 4 exts * 2 trees * (2 * max depth - 1) * block size * the inode btree: max depth * blocksize * the allocation btrees: 2 trees * (max depth - 1) * block size */ STATIC uint xfs_calc_itruncate_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + MAX((xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(5, 0) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(2 + mp->m_ialloc_blks + mp->m_in_maxlevels, 0))); } /* * In renaming a files we can modify: * the four inodes involved: 4 * inode size * the two directory btrees: 2 * (max depth + v2) * dir block size * the two directory bmap btrees: 2 * max depth * block size * And the bmap_finish transaction can free dir and bmap blocks (two sets * of bmap blocks) giving: * the agf for the ags in which the blocks live: 3 * sector size * the agfl for the ags in which the blocks live: 3 * sector size * the superblock for the free block count: sector size * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size */ STATIC uint xfs_calc_rename_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + MAX((xfs_calc_inode_res(mp, 4) + xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 3), XFS_FSB_TO_B(mp, 1)))); } /* * For removing an inode from unlinked list at first, we can modify: * the agi hash list and counters: sector size * the on disk inode before ours in the agi hash list: inode cluster size */ STATIC uint xfs_calc_iunlink_remove_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + max_t(uint, XFS_FSB_TO_B(mp, 1), mp->m_inode_cluster_size); } /* * For creating a link to an inode: * the parent directory inode: inode size * the linked inode: inode size * the directory btree could split: (max depth + v2) * dir block size * the directory bmap btree could join or split: (max depth + v2) * blocksize * And the bmap_finish transaction can free some bmap blocks giving: * the agf for the ag in which the blocks live: sector size * the agfl for the ag in which the blocks live: sector size * the superblock for the free block count: sector size * the allocation btrees: 2 trees * (2 * max depth - 1) * block size */ STATIC uint xfs_calc_link_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + xfs_calc_iunlink_remove_reservation(mp) + MAX((xfs_calc_inode_res(mp, 2) + xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)))); } /* * For adding an inode to unlinked list we can modify: * the agi hash list: sector size * the unlinked inode: inode size */ STATIC uint xfs_calc_iunlink_add_reservation(xfs_mount_t *mp) { return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + xfs_calc_inode_res(mp, 1); } /* * For removing a directory entry we can modify: * the parent directory inode: inode size * the removed inode: inode size * the directory btree could join: (max depth + v2) * dir block size * the directory bmap btree could join or split: (max depth + v2) * blocksize * And the bmap_finish transaction can free the dir and bmap blocks giving: * the agf for the ag in which the blocks live: 2 * sector size * the agfl for the ag in which the blocks live: 2 * sector size * the superblock for the free block count: sector size * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size */ STATIC uint xfs_calc_remove_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + xfs_calc_iunlink_add_reservation(mp) + MAX((xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } /* * For create, break it in to the two cases that the transaction * covers. We start with the modify case - allocation done by modification * of the state of existing inodes - and the allocation case. */ /* * For create we can modify: * the parent directory inode: inode size * the new inode: inode size * the inode btree entry: block size * the superblock for the nlink flag: sector size * the directory btree: (max depth + v2) * dir block size * the directory inode's bmap btree: (max depth + v2) * block size * the finobt (record modification and allocation btrees) */ STATIC uint xfs_calc_create_resv_modify( struct xfs_mount *mp) { return xfs_calc_inode_res(mp, 2) + xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + (uint)XFS_FSB_TO_B(mp, 1) + xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) + xfs_calc_finobt_res(mp, 1, 1); } /* * For create we can allocate some inodes giving: * the agi and agf of the ag getting the new inodes: 2 * sectorsize * the superblock for the nlink flag: sector size * the inode blocks allocated: mp->m_ialloc_blks * blocksize * the inode btree: max depth * blocksize * the allocation btrees: 2 trees * (max depth - 1) * block size */ STATIC uint xfs_calc_create_resv_alloc( struct xfs_mount *mp) { return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + mp->m_sb.sb_sectsize + xfs_calc_buf_res(mp->m_ialloc_blks, XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } STATIC uint __xfs_calc_create_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + MAX(xfs_calc_create_resv_alloc(mp), xfs_calc_create_resv_modify(mp)); } /* * For icreate we can allocate some inodes giving: * the agi and agf of the ag getting the new inodes: 2 * sectorsize * the superblock for the nlink flag: sector size * the inode btree: max depth * blocksize * the allocation btrees: 2 trees * (max depth - 1) * block size * the finobt (record insertion) */ STATIC uint xfs_calc_icreate_resv_alloc( struct xfs_mount *mp) { return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + mp->m_sb.sb_sectsize + xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_finobt_res(mp, 0, 0); } STATIC uint xfs_calc_icreate_reservation(xfs_mount_t *mp) { return XFS_DQUOT_LOGRES(mp) + MAX(xfs_calc_icreate_resv_alloc(mp), xfs_calc_create_resv_modify(mp)); } STATIC uint xfs_calc_create_reservation( struct xfs_mount *mp) { if (xfs_sb_version_hascrc(&mp->m_sb)) return xfs_calc_icreate_reservation(mp); return __xfs_calc_create_reservation(mp); } STATIC uint xfs_calc_create_tmpfile_reservation( struct xfs_mount *mp) { uint res = XFS_DQUOT_LOGRES(mp); if (xfs_sb_version_hascrc(&mp->m_sb)) res += xfs_calc_icreate_resv_alloc(mp); else res += xfs_calc_create_resv_alloc(mp); return res + xfs_calc_iunlink_add_reservation(mp); } /* * Making a new directory is the same as creating a new file. */ STATIC uint xfs_calc_mkdir_reservation( struct xfs_mount *mp) { return xfs_calc_create_reservation(mp); } /* * Making a new symplink is the same as creating a new file, but * with the added blocks for remote symlink data which can be up to 1kB in * length (MAXPATHLEN). */ STATIC uint xfs_calc_symlink_reservation( struct xfs_mount *mp) { return xfs_calc_create_reservation(mp) + xfs_calc_buf_res(1, MAXPATHLEN); } /* * In freeing an inode we can modify: * the inode being freed: inode size * the super block free inode counter: sector size * the agi hash list and counters: sector size * the inode btree entry: block size * the on disk inode before ours in the agi hash list: inode cluster size * the inode btree: max depth * blocksize * the allocation btrees: 2 trees * (max depth - 1) * block size * the finobt (record insertion, removal or modification) */ STATIC uint xfs_calc_ifree_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) + xfs_calc_iunlink_remove_reservation(mp) + xfs_calc_buf_res(1, 0) + xfs_calc_buf_res(2 + mp->m_ialloc_blks + mp->m_in_maxlevels, 0) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_finobt_res(mp, 0, 1); } /* * When only changing the inode we log the inode and possibly the superblock * We also add a bit of slop for the transaction stuff. */ STATIC uint xfs_calc_ichange_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); } /* * Growing the data section of the filesystem. * superblock * agi and agf * allocation btrees */ STATIC uint xfs_calc_growdata_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } /* * Growing the rt section of the filesystem. * In the first set of transactions (ALLOC) we allocate space to the * bitmap or summary files. * superblock: sector size * agf of the ag from which the extent is allocated: sector size * bmap btree for bitmap/summary inode: max depth * blocksize * bitmap/summary inode: inode size * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize */ STATIC uint xfs_calc_growrtalloc_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), XFS_FSB_TO_B(mp, 1)) + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } /* * Growing the rt section of the filesystem. * In the second set of transactions (ZERO) we zero the new metadata blocks. * one bitmap/summary block: blocksize */ STATIC uint xfs_calc_growrtzero_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize); } /* * Growing the rt section of the filesystem. * In the third set of transactions (FREE) we update metadata without * allocating any new blocks. * superblock: sector size * bitmap inode: inode size * summary inode: inode size * one bitmap block: blocksize * summary blocks: new summary size */ STATIC uint xfs_calc_growrtfree_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + xfs_calc_inode_res(mp, 2) + xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) + xfs_calc_buf_res(1, mp->m_rsumsize); } /* * Logging the inode modification timestamp on a synchronous write. * inode */ STATIC uint xfs_calc_swrite_reservation( struct xfs_mount *mp) { return xfs_calc_inode_res(mp, 1); } /* * Logging the inode mode bits when writing a setuid/setgid file * inode */ STATIC uint xfs_calc_writeid_reservation( struct xfs_mount *mp) { return xfs_calc_inode_res(mp, 1); } /* * Converting the inode from non-attributed to attributed. * the inode being converted: inode size * agf block and superblock (for block allocation) * the new block (directory sized) * bmap blocks for the new directory block * allocation btrees */ STATIC uint xfs_calc_addafork_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(1, mp->m_dir_geo->blksize) + xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1, XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } /* * Removing the attribute fork of a file * the inode being truncated: inode size * the inode's bmap btree: max depth * block size * And the bmap_finish transaction can free the blocks and bmap blocks: * the agf for each of the ags: 4 * sector size * the agfl for each of the ags: 4 * sector size * the super block to reflect the freed blocks: sector size * worst case split in allocation btrees per extent assuming 4 extents: * 4 exts * 2 trees * (2 * max depth - 1) * block size */ STATIC uint xfs_calc_attrinval_reservation( struct xfs_mount *mp) { return MAX((xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), XFS_FSB_TO_B(mp, 1)))); } /* * Setting an attribute at mount time. * the inode getting the attribute * the superblock for allocations * the agfs extents are allocated from * the attribute btree * max depth * the inode allocation btree * Since attribute transaction space is dependent on the size of the attribute, * the calculation is done partially at mount time and partially at runtime(see * below). */ STATIC uint xfs_calc_attrsetm_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1)); } /* * Setting an attribute at runtime, transaction space unit per block. * the superblock for allocations: sector size * the inode bmap btree could join or split: max depth * block size * Since the runtime attribute transaction space is dependent on the total * blocks needed for the 1st bmap, here we calculate out the space unit for * one block so that the caller could figure out the total space according * to the attibute extent length in blocks by: * ext * M_RES(mp)->tr_attrsetrt.tr_logres */ STATIC uint xfs_calc_attrsetrt_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK), XFS_FSB_TO_B(mp, 1)); } /* * Removing an attribute. * the inode: inode size * the attribute btree could join: max depth * block size * the inode bmap btree could join or split: max depth * block size * And the bmap_finish transaction can free the attr blocks freed giving: * the agf for the ag in which the blocks live: 2 * sector size * the agfl for the ag in which the blocks live: 2 * sector size * the superblock for the free block count: sector size * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size */ STATIC uint xfs_calc_attrrm_reservation( struct xfs_mount *mp) { return XFS_DQUOT_LOGRES(mp) + MAX((xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1)) + (uint)XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)), (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } /* * Clearing a bad agino number in an agi hash bucket. */ STATIC uint xfs_calc_clear_agi_bucket_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); } /* * Adjusting quota limits. * the xfs_disk_dquot_t: sizeof(struct xfs_disk_dquot) */ STATIC uint xfs_calc_qm_setqlim_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot)); } /* * Allocating quota on disk if needed. * the write transaction log space for quota file extent allocation * the unit of quota allocation: one system block size */ STATIC uint xfs_calc_qm_dqalloc_reservation( struct xfs_mount *mp) { return xfs_calc_write_reservation(mp) + xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1); } /* * Turning off quotas. * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2 * the superblock for the quota flags: sector size */ STATIC uint xfs_calc_qm_quotaoff_reservation( struct xfs_mount *mp) { return sizeof(struct xfs_qoff_logitem) * 2 + xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); } /* * End of turning off quotas. * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2 */ STATIC uint xfs_calc_qm_quotaoff_end_reservation( struct xfs_mount *mp) { return sizeof(struct xfs_qoff_logitem) * 2; } /* * Syncing the incore super block changes to disk. * the super block to reflect the changes: sector size */ STATIC uint xfs_calc_sb_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); } void xfs_trans_resv_calc( struct xfs_mount *mp, struct xfs_trans_resv *resp) { /* * The following transactions are logged in physical format and * require a permanent reservation on space. */ resp->tr_write.tr_logres = xfs_calc_write_reservation(mp); if (xfs_sb_version_hasreflink(&mp->m_sb)) resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; else resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp); if (xfs_sb_version_hasreflink(&mp->m_sb)) resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT_REFLINK; else resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp); resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT; resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_link.tr_logres = xfs_calc_link_reservation(mp); resp->tr_link.tr_logcount = XFS_LINK_LOG_COUNT; resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp); resp->tr_remove.tr_logcount = XFS_REMOVE_LOG_COUNT; resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp); resp->tr_symlink.tr_logcount = XFS_SYMLINK_LOG_COUNT; resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_create.tr_logres = xfs_calc_create_reservation(mp); resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT; resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_create_tmpfile.tr_logres = xfs_calc_create_tmpfile_reservation(mp); resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT; resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp); resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT; resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp); resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT; resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_addafork.tr_logres = xfs_calc_addafork_reservation(mp); resp->tr_addafork.tr_logcount = XFS_ADDAFORK_LOG_COUNT; resp->tr_addafork.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_attrinval.tr_logres = xfs_calc_attrinval_reservation(mp); resp->tr_attrinval.tr_logcount = XFS_ATTRINVAL_LOG_COUNT; resp->tr_attrinval.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_attrsetm.tr_logres = xfs_calc_attrsetm_reservation(mp); resp->tr_attrsetm.tr_logcount = XFS_ATTRSET_LOG_COUNT; resp->tr_attrsetm.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_attrrm.tr_logres = xfs_calc_attrrm_reservation(mp); resp->tr_attrrm.tr_logcount = XFS_ATTRRM_LOG_COUNT; resp->tr_attrrm.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_growrtalloc.tr_logres = xfs_calc_growrtalloc_reservation(mp); resp->tr_growrtalloc.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT; resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp); if (xfs_sb_version_hasreflink(&mp->m_sb)) resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; else resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; /* * The following transactions are logged in logical format with * a default log count. */ resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation(mp); resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT; resp->tr_qm_quotaoff.tr_logres = xfs_calc_qm_quotaoff_reservation(mp); resp->tr_qm_quotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT; resp->tr_qm_equotaoff.tr_logres = xfs_calc_qm_quotaoff_end_reservation(mp); resp->tr_qm_equotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT; resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp); resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT; /* The following transaction are logged in logical format */ resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp); resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp); resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp); resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp); resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp); resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp); resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp); resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp); } xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_trans_resv.h0000644000000000000000000001057113063067170017203 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_TRANS_RESV_H__ #define __XFS_TRANS_RESV_H__ struct xfs_mount; /* * structure for maintaining pre-calculated transaction reservations. */ struct xfs_trans_res { uint tr_logres; /* log space unit in bytes per log ticket */ int tr_logcount; /* number of log operations per log ticket */ int tr_logflags; /* log flags, currently only used for indicating * a reservation request is permanent or not */ }; struct xfs_trans_resv { struct xfs_trans_res tr_write; /* extent alloc trans */ struct xfs_trans_res tr_itruncate; /* truncate trans */ struct xfs_trans_res tr_rename; /* rename trans */ struct xfs_trans_res tr_link; /* link trans */ struct xfs_trans_res tr_remove; /* unlink trans */ struct xfs_trans_res tr_symlink; /* symlink trans */ struct xfs_trans_res tr_create; /* create trans */ struct xfs_trans_res tr_create_tmpfile; /* create O_TMPFILE trans */ struct xfs_trans_res tr_mkdir; /* mkdir trans */ struct xfs_trans_res tr_ifree; /* inode free trans */ struct xfs_trans_res tr_ichange; /* inode update trans */ struct xfs_trans_res tr_growdata; /* fs data section grow trans */ struct xfs_trans_res tr_addafork; /* add inode attr fork trans */ struct xfs_trans_res tr_writeid; /* write setuid/setgid file */ struct xfs_trans_res tr_attrinval; /* attr fork buffer * invalidation */ struct xfs_trans_res tr_attrsetm; /* set/create an attribute at * mount time */ struct xfs_trans_res tr_attrsetrt; /* set/create an attribute at * runtime */ struct xfs_trans_res tr_attrrm; /* remove an attribute */ struct xfs_trans_res tr_clearagi; /* clear agi unlinked bucket */ struct xfs_trans_res tr_growrtalloc; /* grow realtime allocations */ struct xfs_trans_res tr_growrtzero; /* grow realtime zeroing */ struct xfs_trans_res tr_growrtfree; /* grow realtime freeing */ struct xfs_trans_res tr_qm_setqlim; /* adjust quota limits */ struct xfs_trans_res tr_qm_dqalloc; /* allocate quota on disk */ struct xfs_trans_res tr_qm_quotaoff; /* turn quota off */ struct xfs_trans_res tr_qm_equotaoff;/* end of turn quota off */ struct xfs_trans_res tr_sb; /* modify superblock */ struct xfs_trans_res tr_fsyncts; /* update timestamps on fsync */ }; /* shorthand way of accessing reservation structure */ #define M_RES(mp) (&(mp)->m_resv) /* * Per-directory log reservation for any directory change. * dir blocks: (1 btree block per level + data block + free block) * dblock size * bmap btree: (levels + 2) * max depth * block size * v2 directory blocks can be fragmented below the dirblksize down to the fsb * size, so account for that in the DAENTER macros. */ #define XFS_DIROP_LOG_RES(mp) \ (XFS_FSB_TO_B(mp, XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK)) + \ (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1))) #define XFS_DIROP_LOG_COUNT(mp) \ (XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \ XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1) /* * Various log count values. */ #define XFS_DEFAULT_LOG_COUNT 1 #define XFS_DEFAULT_PERM_LOG_COUNT 2 #define XFS_ITRUNCATE_LOG_COUNT 2 #define XFS_ITRUNCATE_LOG_COUNT_REFLINK 8 #define XFS_INACTIVE_LOG_COUNT 2 #define XFS_CREATE_LOG_COUNT 2 #define XFS_CREATE_TMPFILE_LOG_COUNT 2 #define XFS_MKDIR_LOG_COUNT 3 #define XFS_SYMLINK_LOG_COUNT 3 #define XFS_REMOVE_LOG_COUNT 2 #define XFS_LINK_LOG_COUNT 2 #define XFS_RENAME_LOG_COUNT 2 #define XFS_WRITE_LOG_COUNT 2 #define XFS_WRITE_LOG_COUNT_REFLINK 8 #define XFS_ADDAFORK_LOG_COUNT 2 #define XFS_ATTRINVAL_LOG_COUNT 1 #define XFS_ATTRSET_LOG_COUNT 3 #define XFS_ATTRRM_LOG_COUNT 3 void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp); uint xfs_allocfree_log_count(struct xfs_mount *mp, uint num_ops); #endif /* __XFS_TRANS_RESV_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_trans_space.h0000644000000000000000000000773713063067171017332 0ustar /* * Copyright (c) 2000,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_TRANS_SPACE_H__ #define __XFS_TRANS_SPACE_H__ /* * Components of space reservations. */ #define XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp) \ (((mp)->m_rmap_mxr[0]) - ((mp)->m_rmap_mnr[0])) #define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) \ (((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0])) #define XFS_EXTENTADD_SPACE_RES(mp,w) (XFS_BM_MAXLEVELS(mp,w) - 1) #define XFS_NEXTENTADD_SPACE_RES(mp,b,w)\ (((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \ XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \ XFS_EXTENTADD_SPACE_RES(mp,w)) #define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)\ (((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \ XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \ XFS_EXTENTADD_SPACE_RES(mp,w) + \ ((b + XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp) - 1) / \ XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp)) * \ (mp)->m_rmap_maxlevels) #define XFS_DAENTER_1B(mp,w) \ ((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1) #define XFS_DAENTER_DBS(mp,w) \ (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0)) #define XFS_DAENTER_BLOCKS(mp,w) \ (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w)) #define XFS_DAENTER_BMAP1B(mp,w) \ XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w) #define XFS_DAENTER_BMAPS(mp,w) \ (XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w)) #define XFS_DAENTER_SPACE_RES(mp,w) \ (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w)) #define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w) #define XFS_DIRENTER_MAX_SPLIT(mp,nl) 1 #define XFS_DIRENTER_SPACE_RES(mp,nl) \ (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \ XFS_DIRENTER_MAX_SPLIT(mp,nl)) #define XFS_DIRREMOVE_SPACE_RES(mp) \ XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) #define XFS_IALLOC_SPACE_RES(mp) \ ((mp)->m_ialloc_blks + \ (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \ ((mp)->m_in_maxlevels - 1))) /* * Space reservation values for various transactions. */ #define XFS_ADDAFORK_SPACE_RES(mp) \ ((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)) #define XFS_ATTRRM_SPACE_RES(mp) \ XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) /* This macro is not used - see inline code in xfs_attr_set */ #define XFS_ATTRSET_SPACE_RES(mp, v) \ (XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + XFS_B_TO_FSB(mp, v)) #define XFS_CREATE_SPACE_RES(mp,nl) \ (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_DIOSTRAT_SPACE_RES(mp, v) \ (XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v)) #define XFS_GROWFS_SPACE_RES(mp) \ (2 * (mp)->m_ag_maxlevels) #define XFS_GROWFSRT_SPACE_RES(mp,b) \ ((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK)) #define XFS_LINK_SPACE_RES(mp,nl) \ XFS_DIRENTER_SPACE_RES(mp,nl) #define XFS_MKDIR_SPACE_RES(mp,nl) \ (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_QM_DQALLOC_SPACE_RES(mp) \ (XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \ XFS_DQUOT_CLUSTER_SIZE_FSB) #define XFS_QM_QINOCREATE_SPACE_RES(mp) \ XFS_IALLOC_SPACE_RES(mp) #define XFS_REMOVE_SPACE_RES(mp) \ XFS_DIRREMOVE_SPACE_RES(mp) #define XFS_RENAME_SPACE_RES(mp,nl) \ (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_SYMLINK_SPACE_RES(mp,nl,b) \ (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b)) #define XFS_IFREE_SPACE_RES(mp) \ (xfs_sb_version_hasfinobt(&mp->m_sb) ? (mp)->m_in_maxlevels : 0) #endif /* __XFS_TRANS_SPACE_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxfs/xfs_types.h0000644000000000000000000001123213063067171016155 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XFS_TYPES_H__ #define __XFS_TYPES_H__ typedef __uint32_t prid_t; /* project ID */ typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */ typedef __uint32_t xfs_agino_t; /* inode # within allocation grp */ typedef __uint32_t xfs_extlen_t; /* extent length in blocks */ typedef __uint32_t xfs_agnumber_t; /* allocation group number */ typedef __int32_t xfs_extnum_t; /* # of extents in a file */ typedef __int16_t xfs_aextnum_t; /* # extents in an attribute fork */ typedef __int64_t xfs_fsize_t; /* bytes in a file */ typedef __uint64_t xfs_ufsize_t; /* unsigned bytes in a file */ typedef __int32_t xfs_suminfo_t; /* type of bitmap summary info */ typedef __int32_t xfs_rtword_t; /* word type for bitmap manipulations */ typedef __int64_t xfs_lsn_t; /* log sequence number */ typedef __int32_t xfs_tid_t; /* transaction identifier */ typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */ typedef __uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */ typedef __uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */ typedef __uint64_t xfs_rtblock_t; /* extent (block) in realtime area */ typedef __uint64_t xfs_fileoff_t; /* block number in a file */ typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */ typedef __int64_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */ typedef __int64_t xfs_sfiloff_t; /* signed block number in a file */ /* * Null values for the types. */ #define NULLFSBLOCK ((xfs_fsblock_t)-1) #define NULLRFSBLOCK ((xfs_rfsblock_t)-1) #define NULLRTBLOCK ((xfs_rtblock_t)-1) #define NULLFILEOFF ((xfs_fileoff_t)-1) #define NULLAGBLOCK ((xfs_agblock_t)-1) #define NULLAGNUMBER ((xfs_agnumber_t)-1) #define NULLEXTNUM ((xfs_extnum_t)-1) #define NULLCOMMITLSN ((xfs_lsn_t)-1) #define NULLFSINO ((xfs_ino_t)-1) #define NULLAGINO ((xfs_agino_t)-1) /* * Max values for extlen, extnum, aextnum. */ #define MAXEXTLEN ((xfs_extlen_t)0x001fffff) /* 21 bits */ #define MAXEXTNUM ((xfs_extnum_t)0x7fffffff) /* signed int */ #define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */ /* * Minimum and maximum blocksize and sectorsize. * The blocksize upper limit is pretty much arbitrary. * The sectorsize upper limit is due to sizeof(sb_sectsize). * CRC enable filesystems use 512 byte inodes, meaning 512 byte block sizes * cannot be used. */ #define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */ #define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */ #define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG) #define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG) #define XFS_MIN_CRC_BLOCKSIZE (1 << (XFS_MIN_BLOCKSIZE_LOG + 1)) #define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */ #define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */ #define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG) #define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG) /* * Inode fork identifiers. */ #define XFS_DATA_FORK 0 #define XFS_ATTR_FORK 1 #define XFS_COW_FORK 2 /* * Min numbers of data/attr fork btree root pointers. */ #define MINDBTPTRS 3 #define MINABTPTRS 2 /* * MAXNAMELEN is the length (including the terminating null) of * the longest permissible file (component) name. */ #define MAXNAMELEN 256 typedef enum { XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi } xfs_lookup_t; typedef enum { XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_MAX } xfs_btnum_t; struct xfs_name { const unsigned char *name; int len; int type; }; /* * uid_t and gid_t are hard-coded to 32 bits in the inode. * Hence, an 'id' in a dquot is 32 bits.. */ typedef __uint32_t xfs_dqid_t; /* * Constants for bit manipulations. */ #define XFS_NBBYLOG 3 /* log2(NBBY) */ #define XFS_WORDLOG 2 /* log2(sizeof(xfs_rtword_t)) */ #define XFS_NBWORDLOG (XFS_NBBYLOG + XFS_WORDLOG) #define XFS_NBWORD (1 << XFS_NBWORDLOG) #define XFS_WORDMASK ((1 << XFS_WORDLOG) - 1) #endif /* __XFS_TYPES_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/libxlog/0000755000000000000000000000000013063067174014135 5ustar xfsprogs-4.9.0+nmu1ubuntu2/libxlog/Makefile0000644000000000000000000000061713063067172015577 0ustar # # Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTLIBRARY = libxlog.la LT_CURRENT = 0 LT_REVISION = 0 LT_AGE = 0 CFILES = xfs_log_recover.c util.c # don't want to link xfs_repair with a debug libxlog. DEBUG = -DNDEBUG default: ltdepend $(LTLIBRARY) include $(BUILDRULES) install install-dev: default -include .ltdep xfsprogs-4.9.0+nmu1ubuntu2/libxlog/util.c0000644000000000000000000001072413063067172015260 0ustar /* * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" int print_exit; int print_skip_uuid; int print_record_header; libxfs_init_t x; /* * Return 1 for dirty, 0 for clean, -1 for errors */ int xlog_is_dirty( struct xfs_mount *mp, struct xlog *log, libxfs_init_t *x, int verbose) { int error; xfs_daddr_t head_blk, tail_blk; memset(log, 0, sizeof(*log)); /* We (re-)init members of libxfs_init_t here? really? */ x->logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); x->logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); x->lbsize = BBSIZE; if (xfs_sb_version_hassector(&mp->m_sb)) x->lbsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT); log->l_dev = mp->m_logdev_targp; log->l_logBBsize = x->logBBsize; log->l_logBBstart = x->logBBstart; log->l_sectBBsize = BTOBB(x->lbsize); log->l_mp = mp; if (xfs_sb_version_hassector(&mp->m_sb)) { log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; ASSERT(log->l_sectbb_log <= mp->m_sectbb_log); /* for larger sector sizes, must have v2 or external log */ ASSERT(log->l_sectbb_log == 0 || log->l_logBBstart == 0 || xfs_sb_version_haslogv2(&mp->m_sb)); ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT); } log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; error = xlog_find_tail(log, &head_blk, &tail_blk); if (error) { xlog_warn(_("%s: cannot find log head/tail " "(xlog_find_tail=%d)\n"), __func__, error); return -1; } if (verbose) xlog_warn( _("%s: head block %" PRId64 " tail block %" PRId64 "\n"), __func__, head_blk, tail_blk); if (head_blk != tail_blk) return 1; return 0; } static int header_check_uuid(xfs_mount_t *mp, xlog_rec_header_t *head) { char uu_log[64], uu_sb[64]; if (print_skip_uuid) return 0; if (!platform_uuid_compare(&mp->m_sb.sb_uuid, &head->h_fs_uuid)) return 0; platform_uuid_unparse(&mp->m_sb.sb_uuid, uu_sb); platform_uuid_unparse(&head->h_fs_uuid, uu_log); printf(_("* ERROR: mismatched uuid in log\n" "* SB : %s\n* log: %s\n"), uu_sb, uu_log); memcpy(&mp->m_sb.sb_uuid, &head->h_fs_uuid, sizeof(uuid_t)); return 0; } int xlog_header_check_recover(xfs_mount_t *mp, xlog_rec_header_t *head) { if (print_record_header) printf(_("\nLOG REC AT LSN cycle %d block %d (0x%x, 0x%x)\n"), CYCLE_LSN(be64_to_cpu(head->h_lsn)), BLOCK_LSN(be64_to_cpu(head->h_lsn)), CYCLE_LSN(be64_to_cpu(head->h_lsn)), BLOCK_LSN(be64_to_cpu(head->h_lsn))); if (be32_to_cpu(head->h_magicno) != XLOG_HEADER_MAGIC_NUM) { printf(_("* ERROR: bad magic number in log header: 0x%x\n"), be32_to_cpu(head->h_magicno)); } else if (header_check_uuid(mp, head)) { /* failed - fall through */ } else if (be32_to_cpu(head->h_fmt) != XLOG_FMT) { printf(_("* ERROR: log format incompatible (log=%d, ours=%d)\n"), be32_to_cpu(head->h_fmt), XLOG_FMT); } else { /* everything is ok */ return 0; } /* bail out now or just carry on regardless */ if (print_exit) xlog_exit(_("Bad log")); return 0; } int xlog_header_check_mount(xfs_mount_t *mp, xlog_rec_header_t *head) { if (platform_uuid_is_null(&head->h_fs_uuid)) return 0; if (header_check_uuid(mp, head)) { /* bail out now or just carry on regardless */ if (print_exit) xlog_exit(_("Bad log")); } return 0; } /* * Userspace versions of common diagnostic routines (varargs fun). */ void xlog_warn(char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fputs("\n", stderr); va_end(ap); } void xlog_exit(char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fputs("\n", stderr); va_end(ap); exit(1); } void xlog_panic(char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fputs("\n", stderr); va_end(ap); abort(); } xfsprogs-4.9.0+nmu1ubuntu2/libxlog/xfs_log_recover.c0000644000000000000000000013377513063067172017505 0ustar /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #define xfs_readonly_buftarg(buftarg) (0) /* avoid set-but-unused var warning. gcc is not very bright. */ #define xlog_clear_stale_blocks(log, taillsn) ({ \ (taillsn) = (taillsn); \ (0); \ }) #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) /* * Verify the given count of basic blocks is valid number of blocks * to specify for an operation involving the given XFS log buffer. * Returns nonzero if the count is valid, 0 otherwise. */ static inline int xlog_buf_bbcount_valid( struct xlog *log, int bbcount) { return bbcount > 0 && bbcount <= log->l_logBBsize; } /* * Allocate a buffer to hold log data. The buffer needs to be able * to map to a range of nbblks basic blocks at any valid (basic * block) offset within the log. */ xfs_buf_t * xlog_get_bp( struct xlog *log, int nbblks) { if (!xlog_buf_bbcount_valid(log, nbblks)) { xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return NULL; } /* * We do log I/O in units of log sectors (a power-of-2 * multiple of the basic block size), so we round up the * requested size to accommodate the basic blocks required * for complete log sectors. * * In addition, the buffer may be used for a non-sector- * aligned block offset, in which case an I/O of the * requested size could extend beyond the end of the * buffer. If the requested size is only 1 basic block it * will never straddle a sector boundary, so this won't be * an issue. Nor will this be a problem if the log I/O is * done in basic blocks (sector size 1). But otherwise we * extend the buffer by one extra log sector to ensure * there's space to accommodate this possibility. */ if (nbblks > 1 && log->l_sectBBsize > 1) nbblks += log->l_sectBBsize; nbblks = round_up(nbblks, log->l_sectBBsize); return libxfs_getbufr(log->l_dev, (xfs_daddr_t)-1, nbblks); } void xlog_put_bp( xfs_buf_t *bp) { libxfs_putbufr(bp); } /* * Return the address of the start of the given block number's data * in a log buffer. The buffer covers a log sector-aligned region. */ STATIC char * xlog_align( struct xlog *log, xfs_daddr_t blk_no, int nbblks, struct xfs_buf *bp) { xfs_daddr_t offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1); ASSERT(offset + nbblks <= bp->b_length); return bp->b_addr + BBTOB(offset); } /* * nbblks should be uint, but oh well. Just want to catch that 32-bit length. */ int xlog_bread_noalign( struct xlog *log, xfs_daddr_t blk_no, int nbblks, struct xfs_buf *bp) { if (!xlog_buf_bbcount_valid(log, nbblks)) { xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return EFSCORRUPTED; } blk_no = round_down(blk_no, log->l_sectBBsize); nbblks = round_up(nbblks, log->l_sectBBsize); ASSERT(nbblks > 0); ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp)); XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); bp->b_error = 0; return libxfs_readbufr(log->l_dev, XFS_BUF_ADDR(bp), bp, nbblks, 0); } int xlog_bread( struct xlog *log, xfs_daddr_t blk_no, int nbblks, struct xfs_buf *bp, char **offset) { int error; error = xlog_bread_noalign(log, blk_no, nbblks, bp); if (error) return error; *offset = xlog_align(log, blk_no, nbblks, bp); return 0; } /* * Read at an offset into the buffer. Returns with the buffer in it's original * state regardless of the result of the read. */ STATIC int xlog_bread_offset( struct xlog *log, xfs_daddr_t blk_no, /* block to read from */ int nbblks, /* blocks to read */ struct xfs_buf *bp, char *offset) { char *orig_offset = bp->b_addr; int orig_len = bp->b_bcount; int error, error2; error = XFS_BUF_SET_PTR(bp, offset, BBTOB(nbblks)); if (error) return error; error = xlog_bread_noalign(log, blk_no, nbblks, bp); /* must reset buffer pointer even on error */ error2 = XFS_BUF_SET_PTR(bp, orig_offset, orig_len); if (error) return error; return error2; } /* * This routine finds (to an approximation) the first block in the physical * log which contains the given cycle. It uses a binary search algorithm. * Note that the algorithm can not be perfect because the disk will not * necessarily be perfect. */ int xlog_find_cycle_start( struct xlog *log, struct xfs_buf *bp, xfs_daddr_t first_blk, xfs_daddr_t *last_blk, uint cycle) { char *offset; xfs_daddr_t mid_blk; xfs_daddr_t end_blk; uint mid_cycle; int error; end_blk = *last_blk; mid_blk = BLK_AVG(first_blk, end_blk); while (mid_blk != first_blk && mid_blk != end_blk) { error = xlog_bread(log, mid_blk, 1, bp, &offset); if (error) return error; mid_cycle = xlog_get_cycle(offset); if (mid_cycle == cycle) end_blk = mid_blk; /* last_half_cycle == mid_cycle */ else first_blk = mid_blk; /* first_half_cycle == mid_cycle */ mid_blk = BLK_AVG(first_blk, end_blk); } ASSERT((mid_blk == first_blk && mid_blk+1 == end_blk) || (mid_blk == end_blk && mid_blk-1 == first_blk)); *last_blk = end_blk; return 0; } /* * Check that a range of blocks does not contain stop_on_cycle_no. * Fill in *new_blk with the block offset where such a block is * found, or with -1 (an invalid block number) if there is no such * block in the range. The scan needs to occur from front to back * and the pointer into the region must be updated since a later * routine will need to perform another test. */ STATIC int xlog_find_verify_cycle( struct xlog *log, xfs_daddr_t start_blk, int nbblks, uint stop_on_cycle_no, xfs_daddr_t *new_blk) { xfs_daddr_t i, j; uint cycle; xfs_buf_t *bp; int bufblks; char *buf = NULL; int error = 0; /* * Greedily allocate a buffer big enough to handle the full * range of basic blocks we'll be examining. If that fails, * try a smaller size. We need to be able to read at least * a log sector, or we're out of luck. */ bufblks = 1 << ffs(nbblks); while (bufblks > log->l_logBBsize) bufblks >>= 1; while (!(bp = xlog_get_bp(log, bufblks))) { bufblks >>= 1; if (bufblks < log->l_sectBBsize) return ENOMEM; } for (i = start_blk; i < start_blk + nbblks; i += bufblks) { int bcount; bcount = min(bufblks, (start_blk + nbblks - i)); error = xlog_bread(log, i, bcount, bp, &buf); if (error) goto out; for (j = 0; j < bcount; j++) { cycle = xlog_get_cycle(buf); if (cycle == stop_on_cycle_no) { *new_blk = i+j; goto out; } buf += BBSIZE; } } *new_blk = -1; out: xlog_put_bp(bp); return error; } /* * Potentially backup over partial log record write. * * In the typical case, last_blk is the number of the block directly after * a good log record. Therefore, we subtract one to get the block number * of the last block in the given buffer. extra_bblks contains the number * of blocks we would have read on a previous read. This happens when the * last log record is split over the end of the physical log. * * extra_bblks is the number of blocks potentially verified on a previous * call to this routine. */ STATIC int xlog_find_verify_log_record( struct xlog *log, xfs_daddr_t start_blk, xfs_daddr_t *last_blk, int extra_bblks) { xfs_daddr_t i; xfs_buf_t *bp; char *offset = NULL; xlog_rec_header_t *head = NULL; int error = 0; int smallmem = 0; int num_blks = *last_blk - start_blk; int xhdrs; ASSERT(start_blk != 0 || *last_blk != start_blk); if (!(bp = xlog_get_bp(log, num_blks))) { if (!(bp = xlog_get_bp(log, 1))) return ENOMEM; smallmem = 1; } else { error = xlog_bread(log, start_blk, num_blks, bp, &offset); if (error) goto out; offset += ((num_blks - 1) << BBSHIFT); } for (i = (*last_blk) - 1; i >= 0; i--) { if (i < start_blk) { /* valid log record not found */ xfs_warn(log->l_mp, "Log inconsistent (didn't find previous header)"); ASSERT(0); error = XFS_ERROR(EIO); goto out; } if (smallmem) { error = xlog_bread(log, i, 1, bp, &offset); if (error) goto out; } head = (xlog_rec_header_t *)offset; if (head->h_magicno == cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) break; if (!smallmem) offset -= BBSIZE; } /* * We hit the beginning of the physical log & still no header. Return * to caller. If caller can handle a return of -1, then this routine * will be called again for the end of the physical log. */ if (i == -1) { error = -1; goto out; } /* * We have the final block of the good log (the first block * of the log record _before_ the head. So we check the uuid. */ if ((error = xlog_header_check_mount(log->l_mp, head))) goto out; /* * We may have found a log record header before we expected one. * last_blk will be the 1st block # with a given cycle #. We may end * up reading an entire log record. In this case, we don't want to * reset last_blk. Only when last_blk points in the middle of a log * record do we update last_blk. */ if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { uint h_size = be32_to_cpu(head->h_size); xhdrs = h_size / XLOG_HEADER_CYCLE_SIZE; if (h_size % XLOG_HEADER_CYCLE_SIZE) xhdrs++; } else { xhdrs = 1; } if (*last_blk - i + extra_bblks != BTOBB(be32_to_cpu(head->h_len)) + xhdrs) *last_blk = i; out: xlog_put_bp(bp); return error; } /* * Head is defined to be the point of the log where the next log write * write could go. This means that incomplete LR writes at the end are * eliminated when calculating the head. We aren't guaranteed that previous * LR have complete transactions. We only know that a cycle number of * current cycle number -1 won't be present in the log if we start writing * from our current block number. * * last_blk contains the block number of the first block with a given * cycle number. * * Return: zero if normal, non-zero if error. */ STATIC int xlog_find_head( struct xlog *log, xfs_daddr_t *return_head_blk) { xfs_buf_t *bp; char *offset; xfs_daddr_t new_blk, first_blk, start_blk, last_blk, head_blk; int num_scan_bblks; uint first_half_cycle, last_half_cycle; uint stop_on_cycle; int error, log_bbnum = log->l_logBBsize; /* Is the end of the log device zeroed? */ if ((error = xlog_find_zeroed(log, &first_blk)) == -1) { *return_head_blk = first_blk; /* Is the whole lot zeroed? */ if (!first_blk) { /* Linux XFS shouldn't generate totally zeroed logs - * mkfs etc write a dummy unmount record to a fresh * log so we can store the uuid in there */ xfs_warn(log->l_mp, "totally zeroed log"); } return 0; } else if (error) { xfs_warn(log->l_mp, "empty log check failed"); return error; } first_blk = 0; /* get cycle # of 1st block */ bp = xlog_get_bp(log, 1); if (!bp) return ENOMEM; error = xlog_bread(log, 0, 1, bp, &offset); if (error) goto bp_err; first_half_cycle = xlog_get_cycle(offset); last_blk = head_blk = log_bbnum - 1; /* get cycle # of last block */ error = xlog_bread(log, last_blk, 1, bp, &offset); if (error) goto bp_err; last_half_cycle = xlog_get_cycle(offset); ASSERT(last_half_cycle != 0); /* * If the 1st half cycle number is equal to the last half cycle number, * then the entire log is stamped with the same cycle number. In this * case, head_blk can't be set to zero (which makes sense). The below * math doesn't work out properly with head_blk equal to zero. Instead, * we set it to log_bbnum which is an invalid block number, but this * value makes the math correct. If head_blk doesn't changed through * all the tests below, *head_blk is set to zero at the very end rather * than log_bbnum. In a sense, log_bbnum and zero are the same block * in a circular file. */ if (first_half_cycle == last_half_cycle) { /* * In this case we believe that the entire log should have * cycle number last_half_cycle. We need to scan backwards * from the end verifying that there are no holes still * containing last_half_cycle - 1. If we find such a hole, * then the start of that hole will be the new head. The * simple case looks like * x | x ... | x - 1 | x * Another case that fits this picture would be * x | x + 1 | x ... | x * In this case the head really is somewhere at the end of the * log, as one of the latest writes at the beginning was * incomplete. * One more case is * x | x + 1 | x ... | x - 1 | x * This is really the combination of the above two cases, and * the head has to end up at the start of the x-1 hole at the * end of the log. * * In the 256k log case, we will read from the beginning to the * end of the log and search for cycle numbers equal to x-1. * We don't worry about the x+1 blocks that we encounter, * because we know that they cannot be the head since the log * started with x. */ head_blk = log_bbnum; stop_on_cycle = last_half_cycle - 1; } else { /* * In this case we want to find the first block with cycle * number matching last_half_cycle. We expect the log to be * some variation on * x + 1 ... | x ... | x * The first block with cycle number x (last_half_cycle) will * be where the new head belongs. First we do a binary search * for the first occurrence of last_half_cycle. The binary * search may not be totally accurate, so then we scan back * from there looking for occurrences of last_half_cycle before * us. If that backwards scan wraps around the beginning of * the log, then we look for occurrences of last_half_cycle - 1 * at the end of the log. The cases we're looking for look * like * v binary search stopped here * x + 1 ... | x | x + 1 | x ... | x * ^ but we want to locate this spot * or * <---------> less than scan distance * x + 1 ... | x ... | x - 1 | x * ^ we want to locate this spot */ stop_on_cycle = last_half_cycle; if ((error = xlog_find_cycle_start(log, bp, first_blk, &head_blk, last_half_cycle))) goto bp_err; } /* * Now validate the answer. Scan back some number of maximum possible * blocks and make sure each one has the expected cycle number. The * maximum is determined by the total possible amount of buffering * in the in-core log. The following number can be made tighter if * we actually look at the block size of the filesystem. */ num_scan_bblks = XLOG_TOTAL_REC_SHIFT(log); if (head_blk >= num_scan_bblks) { /* * We are guaranteed that the entire check can be performed * in one buffer. */ start_blk = head_blk - num_scan_bblks; if ((error = xlog_find_verify_cycle(log, start_blk, num_scan_bblks, stop_on_cycle, &new_blk))) goto bp_err; if (new_blk != -1) head_blk = new_blk; } else { /* need to read 2 parts of log */ /* * We are going to scan backwards in the log in two parts. * First we scan the physical end of the log. In this part * of the log, we are looking for blocks with cycle number * last_half_cycle - 1. * If we find one, then we know that the log starts there, as * we've found a hole that didn't get written in going around * the end of the physical log. The simple case for this is * x + 1 ... | x ... | x - 1 | x * <---------> less than scan distance * If all of the blocks at the end of the log have cycle number * last_half_cycle, then we check the blocks at the start of * the log looking for occurrences of last_half_cycle. If we * find one, then our current estimate for the location of the * first occurrence of last_half_cycle is wrong and we move * back to the hole we've found. This case looks like * x + 1 ... | x | x + 1 | x ... * ^ binary search stopped here * Another case we need to handle that only occurs in 256k * logs is * x + 1 ... | x ... | x+1 | x ... * ^ binary search stops here * In a 256k log, the scan at the end of the log will see the * x + 1 blocks. We need to skip past those since that is * certainly not the head of the log. By searching for * last_half_cycle-1 we accomplish that. */ ASSERT(head_blk <= INT_MAX && (xfs_daddr_t) num_scan_bblks >= head_blk); start_blk = log_bbnum - (num_scan_bblks - head_blk); if ((error = xlog_find_verify_cycle(log, start_blk, num_scan_bblks - (int)head_blk, (stop_on_cycle - 1), &new_blk))) goto bp_err; if (new_blk != -1) { head_blk = new_blk; goto validate_head; } /* * Scan beginning of log now. The last part of the physical * log is good. This scan needs to verify that it doesn't find * the last_half_cycle. */ start_blk = 0; ASSERT(head_blk <= INT_MAX); if ((error = xlog_find_verify_cycle(log, start_blk, (int)head_blk, stop_on_cycle, &new_blk))) goto bp_err; if (new_blk != -1) head_blk = new_blk; } validate_head: /* * Now we need to make sure head_blk is not pointing to a block in * the middle of a log record. */ num_scan_bblks = XLOG_REC_SHIFT(log); if (head_blk >= num_scan_bblks) { start_blk = head_blk - num_scan_bblks; /* don't read head_blk */ /* start ptr at last block ptr before head_blk */ if ((error = xlog_find_verify_log_record(log, start_blk, &head_blk, 0)) == -1) { error = XFS_ERROR(EIO); goto bp_err; } else if (error) goto bp_err; } else { start_blk = 0; ASSERT(head_blk <= INT_MAX); if ((error = xlog_find_verify_log_record(log, start_blk, &head_blk, 0)) == -1) { /* We hit the beginning of the log during our search */ start_blk = log_bbnum - (num_scan_bblks - head_blk); new_blk = log_bbnum; ASSERT(start_blk <= INT_MAX && (xfs_daddr_t) log_bbnum-start_blk >= 0); ASSERT(head_blk <= INT_MAX); if ((error = xlog_find_verify_log_record(log, start_blk, &new_blk, (int)head_blk)) == -1) { error = XFS_ERROR(EIO); goto bp_err; } else if (error) goto bp_err; if (new_blk != log_bbnum) head_blk = new_blk; } else if (error) goto bp_err; } xlog_put_bp(bp); if (head_blk == log_bbnum) *return_head_blk = 0; else *return_head_blk = head_blk; /* * When returning here, we have a good block number. Bad block * means that during a previous crash, we didn't have a clean break * from cycle number N to cycle number N-1. In this case, we need * to find the first block with cycle number N-1. */ return 0; bp_err: xlog_put_bp(bp); if (error) xfs_warn(log->l_mp, "failed to find log head"); return error; } /* * Find the sync block number or the tail of the log. * * This will be the block number of the last record to have its * associated buffers synced to disk. Every log record header has * a sync lsn embedded in it. LSNs hold block numbers, so it is easy * to get a sync block number. The only concern is to figure out which * log record header to believe. * * The following algorithm uses the log record header with the largest * lsn. The entire log record does not need to be valid. We only care * that the header is valid. * * We could speed up search by using current head_blk buffer, but it is not * available. */ int xlog_find_tail( struct xlog *log, xfs_daddr_t *head_blk, xfs_daddr_t *tail_blk) { xlog_rec_header_t *rhead; xlog_op_header_t *op_head; char *offset = NULL; xfs_buf_t *bp; int error, i, found; xfs_daddr_t umount_data_blk; xfs_daddr_t after_umount_blk; xfs_lsn_t tail_lsn; int hblks; found = 0; /* * Find previous log record */ if ((error = xlog_find_head(log, head_blk))) return error; bp = xlog_get_bp(log, 1); if (!bp) return ENOMEM; if (*head_blk == 0) { /* special case */ error = xlog_bread(log, 0, 1, bp, &offset); if (error) goto done; if (xlog_get_cycle(offset) == 0) { *tail_blk = 0; /* leave all other log inited values alone */ goto done; } } /* * Search backwards looking for log record header block */ ASSERT(*head_blk < INT_MAX); for (i = (int)(*head_blk) - 1; i >= 0; i--) { error = xlog_bread(log, i, 1, bp, &offset); if (error) goto done; if (*(__be32 *)offset == cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) { found = 1; break; } } /* * If we haven't found the log record header block, start looking * again from the end of the physical log. XXXmiken: There should be * a check here to make sure we didn't search more than N blocks in * the previous code. */ if (!found) { for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) { error = xlog_bread(log, i, 1, bp, &offset); if (error) goto done; if (*(__be32 *)offset == cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) { found = 2; break; } } } if (!found) { xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__); xlog_put_bp(bp); ASSERT(0); return XFS_ERROR(EIO); } /* find blk_no of tail of log */ rhead = (xlog_rec_header_t *)offset; *tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn)); /* * Reset log values according to the state of the log when we * crashed. In the case where head_blk == 0, we bump curr_cycle * one because the next write starts a new cycle rather than * continuing the cycle of the last good log record. At this * point we have guaranteed that all partial log records have been * accounted for. Therefore, we know that the last good log record * written was complete and ended exactly on the end boundary * of the physical log. */ log->l_prev_block = i; log->l_curr_block = (int)*head_blk; log->l_curr_cycle = be32_to_cpu(rhead->h_cycle); if (found == 2) log->l_curr_cycle++; atomic64_set(&log->l_tail_lsn, be64_to_cpu(rhead->h_tail_lsn)); atomic64_set(&log->l_last_sync_lsn, be64_to_cpu(rhead->h_lsn)); xlog_assign_grant_head(&log->l_reserve_head.grant, log->l_curr_cycle, BBTOB(log->l_curr_block)); xlog_assign_grant_head(&log->l_write_head.grant, log->l_curr_cycle, BBTOB(log->l_curr_block)); /* * Look for unmount record. If we find it, then we know there * was a clean unmount. Since 'i' could be the last block in * the physical log, we convert to a log block before comparing * to the head_blk. * * Save the current tail lsn to use to pass to * xlog_clear_stale_blocks() below. We won't want to clear the * unmount record if there is one, so we pass the lsn of the * unmount record rather than the block after it. */ if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { int h_size = be32_to_cpu(rhead->h_size); int h_version = be32_to_cpu(rhead->h_version); if ((h_version & XLOG_VERSION_2) && (h_size > XLOG_HEADER_CYCLE_SIZE)) { hblks = h_size / XLOG_HEADER_CYCLE_SIZE; if (h_size % XLOG_HEADER_CYCLE_SIZE) hblks++; } else { hblks = 1; } } else { hblks = 1; } after_umount_blk = (i + hblks + (int) BTOBB(be32_to_cpu(rhead->h_len))) % log->l_logBBsize; tail_lsn = atomic64_read(&log->l_tail_lsn); if (*head_blk == after_umount_blk && be32_to_cpu(rhead->h_num_logops) == 1) { umount_data_blk = (i + hblks) % log->l_logBBsize; error = xlog_bread(log, umount_data_blk, 1, bp, &offset); if (error) goto done; op_head = (xlog_op_header_t *)offset; if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) { /* * Set tail and last sync so that newly written * log records will point recovery to after the * current unmount record. */ xlog_assign_atomic_lsn(&log->l_tail_lsn, log->l_curr_cycle, after_umount_blk); xlog_assign_atomic_lsn(&log->l_last_sync_lsn, log->l_curr_cycle, after_umount_blk); *tail_blk = after_umount_blk; /* * Note that the unmount was clean. If the unmount * was not clean, we need to know this to rebuild the * superblock counters from the perag headers if we * have a filesystem using non-persistent counters. */ log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN; } } /* * Make sure that there are no blocks in front of the head * with the same cycle number as the head. This can happen * because we allow multiple outstanding log writes concurrently, * and the later writes might make it out before earlier ones. * * We use the lsn from before modifying it so that we'll never * overwrite the unmount record after a clean unmount. * * Do this only if we are going to recover the filesystem * * NOTE: This used to say "if (!readonly)" * However on Linux, we can & do recover a read-only filesystem. * We only skip recovery if NORECOVERY is specified on mount, * in which case we would not be here. * * But... if the -device- itself is readonly, just skip this. * We can't recover this device anyway, so it won't matter. */ if (!xfs_readonly_buftarg(log->l_mp->m_logdev_targp)) error = xlog_clear_stale_blocks(log, tail_lsn); done: xlog_put_bp(bp); if (error) xfs_warn(log->l_mp, "failed to locate log tail"); return error; } /* * Is the log zeroed at all? * * The last binary search should be changed to perform an X block read * once X becomes small enough. You can then search linearly through * the X blocks. This will cut down on the number of reads we need to do. * * If the log is partially zeroed, this routine will pass back the blkno * of the first block with cycle number 0. It won't have a complete LR * preceding it. * * Return: * 0 => the log is completely written to * -1 => use *blk_no as the first block of the log * >0 => error has occurred */ int xlog_find_zeroed( struct xlog *log, xfs_daddr_t *blk_no) { xfs_buf_t *bp; char *offset; uint first_cycle, last_cycle; xfs_daddr_t new_blk, last_blk, start_blk; xfs_daddr_t num_scan_bblks; int error, log_bbnum = log->l_logBBsize; *blk_no = 0; /* check totally zeroed log */ bp = xlog_get_bp(log, 1); if (!bp) return ENOMEM; error = xlog_bread(log, 0, 1, bp, &offset); if (error) goto bp_err; first_cycle = xlog_get_cycle(offset); if (first_cycle == 0) { /* completely zeroed log */ *blk_no = 0; xlog_put_bp(bp); return -1; } /* check partially zeroed log */ error = xlog_bread(log, log_bbnum-1, 1, bp, &offset); if (error) goto bp_err; last_cycle = xlog_get_cycle(offset); if (last_cycle != 0) { /* log completely written to */ xlog_put_bp(bp); return 0; } else if (first_cycle != 1) { /* * If the cycle of the last block is zero, the cycle of * the first block must be 1. If it's not, maybe we're * not looking at a log... Bail out. */ xfs_warn(log->l_mp, "Log inconsistent or not a log (last==0, first!=1)"); error = XFS_ERROR(EINVAL); goto bp_err; } /* we have a partially zeroed log */ last_blk = log_bbnum-1; if ((error = xlog_find_cycle_start(log, bp, 0, &last_blk, 0))) goto bp_err; /* * Validate the answer. Because there is no way to guarantee that * the entire log is made up of log records which are the same size, * we scan over the defined maximum blocks. At this point, the maximum * is not chosen to mean anything special. XXXmiken */ num_scan_bblks = XLOG_TOTAL_REC_SHIFT(log); ASSERT(num_scan_bblks <= INT_MAX); if (last_blk < num_scan_bblks) num_scan_bblks = last_blk; start_blk = last_blk - num_scan_bblks; /* * We search for any instances of cycle number 0 that occur before * our current estimate of the head. What we're trying to detect is * 1 ... | 0 | 1 | 0... * ^ binary search ends here */ if ((error = xlog_find_verify_cycle(log, start_blk, (int)num_scan_bblks, 0, &new_blk))) goto bp_err; if (new_blk != -1) last_blk = new_blk; /* * Potentially backup over partial log record write. We don't need * to search the end of the log because we know it is zero. */ if ((error = xlog_find_verify_log_record(log, start_blk, &last_blk, 0)) == -1) { error = XFS_ERROR(EIO); goto bp_err; } else if (error) goto bp_err; *blk_no = last_blk; bp_err: xlog_put_bp(bp); if (error) return error; return -1; } STATIC xlog_recover_t * xlog_recover_find_tid( struct hlist_head *head, xlog_tid_t tid) { xlog_recover_t *trans; struct hlist_node *n; hlist_for_each_entry(trans, n, head, r_list) { if (trans->r_log_tid == tid) return trans; } return NULL; } STATIC void xlog_recover_new_tid( struct hlist_head *head, xlog_tid_t tid, xfs_lsn_t lsn) { xlog_recover_t *trans; trans = kmem_zalloc(sizeof(xlog_recover_t), KM_SLEEP); trans->r_log_tid = tid; trans->r_lsn = lsn; INIT_LIST_HEAD(&trans->r_itemq); INIT_HLIST_NODE(&trans->r_list); hlist_add_head(&trans->r_list, head); } STATIC void xlog_recover_add_item( struct list_head *head) { xlog_recover_item_t *item; item = kmem_zalloc(sizeof(xlog_recover_item_t), KM_SLEEP); INIT_LIST_HEAD(&item->ri_list); list_add_tail(&item->ri_list, head); } #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) STATIC int xlog_recover_add_to_cont_trans( struct xlog *log, struct xlog_recover *trans, char *dp, int len) { xlog_recover_item_t *item; char *ptr, *old_ptr; int old_len; if (list_empty(&trans->r_itemq)) { /* finish copying rest of trans header */ xlog_recover_add_item(&trans->r_itemq); ptr = (char *) &trans->r_theader + sizeof(xfs_trans_header_t) - len; memcpy(ptr, dp, len); /* d, s, l */ return 0; } /* take the tail entry */ item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; old_len = item->ri_buf[item->ri_cnt-1].i_len; ptr = kmem_realloc(old_ptr, len+old_len, KM_SLEEP); memcpy(&ptr[old_len], dp, len); /* d, s, l */ item->ri_buf[item->ri_cnt-1].i_len += len; item->ri_buf[item->ri_cnt-1].i_addr = ptr; trace_xfs_log_recover_item_add_cont(log, trans, item, 0); return 0; } /* * The next region to add is the start of a new region. It could be * a whole region or it could be the first part of a new region. Because * of this, the assumption here is that the type and size fields of all * format structures fit into the first 32 bits of the structure. * * This works because all regions must be 32 bit aligned. Therefore, we * either have both fields or we have neither field. In the case we have * neither field, the data part of the region is zero length. We only have * a log_op_header and can throw away the header since a new one will appear * later. If we have at least 4 bytes, then we can determine how many regions * will appear in the current log item. */ STATIC int xlog_recover_add_to_trans( struct xlog *log, struct xlog_recover *trans, char *dp, int len) { xfs_inode_log_format_t *in_f; /* any will do */ xlog_recover_item_t *item; char *ptr; if (!len) return 0; if (list_empty(&trans->r_itemq)) { /* we need to catch log corruptions here */ if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { xfs_warn(log->l_mp, "%s: bad header magic number", __func__); ASSERT(0); return XFS_ERROR(EIO); } if (len == sizeof(xfs_trans_header_t)) xlog_recover_add_item(&trans->r_itemq); memcpy(&trans->r_theader, dp, len); /* d, s, l */ return 0; } ptr = kmem_alloc(len, KM_SLEEP); memcpy(ptr, dp, len); in_f = (xfs_inode_log_format_t *)ptr; /* take the tail entry */ item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); if (item->ri_total != 0 && item->ri_total == item->ri_cnt) { /* tail item is in use, get a new one */ xlog_recover_add_item(&trans->r_itemq); item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); } if (item->ri_total == 0) { /* first region to be added */ if (in_f->ilf_size == 0 || in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) { xfs_warn(log->l_mp, "bad number of regions (%d) in inode log format", in_f->ilf_size); ASSERT(0); kmem_free(ptr); return XFS_ERROR(EIO); } item->ri_total = in_f->ilf_size; item->ri_buf = kmem_zalloc(item->ri_total * sizeof(xfs_log_iovec_t), KM_SLEEP); } ASSERT(item->ri_total > item->ri_cnt); /* Description region is ri_buf[0] */ item->ri_buf[item->ri_cnt].i_addr = ptr; item->ri_buf[item->ri_cnt].i_len = len; item->ri_cnt++; trace_xfs_log_recover_item_add(log, trans, item, 0); return 0; } /* * Free up any resources allocated by the transaction * * Remember that EFIs, EFDs, and IUNLINKs are handled later. */ STATIC void xlog_recover_free_trans( struct xlog_recover *trans) { xlog_recover_item_t *item, *n; int i; list_for_each_entry_safe(item, n, &trans->r_itemq, ri_list) { /* Free the regions in the item. */ list_del(&item->ri_list); for (i = 0; i < item->ri_cnt; i++) kmem_free(item->ri_buf[i].i_addr); /* Free the item itself */ kmem_free(item->ri_buf); kmem_free(item); } /* Free the transaction recover structure */ kmem_free(trans); } /* * Perform the transaction. * * If the transaction modifies a buffer or inode, do it now. Otherwise, * EFIs and EFDs get queued up by adding entries into the AIL for them. */ STATIC int xlog_recover_commit_trans( struct xlog *log, struct xlog_recover *trans, int pass) { int error = 0; hlist_del(&trans->r_list); if ((error = xlog_recover_do_trans(log, trans, pass))) return error; xlog_recover_free_trans(trans); return 0; } STATIC int xlog_recover_unmount_trans( xlog_recover_t *trans) { /* Do nothing now */ xfs_warn(log->l_mp, "%s: Unmount LR", __func__); return 0; } /* * There are two valid states of the r_state field. 0 indicates that the * transaction structure is in a normal state. We have either seen the * start of the transaction or the last operation we added was not a partial * operation. If the last operation we added to the transaction was a * partial operation, we need to mark r_state with XLOG_WAS_CONT_TRANS. * * NOTE: skip LRs with 0 data length. */ STATIC int xlog_recover_process_data( struct xlog *log, struct hlist_head rhash[], struct xlog_rec_header *rhead, char *dp, int pass) { char *lp; int num_logops; xlog_op_header_t *ohead; xlog_recover_t *trans; xlog_tid_t tid; int error; unsigned long hash; uint flags; lp = dp + be32_to_cpu(rhead->h_len); num_logops = be32_to_cpu(rhead->h_num_logops); /* check the log format matches our own - else we can't recover */ if (xlog_header_check_recover(log->l_mp, rhead)) return (XFS_ERROR(EIO)); while ((dp < lp) && num_logops) { ASSERT(dp + sizeof(xlog_op_header_t) <= lp); ohead = (xlog_op_header_t *)dp; dp += sizeof(xlog_op_header_t); if (ohead->oh_clientid != XFS_TRANSACTION && ohead->oh_clientid != XFS_LOG) { xfs_warn(log->l_mp, "%s: bad clientid 0x%x", __func__, ohead->oh_clientid); ASSERT(0); return (XFS_ERROR(EIO)); } tid = be32_to_cpu(ohead->oh_tid); hash = XLOG_RHASH(tid); trans = xlog_recover_find_tid(&rhash[hash], tid); if (trans == NULL) { /* not found; add new tid */ if (ohead->oh_flags & XLOG_START_TRANS) xlog_recover_new_tid(&rhash[hash], tid, be64_to_cpu(rhead->h_lsn)); } else { if (dp + be32_to_cpu(ohead->oh_len) > lp) { xfs_warn(log->l_mp, "%s: bad length 0x%x", __func__, be32_to_cpu(ohead->oh_len)); return (XFS_ERROR(EIO)); } flags = ohead->oh_flags & ~XLOG_END_TRANS; if (flags & XLOG_WAS_CONT_TRANS) flags &= ~XLOG_CONTINUE_TRANS; switch (flags) { case XLOG_COMMIT_TRANS: error = xlog_recover_commit_trans(log, trans, pass); break; case XLOG_UNMOUNT_TRANS: error = xlog_recover_unmount_trans(trans); break; case XLOG_WAS_CONT_TRANS: error = xlog_recover_add_to_cont_trans(log, trans, dp, be32_to_cpu(ohead->oh_len)); break; case XLOG_START_TRANS: xfs_warn(log->l_mp, "%s: bad transaction", __func__); ASSERT(0); error = XFS_ERROR(EIO); break; case 0: case XLOG_CONTINUE_TRANS: error = xlog_recover_add_to_trans(log, trans, dp, be32_to_cpu(ohead->oh_len)); break; default: xfs_warn(log->l_mp, "%s: bad flag 0x%x", __func__, flags); ASSERT(0); error = XFS_ERROR(EIO); break; } if (error) return error; } dp += be32_to_cpu(ohead->oh_len); num_logops--; } return 0; } /* * Upack the log buffer data and crc check it. If the check fails, issue a * warning if and only if the CRC in the header is non-zero. This makes the * check an advisory warning, and the zero CRC check will prevent failure * warnings from being emitted when upgrading the kernel from one that does not * add CRCs by default. * * When filesystems are CRC enabled, this CRC mismatch becomes a fatal log * corruption failure * * XXX: we do not calculate the CRC here yet. It's not clear what we should do * with CRC errors here in userspace, so we'll address that problem later on. */ #define xlog_cksum(l,r,dp,len) ((r)->h_crc) STATIC int xlog_unpack_data_crc( struct xlog_rec_header *rhead, char *dp, struct xlog *log) { __le32 crc; crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len)); if (crc != rhead->h_crc) { if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) { xfs_alert(log->l_mp, "log record CRC mismatch: found 0x%x, expected 0x%x.", le32_to_cpu(rhead->h_crc), le32_to_cpu(crc)); xfs_hex_dump(dp, 32); } /* * If we've detected a log record corruption, then we can't * recover past this point. Abort recovery if we are enforcing * CRC protection by punting an error back up the stack. */ if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) return EFSCORRUPTED; } return 0; } STATIC int xlog_unpack_data( struct xlog_rec_header *rhead, char *dp, struct xlog *log) { int i, j, k; int error; error = xlog_unpack_data_crc(rhead, dp, log); if (error) return error; for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) && i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { *(__be32 *)dp = *(__be32 *)&rhead->h_cycle_data[i]; dp += BBSIZE; } if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { xlog_in_core_2_t *xhdr = (xlog_in_core_2_t *)rhead; for ( ; i < BTOBB(be32_to_cpu(rhead->h_len)); i++) { j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE); k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); *(__be32 *)dp = xhdr[j].hic_xheader.xh_cycle_data[k]; dp += BBSIZE; } } return 0; } STATIC int xlog_valid_rec_header( struct xlog *log, struct xlog_rec_header *rhead, xfs_daddr_t blkno) { int hlen; if (unlikely(rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))) { XFS_ERROR_REPORT("xlog_valid_rec_header(1)", XFS_ERRLEVEL_LOW, log->l_mp); return XFS_ERROR(EFSCORRUPTED); } if (unlikely( (!rhead->h_version || (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) { xfs_warn(log->l_mp, "%s: unrecognised log version (%d).", __func__, be32_to_cpu(rhead->h_version)); return XFS_ERROR(EIO); } /* LR body must have data or it wouldn't have been written */ hlen = be32_to_cpu(rhead->h_len); if (unlikely( hlen <= 0 || hlen > INT_MAX )) { XFS_ERROR_REPORT("xlog_valid_rec_header(2)", XFS_ERRLEVEL_LOW, log->l_mp); return XFS_ERROR(EFSCORRUPTED); } if (unlikely( blkno > log->l_logBBsize || blkno > INT_MAX )) { XFS_ERROR_REPORT("xlog_valid_rec_header(3)", XFS_ERRLEVEL_LOW, log->l_mp); return XFS_ERROR(EFSCORRUPTED); } return 0; } /* * Read the log from tail to head and process the log records found. * Handle the two cases where the tail and head are in the same cycle * and where the active portion of the log wraps around the end of * the physical log separately. The pass parameter is passed through * to the routines called to process the data and is not looked at * here. */ int xlog_do_recovery_pass( struct xlog *log, xfs_daddr_t head_blk, xfs_daddr_t tail_blk, int pass) { xlog_rec_header_t *rhead; xfs_daddr_t blk_no; char *offset; xfs_buf_t *hbp, *dbp; int error = 0, h_size; int bblks, split_bblks; int hblks, split_hblks, wrapped_hblks; struct hlist_head rhash[XLOG_RHASH_SIZE]; ASSERT(head_blk != tail_blk); /* * Read the header of the tail block and get the iclog buffer size from * h_size. Use this to tell how many sectors make up the log header. */ if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { /* * When using variable length iclogs, read first sector of * iclog header and extract the header size from it. Get a * new hbp that is the correct size. */ hbp = xlog_get_bp(log, 1); if (!hbp) return ENOMEM; error = xlog_bread(log, tail_blk, 1, hbp, &offset); if (error) goto bread_err1; rhead = (xlog_rec_header_t *)offset; error = xlog_valid_rec_header(log, rhead, tail_blk); if (error) goto bread_err1; h_size = be32_to_cpu(rhead->h_size); if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) && (h_size > XLOG_HEADER_CYCLE_SIZE)) { hblks = h_size / XLOG_HEADER_CYCLE_SIZE; if (h_size % XLOG_HEADER_CYCLE_SIZE) hblks++; xlog_put_bp(hbp); hbp = xlog_get_bp(log, hblks); } else { hblks = 1; } } else { ASSERT(log->l_sectBBsize == 1); hblks = 1; hbp = xlog_get_bp(log, 1); h_size = XLOG_BIG_RECORD_BSIZE; } if (!hbp) return ENOMEM; dbp = xlog_get_bp(log, BTOBB(h_size)); if (!dbp) { xlog_put_bp(hbp); return ENOMEM; } memset(rhash, 0, sizeof(rhash)); if (tail_blk <= head_blk) { for (blk_no = tail_blk; blk_no < head_blk; ) { error = xlog_bread(log, blk_no, hblks, hbp, &offset); if (error) goto bread_err2; rhead = (xlog_rec_header_t *)offset; error = xlog_valid_rec_header(log, rhead, blk_no); if (error) goto bread_err2; /* blocks in data section */ bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); error = xlog_bread(log, blk_no + hblks, bblks, dbp, &offset); if (error) goto bread_err2; error = xlog_unpack_data(rhead, offset, log); if (error) goto bread_err2; error = xlog_recover_process_data(log, rhash, rhead, offset, pass); if (error) goto bread_err2; blk_no += bblks + hblks; } } else { /* * Perform recovery around the end of the physical log. * When the head is not on the same cycle number as the tail, * we can't do a sequential recovery as above. */ blk_no = tail_blk; while (blk_no < log->l_logBBsize) { /* * Check for header wrapping around physical end-of-log */ offset = hbp->b_addr; split_hblks = 0; wrapped_hblks = 0; if (blk_no + hblks <= log->l_logBBsize) { /* Read header in one read */ error = xlog_bread(log, blk_no, hblks, hbp, &offset); if (error) goto bread_err2; } else { /* This LR is split across physical log end */ if (blk_no != log->l_logBBsize) { /* some data before physical log end */ ASSERT(blk_no <= INT_MAX); split_hblks = log->l_logBBsize - (int)blk_no; ASSERT(split_hblks > 0); error = xlog_bread(log, blk_no, split_hblks, hbp, &offset); if (error) goto bread_err2; } /* * Note: this black magic still works with * large sector sizes (non-512) only because: * - we increased the buffer size originally * by 1 sector giving us enough extra space * for the second read; * - the log start is guaranteed to be sector * aligned; * - we read the log end (LR header start) * _first_, then the log start (LR header end) * - order is important. */ wrapped_hblks = hblks - split_hblks; error = xlog_bread_offset(log, 0, wrapped_hblks, hbp, offset + BBTOB(split_hblks)); if (error) goto bread_err2; } rhead = (xlog_rec_header_t *)offset; error = xlog_valid_rec_header(log, rhead, split_hblks ? blk_no : 0); if (error) goto bread_err2; bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); blk_no += hblks; /* Read in data for log record */ if (blk_no + bblks <= log->l_logBBsize) { error = xlog_bread(log, blk_no, bblks, dbp, &offset); if (error) goto bread_err2; } else { /* This log record is split across the * physical end of log */ offset = dbp->b_addr; split_bblks = 0; if (blk_no != log->l_logBBsize) { /* some data is before the physical * end of log */ ASSERT(!wrapped_hblks); ASSERT(blk_no <= INT_MAX); split_bblks = log->l_logBBsize - (int)blk_no; ASSERT(split_bblks > 0); error = xlog_bread(log, blk_no, split_bblks, dbp, &offset); if (error) goto bread_err2; } /* * Note: this black magic still works with * large sector sizes (non-512) only because: * - we increased the buffer size originally * by 1 sector giving us enough extra space * for the second read; * - the log start is guaranteed to be sector * aligned; * - we read the log end (LR header start) * _first_, then the log start (LR header end) * - order is important. */ error = xlog_bread_offset(log, 0, bblks - split_bblks, dbp, offset + BBTOB(split_bblks)); if (error) goto bread_err2; } error = xlog_unpack_data(rhead, offset, log); if (error) goto bread_err2; error = xlog_recover_process_data(log, rhash, rhead, offset, pass); if (error) goto bread_err2; blk_no += bblks; } ASSERT(blk_no >= log->l_logBBsize); blk_no -= log->l_logBBsize; /* read first part of physical log */ while (blk_no < head_blk) { error = xlog_bread(log, blk_no, hblks, hbp, &offset); if (error) goto bread_err2; rhead = (xlog_rec_header_t *)offset; error = xlog_valid_rec_header(log, rhead, blk_no); if (error) goto bread_err2; bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); error = xlog_bread(log, blk_no+hblks, bblks, dbp, &offset); if (error) goto bread_err2; error = xlog_unpack_data(rhead, offset, log); if (error) goto bread_err2; error = xlog_recover_process_data(log, rhash, rhead, offset, pass); if (error) goto bread_err2; blk_no += bblks + hblks; } } bread_err2: xlog_put_bp(dbp); bread_err1: xlog_put_bp(hbp); return error; } xfsprogs-4.9.0+nmu1ubuntu2/logprint/0000755000000000000000000000000013063067174014333 5ustar xfsprogs-4.9.0+nmu1ubuntu2/logprint/Makefile0000644000000000000000000000113513063067173015772 0ustar # # Copyright (c) 2000-2001,2004 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_logprint HFILES = logprint.h CFILES = logprint.c \ log_copy.c log_dump.c log_misc.c \ log_print_all.c log_print_trans.c log_redo.c LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) LLDFLAGS = -static-libtool-libs default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/logprint/log_copy.c0000644000000000000000000000362013063067173016312 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "logprint.h" /* * Extract a log and write it out to a file */ void xfs_log_copy( struct xlog *log, int fd, char *filename) { int ofd, r; xfs_daddr_t blkno; char buf[XLOG_HEADER_SIZE]; if ((ofd = open(filename, O_CREAT|O_EXCL|O_RDWR|O_TRUNC, 0666)) == -1) { perror("open"); exit(1); } xlog_print_lseek(log, fd, 0, SEEK_SET); for (blkno = 0; blkno < log->l_logBBsize; blkno++) { r = read(fd, buf, sizeof(buf)); if (r < 0) { fprintf(stderr, _("%s: read error (%lld): %s\n"), __FUNCTION__, (long long)blkno, strerror(errno)); continue; } else if (r == 0) { printf(_("%s: physical end of log at %lld\n"), __FUNCTION__, (long long)blkno); break; } else if (r != sizeof(buf)) { fprintf(stderr, _("%s: short read? (%lld)\n"), __FUNCTION__, (long long)blkno); continue; } r = write(ofd, buf, sizeof(buf)); if (r < 0) { fprintf(stderr, _("%s: write error (%lld): %s\n"), __FUNCTION__, (long long)blkno, strerror(errno)); break; } else if (r != sizeof(buf)) { fprintf(stderr, _("%s: short write? (%lld)\n"), __FUNCTION__, (long long)blkno); continue; } } close(ofd); } xfsprogs-4.9.0+nmu1ubuntu2/logprint/log_dump.c0000644000000000000000000000407213063067173016307 0ustar /* * Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "logprint.h" /* * Dump log blocks, not data */ void xfs_log_dump( struct xlog *log, int fd, int print_block_start) { int r; uint last_cycle = -1; xfs_daddr_t blkno, dupblkno; xlog_rec_header_t *hdr; char buf[XLOG_HEADER_SIZE]; dupblkno = 0; hdr = (xlog_rec_header_t *)buf; xlog_print_lseek(log, fd, 0, SEEK_SET); for (blkno = 0; blkno < log->l_logBBsize; blkno++) { r = read(fd, buf, sizeof(buf)); if (r < 0) { fprintf(stderr, _("%s: read error (%lld): %s\n"), __FUNCTION__, (long long)blkno, strerror(errno)); continue; } else if (r == 0) { printf(_("%s: physical end of log at %lld\n"), __FUNCTION__, (long long)blkno); break; } if (CYCLE_LSN(be64_to_cpu(*(__be64 *)buf)) == XLOG_HEADER_MAGIC_NUM && !print_no_data) { printf(_( "%6lld HEADER Cycle %d tail %d:%06d len %6d ops %d\n"), (long long)blkno, be32_to_cpu(hdr->h_cycle), CYCLE_LSN(be64_to_cpu(hdr->h_tail_lsn)), BLOCK_LSN(be64_to_cpu(hdr->h_tail_lsn)), be32_to_cpu(hdr->h_len), be32_to_cpu(hdr->h_num_logops)); } if (xlog_get_cycle(buf) != last_cycle) { printf(_( "[%05lld - %05lld] Cycle 0x%08x New Cycle 0x%08x\n"), (long long)dupblkno, (long long)blkno, last_cycle, xlog_get_cycle(buf)); last_cycle = xlog_get_cycle(buf); dupblkno = blkno; } } } xfsprogs-4.9.0+nmu1ubuntu2/logprint/log_misc.c0000644000000000000000000012064613063067173016303 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "logprint.h" #define CLEARED_BLKS (-5) #define ZEROED_LOG (-4) #define FULL_READ (-3) #define PARTIAL_READ (-2) #define BAD_HEADER (-1) #define NO_ERROR (0) static int logBBsize; typedef struct xlog_split_item { struct xlog_split_item *si_next; struct xlog_split_item *si_prev; xlog_tid_t si_xtid; int si_skip; } xlog_split_item_t; xlog_split_item_t *split_list = NULL; void print_xlog_op_line(void) { printf("--------------------------------------" "--------------------------------------\n"); } /* print_xlog_op_line */ void print_xlog_xhdr_line(void) { printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); } /* print_xlog_xhdr_line */ void print_xlog_record_line(void) { printf("======================================" "======================================\n"); } /* print_xlog_record_line */ void print_stars(void) { printf("***********************************" "***********************************\n"); } /* print_stars */ /* * Given a pointer to a data segment, print out the data as if it were * a log operation header. */ void xlog_print_op_header(xlog_op_header_t *op_head, int i, char **ptr) { xlog_op_header_t hbuf; /* * memmove because on 64/n32, partial reads can cause the op_head * pointer to come in pointing to an odd-numbered byte */ memmove(&hbuf, op_head, sizeof(xlog_op_header_t)); op_head = &hbuf; *ptr += sizeof(xlog_op_header_t); printf(_("Oper (%d): tid: %x len: %d clientid: %s "), i, be32_to_cpu(op_head->oh_tid), be32_to_cpu(op_head->oh_len), (op_head->oh_clientid == XFS_TRANSACTION ? "TRANS" : (op_head->oh_clientid == XFS_LOG ? "LOG" : "ERROR"))); printf(_("flags: ")); if (op_head->oh_flags) { if (op_head->oh_flags & XLOG_START_TRANS) printf("START "); if (op_head->oh_flags & XLOG_COMMIT_TRANS) printf("COMMIT "); if (op_head->oh_flags & XLOG_WAS_CONT_TRANS) printf("WAS_CONT "); if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) printf("UNMOUNT "); if (op_head->oh_flags & XLOG_CONTINUE_TRANS) printf("CONTINUE "); if (op_head->oh_flags & XLOG_END_TRANS) printf("END "); } else { printf(_("none")); } printf("\n"); } /* xlog_print_op_header */ void xlog_print_add_to_trans(xlog_tid_t tid, int skip) { xlog_split_item_t *item; item = (xlog_split_item_t *)calloc(sizeof(xlog_split_item_t), 1); item->si_xtid = tid; item->si_skip = skip; item->si_next = split_list; item->si_prev = NULL; if (split_list) split_list->si_prev = item; split_list = item; } /* xlog_print_add_to_trans */ int xlog_print_find_tid(xlog_tid_t tid, uint was_cont) { xlog_split_item_t *listp = split_list; if (!split_list) { if (was_cont != 0) /* Not first time we have used this tid */ return 1; else return 0; } while (listp) { if (listp->si_xtid == tid) break; listp = listp->si_next; } if (!listp) { return 0; } if (--listp->si_skip == 0) { if (listp == split_list) { /* delete at head */ split_list = listp->si_next; if (split_list) split_list->si_prev = NULL; } else { if (listp->si_next) listp->si_next->si_prev = listp->si_prev; listp->si_prev->si_next = listp->si_next; } free(listp); } return 1; } /* xlog_print_find_tid */ int xlog_print_trans_header(char **ptr, int len) { xfs_trans_header_t *h; char *cptr = *ptr; __uint32_t magic; char *magic_c = (char *)&magic; *ptr += len; magic=*(__uint32_t*)cptr; /* XXX be32_to_cpu soon */ if (len >= 4) { #if __BYTE_ORDER == __LITTLE_ENDIAN printf("%c%c%c%c:", magic_c[3], magic_c[2], magic_c[1], magic_c[0]); #else printf("%c%c%c%c:", magic_c[0], magic_c[1], magic_c[2], magic_c[3]); #endif } if (len != sizeof(xfs_trans_header_t)) { printf(_(" Not enough data to decode further\n")); return 1; } h = (xfs_trans_header_t *)cptr; printf(_(" tid: %x num_items: %d\n"), h->th_tid, h->th_num_items); return 0; } /* xlog_print_trans_header */ int xlog_print_trans_buffer(char **ptr, int len, int *i, int num_ops) { xfs_buf_log_format_t *f; xlog_op_header_t *head = NULL; int num, skip; int super_block = 0; int bucket, col, buckets; __int64_t blkno; xfs_buf_log_format_t lbuf; int size, blen, map_size, struct_size; __be64 x, y; unsigned short flags; /* * memmove to ensure 8-byte alignment for the long longs in * buf_log_format_t structure */ memmove(&lbuf, *ptr, MIN(sizeof(xfs_buf_log_format_t), len)); f = &lbuf; *ptr += len; ASSERT(f->blf_type == XFS_LI_BUF); printf("BUF: "); blkno = f->blf_blkno; size = f->blf_size; blen = f->blf_len; map_size = f->blf_map_size; flags = f->blf_flags; /* * size of the format header is dependent on the size of the bitmap, not * the size of the in-memory structure. Hence the slightly obtuse * calculation. */ struct_size = offsetof(struct xfs_buf_log_format, blf_map_size) + map_size; if (len >= struct_size) { ASSERT((len - sizeof(struct_size)) % sizeof(int) == 0); printf(_("#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d flags: 0x%x\n"), size, (long long)blkno, (unsigned long long)blkno, blen, map_size, flags); if (blkno == 0) super_block = 1; } else { ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */ printf(_("#regs: %d Not printing rest of data\n"), f->blf_size); return size; } num = size-1; /* Check if all regions in this log item were in the given LR ptr */ if (*i+num > num_ops-1) { skip = num - (num_ops-1-*i); num = num_ops-1-*i; } else { skip = 0; } while (num-- > 0) { (*i)++; head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); if (super_block) { printf(_("SUPER BLOCK Buffer: ")); if (be32_to_cpu(head->oh_len) < 4*8) { printf(_("Out of space\n")); } else { printf("\n"); /* * memmove because *ptr may not be 8-byte aligned */ memmove(&x, *ptr, sizeof(__be64)); memmove(&y, *ptr+8, sizeof(__be64)); printf(_("icount: %llu ifree: %llu "), (unsigned long long) be64_to_cpu(x), (unsigned long long) be64_to_cpu(y)); memmove(&x, *ptr+16, sizeof(__be64)); memmove(&y, *ptr+24, sizeof(__be64)); printf(_("fdblks: %llu frext: %llu\n"), (unsigned long long) be64_to_cpu(x), (unsigned long long) be64_to_cpu(y)); } super_block = 0; } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_AGI_MAGIC) { struct xfs_agi *agi, agi_s; /* memmove because *ptr may not be 8-byte aligned */ agi = &agi_s; memmove(agi, *ptr, sizeof(struct xfs_agi)); printf(_("AGI Buffer: XAGI ")); /* * v4 filesystems only contain the fields before the uuid. * Even v5 filesystems don't log any field beneath it. That * means that the size that is logged is almost always going to * be smaller than the structure itself. Hence we need to make * sure that the buffer contains all the data we want to print * rather than just check against the structure size. */ if (be32_to_cpu(head->oh_len) < offsetof(xfs_agi_t, agi_uuid) - XFS_AGI_UNLINKED_BUCKETS*sizeof(xfs_agino_t)) { printf(_("out of space\n")); } else { printf("\n"); printf(_("ver: %d "), be32_to_cpu(agi->agi_versionnum)); printf(_("seq#: %d len: %d cnt: %d root: %d\n"), be32_to_cpu(agi->agi_seqno), be32_to_cpu(agi->agi_length), be32_to_cpu(agi->agi_count), be32_to_cpu(agi->agi_root)); printf(_("level: %d free#: 0x%x newino: 0x%x\n"), be32_to_cpu(agi->agi_level), be32_to_cpu(agi->agi_freecount), be32_to_cpu(agi->agi_newino)); if (be32_to_cpu(head->oh_len) == 128) { buckets = 17; } else if (be32_to_cpu(head->oh_len) == 256) { buckets = 32 + 17; } else { if (head->oh_flags & XLOG_CONTINUE_TRANS) { printf(_("AGI unlinked data skipped ")); printf(_("(CONTINUE set, no space)\n")); continue; } buckets = XFS_AGI_UNLINKED_BUCKETS; } for (bucket = 0; bucket < buckets;) { printf(_("bucket[%d - %d]: "), bucket, bucket+3); for (col = 0; col < 4; col++, bucket++) { if (bucket < buckets) { printf("0x%x ", be32_to_cpu(agi->agi_unlinked[bucket])); } } printf("\n"); } } } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_AGF_MAGIC) { struct xfs_agf *agf, agf_s; /* memmove because *ptr may not be 8-byte aligned */ agf = &agf_s; memmove(agf, *ptr, sizeof(struct xfs_agf)); printf(_("AGF Buffer: XAGF ")); /* * v4 filesystems only contain the fields before the uuid. * Even v5 filesystems don't log any field beneath it. That * means that the size that is logged is almost always going to * be smaller than the structure itself. Hence we need to make * sure that the buffer contains all the data we want to print * rather than just check against the structure size. */ if (be32_to_cpu(head->oh_len) < offsetof(xfs_agf_t, agf_uuid)) { printf(_("Out of space\n")); } else { printf("\n"); printf(_("ver: %d seq#: %d len: %d \n"), be32_to_cpu(agf->agf_versionnum), be32_to_cpu(agf->agf_seqno), be32_to_cpu(agf->agf_length)); printf(_("root BNO: %d CNT: %d\n"), be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]), be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi])); printf(_("level BNO: %d CNT: %d\n"), be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]), be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); printf(_("1st: %d last: %d cnt: %d " "freeblks: %d longest: %d\n"), be32_to_cpu(agf->agf_flfirst), be32_to_cpu(agf->agf_fllast), be32_to_cpu(agf->agf_flcount), be32_to_cpu(agf->agf_freeblks), be32_to_cpu(agf->agf_longest)); } } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_DQUOT_MAGIC) { struct xfs_disk_dquot *dq, dq_s; /* memmove because *ptr may not be 8-byte aligned */ dq = &dq_s; memmove(dq, *ptr, sizeof(struct xfs_disk_dquot)); printf(_("DQUOT Buffer: DQ ")); if (be32_to_cpu(head->oh_len) < sizeof(xfs_disk_dquot_t)) { printf(_("Out of space\n")); } else { printf("\n"); printf(_("ver: %d flags: 0x%x id: %d \n"), dq->d_version, dq->d_flags, be32_to_cpu(dq->d_id)); printf(_("blk limits hard: %llu soft: %llu\n"), (unsigned long long) be64_to_cpu(dq->d_blk_hardlimit), (unsigned long long) be64_to_cpu(dq->d_blk_softlimit)); printf(_("blk count: %llu warns: %d timer: %d\n"), (unsigned long long) be64_to_cpu(dq->d_bcount), (int) be16_to_cpu(dq->d_bwarns), be32_to_cpu(dq->d_btimer)); printf(_("ino limits hard: %llu soft: %llu\n"), (unsigned long long) be64_to_cpu(dq->d_ino_hardlimit), (unsigned long long) be64_to_cpu(dq->d_ino_softlimit)); printf(_("ino count: %llu warns: %d timer: %d\n"), (unsigned long long) be64_to_cpu(dq->d_icount), (int) be16_to_cpu(dq->d_iwarns), be32_to_cpu(dq->d_itimer)); } } else { printf(_("BUF DATA\n")); if (print_data) { uint *dp = (uint *)*ptr; int nums = be32_to_cpu(head->oh_len) >> 2; int i = 0; while (i < nums) { if ((i % 8) == 0) printf("%2x ", i); printf("%8x ", *dp); dp++; i++; if ((i % 8) == 0) printf("\n"); } printf("\n"); } } *ptr += be32_to_cpu(head->oh_len); } if (head && head->oh_flags & XLOG_CONTINUE_TRANS) skip++; return skip; } /* xlog_print_trans_buffer */ int xlog_print_trans_qoff(char **ptr, uint len) { xfs_qoff_logformat_t *f; xfs_qoff_logformat_t lbuf; memmove(&lbuf, *ptr, MIN(sizeof(xfs_qoff_logformat_t), len)); f = &lbuf; *ptr += len; if (len >= sizeof(xfs_qoff_logformat_t)) { printf(_("QOFF: #regs: %d flags: 0x%x\n"), f->qf_size, f->qf_flags); return 0; } else { printf(_("QOFF: Not enough data to decode further\n")); return 1; } } /* xlog_print_trans_qoff */ void xlog_print_trans_inode_core( struct xfs_log_dinode *ip) { printf(_("INODE CORE\n")); printf(_("magic 0x%hx mode 0%ho version %d format %d\n"), ip->di_magic, ip->di_mode, (int)ip->di_version, (int)ip->di_format); printf(_("nlink %hd uid %d gid %d\n"), ip->di_nlink, ip->di_uid, ip->di_gid); printf(_("atime 0x%x mtime 0x%x ctime 0x%x\n"), ip->di_atime.t_sec, ip->di_mtime.t_sec, ip->di_ctime.t_sec); printf(_("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n"), (unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks, ip->di_extsize, ip->di_nextents); printf(_("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n"), ip->di_anextents, (int)ip->di_forkoff, ip->di_dmevmask, ip->di_dmstate); printf(_("flags 0x%x gen 0x%x\n"), ip->di_flags, ip->di_gen); if (ip->di_version == 3) { printf(_("flags2 0x%llx cowextsize 0x%x\n"), (unsigned long long)ip->di_flags2, ip->di_cowextsize); } } void xlog_print_dir2_sf( struct xlog *log, xfs_dir2_sf_hdr_t *sfp, int size) { xfs_ino_t ino; int count; int i; char namebuf[257]; xfs_dir2_sf_entry_t *sfep; printf(_("SHORTFORM DIRECTORY size %d\n"), size); /* bail out for now */ return; printf(_("SHORTFORM DIRECTORY size %d count %d\n"), size, sfp->count); memmove(&ino, &(sfp->parent), sizeof(ino)); printf(_(".. ino 0x%llx\n"), (unsigned long long) be64_to_cpu(ino)); count = sfp->count; sfep = xfs_dir2_sf_firstentry(sfp); for (i = 0; i < count; i++) { ino = M_DIROPS(log->l_mp)->sf_get_ino(sfp, sfep); memmove(namebuf, (sfep->name), sfep->namelen); namebuf[sfep->namelen] = '\0'; printf(_("%s ino 0x%llx namelen %d\n"), namebuf, (unsigned long long)ino, sfep->namelen); sfep = M_DIROPS(log->l_mp)->sf_nextentry(sfp, sfep); } } int xlog_print_trans_inode( struct xlog *log, char **ptr, int len, int *i, int num_ops, int continued) { struct xfs_log_dinode dino; xlog_op_header_t *op_head; xfs_inode_log_format_t dst_lbuf; xfs_inode_log_format_64_t src_lbuf; /* buffer of biggest one */ xfs_inode_log_format_t *f; int mode; int size; /* * print inode type header region * * memmove to ensure 8-byte alignment for the long longs in * xfs_inode_log_format_t structure * * len can be smaller than xfs_inode_log_format_32|64_t * if format data is split over operations */ memmove(&src_lbuf, *ptr, MIN(sizeof(xfs_inode_log_format_64_t), len)); (*i)++; /* bump index */ *ptr += len; if (!continued && (len == sizeof(xfs_inode_log_format_32_t) || len == sizeof(xfs_inode_log_format_64_t))) { f = xfs_inode_item_format_convert((char*)&src_lbuf, len, &dst_lbuf); printf(_("INODE: ")); printf(_("#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n"), f->ilf_size, (unsigned long long)f->ilf_ino, f->ilf_fields, f->ilf_dsize); printf(_(" blkno: %lld len: %d boff: %d\n"), (long long)f->ilf_blkno, f->ilf_len, f->ilf_boffset); } else { ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */ f = (xfs_inode_log_format_t *)&src_lbuf; printf(_("INODE: #regs: %d Not printing rest of data\n"), f->ilf_size); return f->ilf_size; } if (*i >= num_ops) /* end of LR */ return f->ilf_size-1; /* core inode comes 2nd */ op_head = (xlog_op_header_t *)*ptr; xlog_print_op_header(op_head, *i, ptr); if (op_head->oh_flags & XLOG_CONTINUE_TRANS) { return f->ilf_size-1; } memmove(&dino, *ptr, sizeof(dino)); mode = dino.di_mode & S_IFMT; size = (int)dino.di_size; xlog_print_trans_inode_core(&dino); *ptr += xfs_log_dinode_size(dino.di_version); if (*i == num_ops-1 && f->ilf_size == 3) { return 1; } /* does anything come next */ op_head = (xlog_op_header_t *)*ptr; switch (f->ilf_fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) { case XFS_ILOG_DEV: printf(_("DEV inode: no extra region\n")); break; case XFS_ILOG_UUID: printf(_("UUID inode: no extra region\n")); break; } /* Only the inode core is logged */ if (f->ilf_size == 2) return 0; ASSERT(f->ilf_size <= 4); ASSERT((f->ilf_size == 3) || (f->ilf_fields & XFS_ILOG_AFORK)); if (f->ilf_fields & XFS_ILOG_DFORK) { (*i)++; xlog_print_op_header(op_head, *i, ptr); switch (f->ilf_fields & XFS_ILOG_DFORK) { case XFS_ILOG_DEXT: printf(_("EXTENTS inode data\n")); break; case XFS_ILOG_DBROOT: printf(_("BTREE inode data\n")); break; case XFS_ILOG_DDATA: printf(_("LOCAL inode data\n")); if (mode == S_IFDIR) xlog_print_dir2_sf(log, (xfs_dir2_sf_hdr_t *)*ptr, size); break; default: ASSERT((f->ilf_fields & XFS_ILOG_DFORK) == 0); break; } *ptr += be32_to_cpu(op_head->oh_len); if (op_head->oh_flags & XLOG_CONTINUE_TRANS) return 1; op_head = (xlog_op_header_t *)*ptr; } if (f->ilf_fields & XFS_ILOG_AFORK) { (*i)++; xlog_print_op_header(op_head, *i, ptr); switch (f->ilf_fields & XFS_ILOG_AFORK) { case XFS_ILOG_AEXT: printf(_("EXTENTS attr data\n")); break; case XFS_ILOG_ABROOT: printf(_("BTREE attr data\n")); break; case XFS_ILOG_ADATA: printf(_("LOCAL attr data\n")); if (mode == S_IFDIR) xlog_print_dir2_sf(log, (xfs_dir2_sf_hdr_t *)*ptr, size); break; default: ASSERT((f->ilf_fields & XFS_ILOG_AFORK) == 0); break; } *ptr += be32_to_cpu(op_head->oh_len); if (op_head->oh_flags & XLOG_CONTINUE_TRANS) return 1; } return 0; } /* xlog_print_trans_inode */ int xlog_print_trans_dquot(char **ptr, int len, int *i, int num_ops) { xfs_dq_logformat_t *f; xfs_dq_logformat_t lbuf = {0}; xfs_disk_dquot_t ddq; xlog_op_header_t *head = NULL; int num, skip; /* * print dquot header region * * memmove to ensure 8-byte alignment for the long longs in * xfs_dq_logformat_t structure */ memmove(&lbuf, *ptr, MIN(sizeof(xfs_dq_logformat_t), len)); f = &lbuf; (*i)++; /* bump index */ *ptr += len; if (len == sizeof(xfs_dq_logformat_t)) { printf(_("#regs: %d id: 0x%x"), f->qlf_size, f->qlf_id); printf(_(" blkno: %lld len: %d boff: %d\n"), (long long)f->qlf_blkno, f->qlf_len, f->qlf_boffset); } else { ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */ printf(_("DQUOT: #regs: %d Not printing rest of data\n"), f->qlf_size); return f->qlf_size; } num = f->qlf_size-1; /* Check if all regions in this log item were in the given LR ptr */ if (*i+num > num_ops-1) { skip = num - (num_ops-1-*i); num = num_ops-1-*i; } else { skip = 0; } while (num-- > 0) { head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); ASSERT(be32_to_cpu(head->oh_len) == sizeof(xfs_disk_dquot_t)); memmove(&ddq, *ptr, sizeof(xfs_disk_dquot_t)); printf(_("DQUOT: magic 0x%hx flags 0%ho\n"), be16_to_cpu(ddq.d_magic), ddq.d_flags); *ptr += be32_to_cpu(head->oh_len); } if (head && head->oh_flags & XLOG_CONTINUE_TRANS) skip++; return skip; } /* xlog_print_trans_dquot */ STATIC int xlog_print_trans_icreate( char **ptr, int len, int *i, int num_ops) { struct xfs_icreate_log icl_buf = {0}; struct xfs_icreate_log *icl; memmove(&icl_buf, *ptr, MIN(sizeof(struct xfs_icreate_log), len)); icl = &icl_buf; *ptr += len; /* handle complete header only */ if (len != sizeof(struct xfs_icreate_log)) { printf(_("ICR: split header, not printing\n")); return 1; /* to skip leftover in next region */ } printf(_("ICR: #ag: %d agbno: 0x%x len: %d\n" " cnt: %d isize: %d gen: 0x%x\n"), be32_to_cpu(icl->icl_ag), be32_to_cpu(icl->icl_agbno), be32_to_cpu(icl->icl_length), be32_to_cpu(icl->icl_count), be32_to_cpu(icl->icl_isize), be32_to_cpu(icl->icl_gen)); return 0; } /****************************************************************************** * * Log print routines * ****************************************************************************** */ void xlog_print_lseek(struct xlog *log, int fd, xfs_daddr_t blkno, int whence) { #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT) xfs_off_t offset; if (whence == SEEK_SET) offset = BBTOOFF64(blkno+log->l_logBBstart); else offset = BBTOOFF64(blkno); if (lseek(fd, offset, whence) < 0) { fprintf(stderr, _("%s: lseek to %lld failed: %s\n"), progname, (long long)offset, strerror(errno)); exit(1); } } /* xlog_print_lseek */ void print_lsn(char *string, __be64 *lsn) { printf("%s: %u,%u", string, CYCLE_LSN(be64_to_cpu(*lsn)), BLOCK_LSN(be64_to_cpu(*lsn))); } int xlog_print_record( struct xlog *log, int fd, int num_ops, int len, int *read_type, char **partial_buf, xlog_rec_header_t *rhead, xlog_rec_ext_header_t *xhdrs, int bad_hdr_warn) { char *buf, *ptr; int read_len, skip, lost_context = 0; int ret, n, i, j, k; if (print_no_print) return NO_ERROR; if (!len) { printf("\n"); return NO_ERROR; } /* read_len must read up to some block boundary */ read_len = (int) BBTOB(BTOBB(len)); /* read_type => don't malloc() new buffer, use old one */ if (*read_type == FULL_READ) { if ((ptr = buf = malloc(read_len)) == NULL) { fprintf(stderr, _("%s: xlog_print_record: malloc failed\n"), progname); exit(1); } } else { read_len -= *read_type; buf = (char *)((intptr_t)(*partial_buf) + (intptr_t)(*read_type)); ptr = *partial_buf; } if ((ret = (int) read(fd, buf, read_len)) == -1) { fprintf(stderr, _("%s: xlog_print_record: read error\n"), progname); exit(1); } /* Did we overflow the end? */ if (*read_type == FULL_READ && BLOCK_LSN(be64_to_cpu(rhead->h_lsn)) + BTOBB(read_len) >= logBBsize) { *read_type = BBTOB(logBBsize - BLOCK_LSN(be64_to_cpu(rhead->h_lsn))-1); *partial_buf = buf; return PARTIAL_READ; } /* Did we read everything? */ if ((ret == 0 && read_len != 0) || ret != read_len) { *read_type = ret; *partial_buf = buf; return PARTIAL_READ; } if (*read_type != FULL_READ) read_len += *read_type; /* Everything read in. Start from beginning of buffer * Unpack the data, by putting the saved cycle-data back * into the first word of each BB. * Do some checks. */ buf = ptr; for (i = 0; ptr < buf + read_len; ptr += BBSIZE, i++) { xlog_rec_header_t *rechead = (xlog_rec_header_t *)ptr; /* sanity checks */ if (be32_to_cpu(rechead->h_magicno) == XLOG_HEADER_MAGIC_NUM) { /* data should not have magicno as first word * as it should by cycle# */ free(buf); return -1; } else { /* verify cycle# * FIXME: cycle+1 should be a macro pv#900369 */ if (be32_to_cpu(rhead->h_cycle) != be32_to_cpu(*(__be32 *)ptr)) { if ((*read_type == FULL_READ) || (be32_to_cpu(rhead->h_cycle) + 1 != be32_to_cpu(*(__be32 *)ptr))) { free(buf); return -1; } } } /* copy back the data from the header */ if (i < XLOG_HEADER_CYCLE_SIZE / BBSIZE) { /* from 1st header */ *(__be32 *)ptr = rhead->h_cycle_data[i]; } else { ASSERT(xhdrs != NULL); /* from extra headers */ j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE); k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); *(__be32 *)ptr = xhdrs[j-1].xh_cycle_data[k]; } } ptr = buf; for (i=0; ioh_flags & XLOG_WAS_CONT_TRANS) || (op_head->oh_flags & XLOG_CONTINUE_TRANS)); if (continued && be32_to_cpu(op_head->oh_len) == 0) continue; if (print_no_data) { for (n = 0; n < be32_to_cpu(op_head->oh_len); n++) { printf("0x%02x ", (unsigned int)*ptr); if (n % 16 == 15) printf("\n"); ptr++; } printf("\n"); continue; } /* print transaction data */ if (xlog_print_find_tid(be32_to_cpu(op_head->oh_tid), op_head->oh_flags & XLOG_WAS_CONT_TRANS)) { printf(_("Left over region from split log item\n")); /* Skip this leftover bit */ ptr += be32_to_cpu(op_head->oh_len); /* We've lost context; don't complain if next one looks bad too */ lost_context = 1; continue; } if (be32_to_cpu(op_head->oh_len) != 0) { if (*(uint *)ptr == XFS_TRANS_HEADER_MAGIC) { skip = xlog_print_trans_header(&ptr, be32_to_cpu(op_head->oh_len)); } else { switch (*(unsigned short *)ptr) { case XFS_LI_BUF: { skip = xlog_print_trans_buffer(&ptr, be32_to_cpu(op_head->oh_len), &i, num_ops); break; } case XFS_LI_ICREATE: { skip = xlog_print_trans_icreate(&ptr, be32_to_cpu(op_head->oh_len), &i, num_ops); break; } case XFS_LI_INODE: { skip = xlog_print_trans_inode(log, &ptr, be32_to_cpu(op_head->oh_len), &i, num_ops, continued); break; } case XFS_LI_DQUOT: { skip = xlog_print_trans_dquot(&ptr, be32_to_cpu(op_head->oh_len), &i, num_ops); break; } case XFS_LI_EFI: { skip = xlog_print_trans_efi(&ptr, be32_to_cpu(op_head->oh_len), continued); break; } case XFS_LI_EFD: { skip = xlog_print_trans_efd(&ptr, be32_to_cpu(op_head->oh_len)); break; } case XFS_LI_RUI: { skip = xlog_print_trans_rui(&ptr, be32_to_cpu(op_head->oh_len), continued); break; } case XFS_LI_RUD: { skip = xlog_print_trans_rud(&ptr, be32_to_cpu(op_head->oh_len)); break; } case XFS_LI_CUI: { skip = xlog_print_trans_cui(&ptr, be32_to_cpu(op_head->oh_len), continued); break; } case XFS_LI_CUD: { skip = xlog_print_trans_cud(&ptr, be32_to_cpu(op_head->oh_len)); break; } case XFS_LI_BUI: { skip = xlog_print_trans_bui(&ptr, be32_to_cpu(op_head->oh_len), continued); break; } case XFS_LI_BUD: { skip = xlog_print_trans_bud(&ptr, be32_to_cpu(op_head->oh_len)); break; } case XFS_LI_QUOTAOFF: { skip = xlog_print_trans_qoff(&ptr, be32_to_cpu(op_head->oh_len)); break; } case XLOG_UNMOUNT_TYPE: { printf(_("Unmount filesystem\n")); skip = 0; break; } default: { if (bad_hdr_warn && !lost_context) { fprintf(stderr, _("%s: unknown log operation type (%x)\n"), progname, *(unsigned short *)ptr); if (print_exit) { free(buf); return BAD_HEADER; } } else { printf( _("Left over region from split log item\n")); } skip = 0; ptr += be32_to_cpu(op_head->oh_len); lost_context = 0; } } /* switch */ } /* else */ if (skip != 0) xlog_print_add_to_trans(be32_to_cpu(op_head->oh_tid), skip); } } printf("\n"); free(buf); return NO_ERROR; } /* xlog_print_record */ int xlog_print_rec_head(xlog_rec_header_t *head, int *len, int bad_hdr_warn) { int i; char uub[64]; int datalen,bbs; if (print_no_print) return be32_to_cpu(head->h_num_logops); if (!head->h_magicno) return ZEROED_LOG; if (be32_to_cpu(head->h_magicno) != XLOG_HEADER_MAGIC_NUM) { if (bad_hdr_warn) printf(_("Header 0x%x wanted 0x%x\n"), be32_to_cpu(head->h_magicno), XLOG_HEADER_MAGIC_NUM); return BAD_HEADER; } /* check for cleared blocks written by xlog_clear_stale_blocks() */ if (!head->h_len && !head->h_crc && !head->h_prev_block && !head->h_num_logops && !head->h_size) return CLEARED_BLKS; datalen=be32_to_cpu(head->h_len); bbs=BTOBB(datalen); printf(_("cycle: %d version: %d "), be32_to_cpu(head->h_cycle), be32_to_cpu(head->h_version)); print_lsn(" lsn", &head->h_lsn); print_lsn(" tail_lsn", &head->h_tail_lsn); printf("\n"); printf(_("length of Log Record: %d prev offset: %d num ops: %d\n"), datalen, be32_to_cpu(head->h_prev_block), be32_to_cpu(head->h_num_logops)); if (print_overwrite) { printf(_("cycle num overwrites: ")); for (i=0; i< MIN(bbs, XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) printf("%d - 0x%x ", i, be32_to_cpu(head->h_cycle_data[i])); printf("\n"); } platform_uuid_unparse(&head->h_fs_uuid, uub); printf(_("uuid: %s format: "), uub); switch (be32_to_cpu(head->h_fmt)) { case XLOG_FMT_UNKNOWN: printf(_("unknown\n")); break; case XLOG_FMT_LINUX_LE: printf(_("little endian linux\n")); break; case XLOG_FMT_LINUX_BE: printf(_("big endian linux\n")); break; case XLOG_FMT_IRIX_BE: printf(_("big endian irix\n")); break; default: printf("? (%d)\n", be32_to_cpu(head->h_fmt)); break; } printf(_("h_size: %d\n"), be32_to_cpu(head->h_size)); *len = be32_to_cpu(head->h_len); return(be32_to_cpu(head->h_num_logops)); } /* xlog_print_rec_head */ void xlog_print_rec_xhead(xlog_rec_ext_header_t *head, int coverage) { int i; print_xlog_xhdr_line(); printf(_("extended-header: cycle: %d\n"), be32_to_cpu(head->xh_cycle)); if (print_overwrite) { printf(_("cycle num overwrites: ")); for (i = 0; i < coverage; i++) printf("%d - 0x%x ", i, be32_to_cpu(head->xh_cycle_data[i])); printf("\n"); } } /* xlog_print_rec_xhead */ static void print_xlog_bad_zeroed(xfs_daddr_t blkno) { print_stars(); printf(_("* ERROR: found data after zeroed blocks block=%-21lld *\n"), (long long)blkno); print_stars(); if (print_exit) xlog_exit("Bad log - data after zeroed blocks"); } /* print_xlog_bad_zeroed */ static void print_xlog_bad_header(xfs_daddr_t blkno, char *buf) { print_stars(); printf(_("* ERROR: header cycle=%-11d block=%-21lld *\n"), xlog_get_cycle(buf), (long long)blkno); print_stars(); if (print_exit) xlog_exit("Bad log record header"); } /* print_xlog_bad_header */ void print_xlog_bad_data(xfs_daddr_t blkno) { print_stars(); printf(_("* ERROR: data block=%-21lld *\n"), (long long)blkno); print_stars(); if (print_exit) xlog_exit("Bad data in log"); } /* print_xlog_bad_data */ static void print_xlog_bad_reqd_hdrs(xfs_daddr_t blkno, int num_reqd, int num_hdrs) { print_stars(); printf(_("* ERROR: for header block=%lld\n" "* not enough hdrs for data length, " "required num = %d, hdr num = %d\n"), (long long)blkno, num_reqd, num_hdrs); print_stars(); if (print_exit) xlog_exit(_("Not enough headers for data length.")); } /* print_xlog_bad_reqd_hdrs */ static void xlog_reallocate_xhdrs(int num_hdrs, xlog_rec_ext_header_t **ret_xhdrs) { int len = (num_hdrs-1) * sizeof(xlog_rec_ext_header_t); *ret_xhdrs = (xlog_rec_ext_header_t *)realloc(*ret_xhdrs, len); if (*ret_xhdrs == NULL) { fprintf(stderr, _("%s: xlog_print: malloc failed for ext hdrs\n"), progname); exit(1); } } /* for V2 logs read each extra hdr and print it out */ static int xlog_print_extended_headers( int fd, int len, xfs_daddr_t *blkno, xlog_rec_header_t *hdr, int *ret_num_hdrs, xlog_rec_ext_header_t **ret_xhdrs) { int i, j; int coverage_bb; int num_hdrs; int num_required; char xhbuf[XLOG_HEADER_SIZE]; xlog_rec_ext_header_t *x; num_required = howmany(len, XLOG_HEADER_CYCLE_SIZE); num_hdrs = be32_to_cpu(hdr->h_size) / XLOG_HEADER_CYCLE_SIZE; if (be32_to_cpu(hdr->h_size) % XLOG_HEADER_CYCLE_SIZE) num_hdrs++; if (num_required > num_hdrs) { print_xlog_bad_reqd_hdrs((*blkno)-1, num_required, num_hdrs); } if (num_hdrs == 1) { free(*ret_xhdrs); *ret_xhdrs = NULL; *ret_num_hdrs = 1; return 0; } if (*ret_xhdrs == NULL || num_hdrs > *ret_num_hdrs) { xlog_reallocate_xhdrs(num_hdrs, ret_xhdrs); } *ret_num_hdrs = num_hdrs; /* don't include 1st header */ for (i = 1, x = *ret_xhdrs; i < num_hdrs; i++, (*blkno)++, x++) { /* read one extra header blk */ if (read(fd, xhbuf, 512) == 0) { printf(_("%s: physical end of log\n"), progname); print_xlog_record_line(); /* reached the end so return 1 */ return 1; } if (print_only_data) { printf(_("BLKNO: %lld\n"), (long long)*blkno); xlog_recover_print_data(xhbuf, 512); } else { if (i == num_hdrs - 1) { /* last header */ coverage_bb = BTOBB(len) % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); } else { /* earliear header */ coverage_bb = XLOG_HEADER_CYCLE_SIZE / BBSIZE; } xlog_print_rec_xhead((xlog_rec_ext_header_t*)xhbuf, coverage_bb); } /* Copy from buffer into xhdrs array for later. * Could endian convert here but then code later on * will look asymmetric with the 1 hdr normal case * which does endian coversion on access. */ x->xh_cycle = ((xlog_rec_ext_header_t*)xhbuf)->xh_cycle; for (j = 0; j < XLOG_HEADER_CYCLE_SIZE / BBSIZE; j++) { x->xh_cycle_data[j] = ((xlog_rec_ext_header_t*)xhbuf)->xh_cycle_data[j]; } } return 0; } /* * This code is gross and needs to be rewritten. */ void xfs_log_print(struct xlog *log, int fd, int print_block_start) { char hbuf[XLOG_HEADER_SIZE]; xlog_rec_header_t *hdr = (xlog_rec_header_t *)&hbuf[0]; xlog_rec_ext_header_t *xhdrs = NULL; int num_ops, len, num_hdrs = 1; xfs_daddr_t block_end = 0, block_start, blkno, error; xfs_daddr_t zeroed_blkno = 0, cleared_blkno = 0; int read_type = FULL_READ; char *partial_buf; int zeroed = 0; int cleared = 0; int first_hdr_found = 0; logBBsize = log->l_logBBsize; /* * Normally, block_start and block_end are the same value since we * are printing the entire log. However, if the start block is given, * we still end at the end of the logical log. */ if ((error = xlog_print_find_oldest(log, &block_end))) { fprintf(stderr, _("%s: problem finding oldest LR\n"), progname); return; } if (print_block_start == -1) block_start = block_end; else block_start = print_block_start; xlog_print_lseek(log, fd, block_start, SEEK_SET); blkno = block_start; for (;;) { if (read(fd, hbuf, 512) == 0) { printf(_("%s: physical end of log\n"), progname); print_xlog_record_line(); break; } if (print_only_data) { printf(_("BLKNO: %lld\n"), (long long)blkno); xlog_recover_print_data(hbuf, 512); blkno++; goto loop; } num_ops = xlog_print_rec_head(hdr, &len, first_hdr_found); blkno++; if (zeroed && num_ops != ZEROED_LOG) { printf(_("%s: after %d zeroed blocks\n"), progname, zeroed); /* once we find zeroed blocks - that's all we expect */ print_xlog_bad_zeroed(blkno-1); /* reset count since we're assuming previous zeroed blocks * were bad */ zeroed = 0; } if (num_ops == ZEROED_LOG || num_ops == CLEARED_BLKS || num_ops == BAD_HEADER) { if (num_ops == ZEROED_LOG) { if (zeroed == 0) zeroed_blkno = blkno-1; zeroed++; } else if (num_ops == CLEARED_BLKS) { if (cleared == 0) cleared_blkno = blkno-1; cleared++; } else { if (!first_hdr_found) block_start = blkno; else print_xlog_bad_header(blkno-1, hbuf); } goto loop; } if (be32_to_cpu(hdr->h_version) == 2) { if (xlog_print_extended_headers(fd, len, &blkno, hdr, &num_hdrs, &xhdrs) != 0) break; } error = xlog_print_record(log, fd, num_ops, len, &read_type, &partial_buf, hdr, xhdrs, first_hdr_found); first_hdr_found++; switch (error) { case 0: { blkno += BTOBB(len); if (print_block_start != -1 && blkno >= block_end) /* If start specified, we */ goto end; /* end early */ break; } case -1: { print_xlog_bad_data(blkno-1); if (print_block_start != -1 && blkno >= block_end) /* If start specified, */ goto end; /* we end early */ xlog_print_lseek(log, fd, blkno, SEEK_SET); goto loop; } case PARTIAL_READ: { print_xlog_record_line(); printf(_("%s: physical end of log\n"), progname); print_xlog_record_line(); blkno = 0; xlog_print_lseek(log, fd, 0, SEEK_SET); /* * We may have hit the end of the log when we started at 0. * In this case, just end. */ if (block_start == 0) goto end; goto partial_log_read; } default: xlog_panic(_("illegal value")); } print_xlog_record_line(); loop: if (blkno >= logBBsize) { if (cleared) { printf(_("%s: skipped %d cleared blocks in range: %lld - %lld\n"), progname, cleared, (long long)(cleared_blkno), (long long)(cleared + cleared_blkno - 1)); if (cleared == logBBsize) printf(_("%s: totally cleared log\n"), progname); cleared=0; } if (zeroed) { printf(_("%s: skipped %d zeroed blocks in range: %lld - %lld\n"), progname, zeroed, (long long)(zeroed_blkno), (long long)(zeroed + zeroed_blkno - 1)); if (zeroed == logBBsize) printf(_("%s: totally zeroed log\n"), progname); zeroed=0; } printf(_("%s: physical end of log\n"), progname); print_xlog_record_line(); break; } } /* Do we need to print the first part of physical log? */ if (block_start != 0) { blkno = 0; xlog_print_lseek(log, fd, 0, SEEK_SET); for (;;) { if (read(fd, hbuf, 512) == 0) { xlog_panic(_("xlog_find_head: bad read")); } if (print_only_data) { printf(_("BLKNO: %lld\n"), (long long)blkno); xlog_recover_print_data(hbuf, 512); blkno++; goto loop2; } num_ops = xlog_print_rec_head(hdr, &len, first_hdr_found); blkno++; if (num_ops == ZEROED_LOG || num_ops == CLEARED_BLKS || num_ops == BAD_HEADER) { /* we only expect zeroed log entries or cleared log * entries at the end of the _physical_ log, * so treat them the same as bad blocks here */ print_xlog_bad_header(blkno-1, hbuf); if (blkno >= block_end) break; continue; } if (be32_to_cpu(hdr->h_version) == 2) { if (xlog_print_extended_headers(fd, len, &blkno, hdr, &num_hdrs, &xhdrs) != 0) break; } partial_log_read: error= xlog_print_record(log, fd, num_ops, len, &read_type, &partial_buf, (xlog_rec_header_t *)hbuf, xhdrs, first_hdr_found); if (read_type != FULL_READ) len -= read_type; read_type = FULL_READ; if (!error) blkno += BTOBB(len); else { print_xlog_bad_data(blkno-1); xlog_print_lseek(log, fd, blkno, SEEK_SET); goto loop2; } print_xlog_record_line(); loop2: if (blkno >= block_end) break; } } end: printf(_("%s: logical end of log\n"), progname); print_xlog_record_line(); } /* * if necessary, convert an xfs_inode_log_format struct from 32bit or 64 bit versions * (which can have different field alignments) to the native version */ xfs_inode_log_format_t * xfs_inode_item_format_convert(char *src_buf, uint len, xfs_inode_log_format_t *in_f) { /* if we have native format then just return buf without copying data */ if (len == sizeof(xfs_inode_log_format_t)) { return (xfs_inode_log_format_t *)src_buf; } if (len == sizeof(xfs_inode_log_format_32_t)) { xfs_inode_log_format_32_t *in_f32; in_f32 = (xfs_inode_log_format_32_t *)src_buf; in_f->ilf_type = in_f32->ilf_type; in_f->ilf_size = in_f32->ilf_size; in_f->ilf_fields = in_f32->ilf_fields; in_f->ilf_asize = in_f32->ilf_asize; in_f->ilf_dsize = in_f32->ilf_dsize; in_f->ilf_ino = in_f32->ilf_ino; /* copy biggest */ memcpy(&in_f->ilf_u.ilfu_uuid, &in_f32->ilf_u.ilfu_uuid, sizeof(uuid_t)); in_f->ilf_blkno = in_f32->ilf_blkno; in_f->ilf_len = in_f32->ilf_len; in_f->ilf_boffset = in_f32->ilf_boffset; } else { xfs_inode_log_format_64_t *in_f64; ASSERT(len == sizeof(xfs_inode_log_format_64_t)); in_f64 = (xfs_inode_log_format_64_t *)src_buf; in_f->ilf_type = in_f64->ilf_type; in_f->ilf_size = in_f64->ilf_size; in_f->ilf_fields = in_f64->ilf_fields; in_f->ilf_asize = in_f64->ilf_asize; in_f->ilf_dsize = in_f64->ilf_dsize; in_f->ilf_ino = in_f64->ilf_ino; /* copy biggest */ memcpy(&in_f->ilf_u.ilfu_uuid, &in_f64->ilf_u.ilfu_uuid, sizeof(uuid_t)); in_f->ilf_blkno = in_f64->ilf_blkno; in_f->ilf_len = in_f64->ilf_len; in_f->ilf_boffset = in_f64->ilf_boffset; } return in_f; } xfsprogs-4.9.0+nmu1ubuntu2/logprint/log_print_all.c0000644000000000000000000003407013063067173017327 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "logprint.h" /* * Start is defined to be the block pointing to the oldest valid log record. */ int xlog_print_find_oldest( struct xlog *log, xfs_daddr_t *last_blk) { xfs_buf_t *bp; xfs_daddr_t first_blk; uint first_half_cycle, last_half_cycle; int error = 0; if (xlog_find_zeroed(log, &first_blk)) return 0; first_blk = 0; /* read first block */ bp = xlog_get_bp(log, 1); xlog_bread_noalign(log, 0, 1, bp); first_half_cycle = xlog_get_cycle(XFS_BUF_PTR(bp)); *last_blk = log->l_logBBsize-1; /* read last block */ xlog_bread_noalign(log, *last_blk, 1, bp); last_half_cycle = xlog_get_cycle(XFS_BUF_PTR(bp)); ASSERT(last_half_cycle != 0); if (first_half_cycle == last_half_cycle) /* all cycle nos are same */ *last_blk = 0; else /* have 1st and last; look for middle cycle */ error = xlog_find_cycle_start(log, bp, first_blk, last_blk, last_half_cycle); xlog_put_bp(bp); return error; } void xlog_recover_print_data( char *p, int len) { if (print_data) { uint *dp = (uint *)p; int nums = len >> 2; int j = 0; while (j < nums) { if ((j % 8) == 0) printf("%2x ", j); printf("%8x ", *dp); dp++; j++; if ((j % 8) == 0) printf("\n"); } printf("\n"); } } STATIC void xlog_recover_print_buffer( xlog_recover_item_t *item) { xfs_agi_t *agi; xfs_agf_t *agf; xfs_buf_log_format_t *f; char *p; int len, num, i; xfs_daddr_t blkno; xfs_disk_dquot_t *ddq; f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr; printf(" "); ASSERT(f->blf_type == XFS_LI_BUF); printf(_("BUF: #regs:%d start blkno:0x%llx len:%d bmap size:%d flags:0x%x\n"), f->blf_size, (long long)f->blf_blkno, f->blf_len, f->blf_map_size, f->blf_flags); blkno = (xfs_daddr_t)f->blf_blkno; num = f->blf_size-1; i = 1; while (num-- > 0) { p = item->ri_buf[i].i_addr; len = item->ri_buf[i].i_len; i++; if (blkno == 0) { /* super block */ printf(_(" SUPER Block Buffer:\n")); if (!print_buffer) continue; printf(_(" icount:%llu ifree:%llu "), (unsigned long long) be64_to_cpu(*(__be64 *)(p)), (unsigned long long) be64_to_cpu(*(__be64 *)(p+8))); printf(_("fdblks:%llu frext:%llu\n"), (unsigned long long) be64_to_cpu(*(__be64 *)(p+16)), (unsigned long long) be64_to_cpu(*(__be64 *)(p+24))); printf(_(" sunit:%u swidth:%u\n"), be32_to_cpu(*(__be32 *)(p+56)), be32_to_cpu(*(__be32 *)(p+60))); } else if (be32_to_cpu(*(__be32 *)p) == XFS_AGI_MAGIC) { int bucket, buckets; agi = (xfs_agi_t *)p; printf(_(" AGI Buffer: (XAGI)\n")); if (!print_buffer) continue; printf(_(" ver:%d "), be32_to_cpu(agi->agi_versionnum)); printf(_("seq#:%d len:%d cnt:%d root:%d\n"), be32_to_cpu(agi->agi_seqno), be32_to_cpu(agi->agi_length), be32_to_cpu(agi->agi_count), be32_to_cpu(agi->agi_root)); printf(_(" level:%d free#:0x%x newino:0x%x\n"), be32_to_cpu(agi->agi_level), be32_to_cpu(agi->agi_freecount), be32_to_cpu(agi->agi_newino)); if (len == 128) { buckets = 17; } else if (len == 256) { buckets = 32 + 17; } else { buckets = XFS_AGI_UNLINKED_BUCKETS; } for (bucket = 0; bucket < buckets;) { int col; printf(_("bucket[%d - %d]: "), bucket, bucket+3); for (col = 0; col < 4; col++, bucket++) { if (bucket < buckets) { printf("0x%x ", be32_to_cpu(agi->agi_unlinked[bucket])); } } printf("\n"); } } else if (be32_to_cpu(*(__be32 *)p) == XFS_AGF_MAGIC) { agf = (xfs_agf_t *)p; printf(_(" AGF Buffer: (XAGF)\n")); if (!print_buffer) continue; printf(_(" ver:%d seq#:%d len:%d \n"), be32_to_cpu(agf->agf_versionnum), be32_to_cpu(agf->agf_seqno), be32_to_cpu(agf->agf_length)); printf(_(" root BNO:%d CNT:%d\n"), be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]), be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi])); printf(_(" level BNO:%d CNT:%d\n"), be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]), be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); printf(_(" 1st:%d last:%d cnt:%d " "freeblks:%d longest:%d\n"), be32_to_cpu(agf->agf_flfirst), be32_to_cpu(agf->agf_fllast), be32_to_cpu(agf->agf_flcount), be32_to_cpu(agf->agf_freeblks), be32_to_cpu(agf->agf_longest)); } else if (*(uint *)p == XFS_DQUOT_MAGIC) { ddq = (xfs_disk_dquot_t *)p; printf(_(" DQUOT Buffer:\n")); if (!print_buffer) continue; printf(_(" UIDs 0x%lx-0x%lx\n"), (unsigned long)be32_to_cpu(ddq->d_id), (unsigned long)be32_to_cpu(ddq->d_id) + (BBTOB(f->blf_len) / sizeof(xfs_dqblk_t)) - 1); } else { printf(_(" BUF DATA\n")); if (!print_buffer) continue; xlog_recover_print_data(p, len); } } } STATIC void xlog_recover_print_quotaoff( xlog_recover_item_t *item) { xfs_qoff_logformat_t *qoff_f; char str[32] = { 0 }; qoff_f = (xfs_qoff_logformat_t *)item->ri_buf[0].i_addr; ASSERT(qoff_f); if (qoff_f->qf_flags & XFS_UQUOTA_ACCT) strcat(str, "USER QUOTA"); if (qoff_f->qf_flags & XFS_GQUOTA_ACCT) strcat(str, "GROUP QUOTA"); if (qoff_f->qf_flags & XFS_PQUOTA_ACCT) strcat(str, "PROJECT QUOTA"); printf(_("\tQUOTAOFF: #regs:%d type:%s\n"), qoff_f->qf_size, str); } STATIC void xlog_recover_print_dquot( xlog_recover_item_t *item) { xfs_dq_logformat_t *f; xfs_disk_dquot_t *d; f = (xfs_dq_logformat_t *)item->ri_buf[0].i_addr; ASSERT(f); ASSERT(f->qlf_len == 1); d = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr; printf(_("\tDQUOT: #regs:%d blkno:%lld boffset:%u id: %d\n"), f->qlf_size, (long long)f->qlf_blkno, f->qlf_boffset, f->qlf_id); if (!print_quota) return; printf(_("\t\tmagic 0x%x\tversion 0x%x\tID 0x%x (%d)\t\n"), be16_to_cpu(d->d_magic), d->d_version, be32_to_cpu(d->d_id), be32_to_cpu(d->d_id)); printf(_("\t\tblk_hard 0x%x\tblk_soft 0x%x\tino_hard 0x%x" "\tino_soft 0x%x\n"), (int)be64_to_cpu(d->d_blk_hardlimit), (int)be64_to_cpu(d->d_blk_softlimit), (int)be64_to_cpu(d->d_ino_hardlimit), (int)be64_to_cpu(d->d_ino_softlimit)); printf(_("\t\tbcount 0x%x (%d) icount 0x%x (%d)\n"), (int)be64_to_cpu(d->d_bcount), (int)be64_to_cpu(d->d_bcount), (int)be64_to_cpu(d->d_icount), (int)be64_to_cpu(d->d_icount)); printf(_("\t\tbtimer 0x%x itimer 0x%x \n"), (int)be32_to_cpu(d->d_btimer), (int)be32_to_cpu(d->d_itimer)); } STATIC void xlog_recover_print_inode_core( struct xfs_log_dinode *di) { printf(_(" CORE inode:\n")); if (!print_inode) return; printf(_(" magic:%c%c mode:0x%x ver:%d format:%d\n"), (di->di_magic>>8) & 0xff, di->di_magic & 0xff, di->di_mode, di->di_version, di->di_format); printf(_(" uid:%d gid:%d nlink:%d projid:0x%04x%04x\n"), di->di_uid, di->di_gid, di->di_nlink, di->di_projid_hi, di->di_projid_lo); printf(_(" atime:%d mtime:%d ctime:%d\n"), di->di_atime.t_sec, di->di_mtime.t_sec, di->di_ctime.t_sec); printf(_(" flushiter:%d\n"), di->di_flushiter); printf(_(" size:0x%llx nblks:0x%llx exsize:%d " "nextents:%d anextents:%d\n"), (unsigned long long) di->di_size, (unsigned long long)di->di_nblocks, di->di_extsize, di->di_nextents, (int)di->di_anextents); printf(_(" forkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x " "gen:%d\n"), (int)di->di_forkoff, di->di_dmevmask, (int)di->di_dmstate, (int)di->di_flags, di->di_gen); if (di->di_version == 3) { printf(_("flags2 0x%llx cowextsize 0x%x\n"), (unsigned long long)di->di_flags2, di->di_cowextsize); } } STATIC void xlog_recover_print_inode( xlog_recover_item_t *item) { xfs_inode_log_format_t f_buf; xfs_inode_log_format_t *f; int attr_index; int hasdata; int hasattr; ASSERT(item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_32_t) || item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_64_t)); f = xfs_inode_item_format_convert(item->ri_buf[0].i_addr, item->ri_buf[0].i_len, &f_buf); printf(_(" INODE: #regs:%d ino:0x%llx flags:0x%x dsize:%d\n"), f->ilf_size, (unsigned long long)f->ilf_ino, f->ilf_fields, f->ilf_dsize); /* core inode comes 2nd */ ASSERT(item->ri_buf[1].i_len == xfs_log_dinode_size(2) || item->ri_buf[1].i_len == xfs_log_dinode_size(3)); xlog_recover_print_inode_core((struct xfs_log_dinode *) item->ri_buf[1].i_addr); hasdata = (f->ilf_fields & XFS_ILOG_DFORK) != 0; hasattr = (f->ilf_fields & XFS_ILOG_AFORK) != 0; /* does anything come next */ switch (f->ilf_fields & (XFS_ILOG_DFORK|XFS_ILOG_DEV|XFS_ILOG_UUID)) { case XFS_ILOG_DEXT: ASSERT(f->ilf_size == 3 + hasattr); printf(_(" DATA FORK EXTENTS inode data:\n")); if (print_inode && print_data) xlog_recover_print_data(item->ri_buf[2].i_addr, item->ri_buf[2].i_len); break; case XFS_ILOG_DBROOT: ASSERT(f->ilf_size == 3 + hasattr); printf(_(" DATA FORK BTREE inode data:\n")); if (print_inode && print_data) xlog_recover_print_data(item->ri_buf[2].i_addr, item->ri_buf[2].i_len); break; case XFS_ILOG_DDATA: ASSERT(f->ilf_size == 3 + hasattr); printf(_(" DATA FORK LOCAL inode data:\n")); if (print_inode && print_data) xlog_recover_print_data(item->ri_buf[2].i_addr, item->ri_buf[2].i_len); break; case XFS_ILOG_DEV: ASSERT(f->ilf_size == 2 + hasattr); printf(_(" DEV inode: no extra region\n")); break; case XFS_ILOG_UUID: ASSERT(f->ilf_size == 2 + hasattr); printf(_(" UUID inode: no extra region\n")); break; case 0: ASSERT(f->ilf_size == 2 + hasattr); break; default: xlog_panic("xlog_print_trans_inode: illegal inode type"); } if (hasattr) { attr_index = 2 + hasdata; switch (f->ilf_fields & XFS_ILOG_AFORK) { case XFS_ILOG_AEXT: ASSERT(f->ilf_size == 3 + hasdata); printf(_(" ATTR FORK EXTENTS inode data:\n")); if (print_inode && print_data) xlog_recover_print_data( item->ri_buf[attr_index].i_addr, item->ri_buf[attr_index].i_len); break; case XFS_ILOG_ABROOT: ASSERT(f->ilf_size == 3 + hasdata); printf(_(" ATTR FORK BTREE inode data:\n")); if (print_inode && print_data) xlog_recover_print_data( item->ri_buf[attr_index].i_addr, item->ri_buf[attr_index].i_len); break; case XFS_ILOG_ADATA: ASSERT(f->ilf_size == 3 + hasdata); printf(_(" ATTR FORK LOCAL inode data:\n")); if (print_inode && print_data) xlog_recover_print_data( item->ri_buf[attr_index].i_addr, item->ri_buf[attr_index].i_len); break; default: xlog_panic("%s: illegal inode log flag", __FUNCTION__); } } } STATIC void xlog_recover_print_icreate( struct xlog_recover_item *item) { struct xfs_icreate_log *icl; icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; printf(_(" ICR: #ag: %d agbno: 0x%x len: %d\n" " cnt: %d isize: %d gen: 0x%x\n"), be32_to_cpu(icl->icl_ag), be32_to_cpu(icl->icl_agbno), be32_to_cpu(icl->icl_length), be32_to_cpu(icl->icl_count), be32_to_cpu(icl->icl_isize), be32_to_cpu(icl->icl_gen)); } void xlog_recover_print_logitem( xlog_recover_item_t *item) { switch (ITEM_TYPE(item)) { case XFS_LI_BUF: xlog_recover_print_buffer(item); break; case XFS_LI_ICREATE: xlog_recover_print_icreate(item); break; case XFS_LI_INODE: xlog_recover_print_inode(item); break; case XFS_LI_EFD: xlog_recover_print_efd(item); break; case XFS_LI_EFI: xlog_recover_print_efi(item); break; case XFS_LI_RUD: xlog_recover_print_rud(item); break; case XFS_LI_RUI: xlog_recover_print_rui(item); break; case XFS_LI_CUD: xlog_recover_print_cud(item); break; case XFS_LI_CUI: xlog_recover_print_cui(item); break; case XFS_LI_BUD: xlog_recover_print_bud(item); break; case XFS_LI_BUI: xlog_recover_print_bui(item); break; case XFS_LI_DQUOT: xlog_recover_print_dquot(item); break; case XFS_LI_QUOTAOFF: xlog_recover_print_quotaoff(item); break; default: printf(_("xlog_recover_print_logitem: illegal type\n")); break; } } void xlog_recover_print_item( xlog_recover_item_t *item) { int i; switch (ITEM_TYPE(item)) { case XFS_LI_BUF: printf("BUF"); break; case XFS_LI_ICREATE: printf("ICR"); break; case XFS_LI_INODE: printf("INO"); break; case XFS_LI_EFD: printf("EFD"); break; case XFS_LI_EFI: printf("EFI"); break; case XFS_LI_RUD: printf("RUD"); break; case XFS_LI_RUI: printf("RUI"); break; case XFS_LI_CUD: printf("CUD"); break; case XFS_LI_CUI: printf("CUI"); break; case XFS_LI_BUD: printf("BUD"); break; case XFS_LI_BUI: printf("BUI"); break; case XFS_LI_DQUOT: printf("DQ "); break; case XFS_LI_QUOTAOFF: printf("QOFF"); break; default: cmn_err(CE_PANIC, _("%s: illegal type"), __FUNCTION__); break; } /* type isn't filled in yet printf(_("ITEM: type: %d cnt: %d total: %d "), item->ri_type, item->ri_cnt, item->ri_total); */ printf(_(": cnt:%d total:%d "), item->ri_cnt, item->ri_total); for (i=0; iri_cnt; i++) { printf(_("a:0x%lx len:%d "), (long)item->ri_buf[i].i_addr, item->ri_buf[i].i_len); } printf("\n"); xlog_recover_print_logitem(item); } void xlog_recover_print_trans( xlog_recover_t *trans, struct list_head *itemq, int print) { xlog_recover_item_t *item; if (print < 3) return; print_xlog_record_line(); xlog_recover_print_trans_head(trans); list_for_each_entry(item, itemq, ri_list) xlog_recover_print_item(item); } xfsprogs-4.9.0+nmu1ubuntu2/logprint/log_print_trans.c0000644000000000000000000000530613063067173017706 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "logprint.h" void xlog_recover_print_trans_head( xlog_recover_t *tr) { printf(_("TRANS: tid:0x%x #items:%d trans:0x%x q:0x%lx\n"), tr->r_log_tid, tr->r_theader.th_num_items, tr->r_theader.th_tid, (long)&tr->r_itemq); } int xlog_recover_do_trans( struct xlog *log, xlog_recover_t *trans, int pass) { xlog_recover_print_trans(trans, &trans->r_itemq, 3); return 0; } void xfs_log_print_trans( struct xlog *log, int print_block_start) { xfs_daddr_t head_blk, tail_blk; int error; error = xlog_find_tail(log, &head_blk, &tail_blk); if (error) { fprintf(stderr, _("%s: failed to find head and tail, error: %d\n"), progname, error); exit(1); } printf(_(" log tail: %lld head: %lld state: %s\n"), (long long)tail_blk, (long long)head_blk, (tail_blk == head_blk)?"":""); if (print_block_start != -1) { printf(_(" override tail: %d\n"), print_block_start); tail_blk = print_block_start; } printf("\n"); print_record_header = 1; if (head_blk == tail_blk) return; /* * Version 5 superblock log feature mask validation. We know the * log is dirty so check if there are any unknown log features * in what we need to recover. If there are unknown features * (e.g. unsupported transactions) then warn about it. */ if (XFS_SB_VERSION_NUM(&log->l_mp->m_sb) == XFS_SB_VERSION_5 && xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb, XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) { printf(_( "Superblock has unknown incompatible log features (0x%x) enabled.\n" "Output may be incomplete or inaccurate. It is recommended that you\n" "upgrade your xfsprogs installation to match the filesystem features.\n"), (log->l_mp->m_sb.sb_features_log_incompat & XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)); } if ((error = xlog_do_recovery_pass(log, head_blk, tail_blk, XLOG_RECOVER_PASS1))) { fprintf(stderr, _("%s: failed in xfs_do_recovery_pass, error: %d\n"), progname, error); exit(1); } } xfsprogs-4.9.0+nmu1ubuntu2/logprint/log_redo.c0000644000000000000000000003650613033541503016271 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * Copyright (c) 2016 Oracle, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "logprint.h" /* Extent Free Items */ static int xfs_efi_copy_format( char *buf, uint len, struct xfs_efi_log_format *dst_efi_fmt, int continued) { uint i; uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents; uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t); uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t); uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t); if (len == dst_len || continued) { memcpy((char *)dst_efi_fmt, buf, len); return 0; } else if (len == len32) { xfs_efi_log_format_32_t *src_efi_fmt_32 = (xfs_efi_log_format_32_t *)buf; dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { dst_efi_fmt->efi_extents[i].ext_start = src_efi_fmt_32->efi_extents[i].ext_start; dst_efi_fmt->efi_extents[i].ext_len = src_efi_fmt_32->efi_extents[i].ext_len; } return 0; } else if (len == len64) { xfs_efi_log_format_64_t *src_efi_fmt_64 = (xfs_efi_log_format_64_t *)buf; dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { dst_efi_fmt->efi_extents[i].ext_start = src_efi_fmt_64->efi_extents[i].ext_start; dst_efi_fmt->efi_extents[i].ext_len = src_efi_fmt_64->efi_extents[i].ext_len; } return 0; } fprintf(stderr, _("%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n"), progname, len, len32, len64, nextents); return 1; } int xlog_print_trans_efi( char **ptr, uint src_len, int continued) { xfs_efi_log_format_t *src_f, *f = NULL; uint dst_len; xfs_extent_t *ex; int i; int error = 0; int core_size = offsetof(xfs_efi_log_format_t, efi_extents); /* * memmove to ensure 8-byte alignment for the long longs in * xfs_efi_log_format_t structure */ if ((src_f = (xfs_efi_log_format_t *)malloc(src_len)) == NULL) { fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); exit(1); } memmove((char*)src_f, *ptr, src_len); *ptr += src_len; /* convert to native format */ dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); if (continued && src_len < core_size) { printf(_("EFI: Not enough data to decode further\n")); error = 1; goto error; } if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); exit(1); } if (xfs_efi_copy_format((char*)src_f, src_len, f, continued)) { error = 1; goto error; } printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"), f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); if (continued) { printf(_("EFI free extent data skipped (CONTINUE set, no space)\n")); goto error; } ex = f->efi_extents; for (i=0; i < f->efi_nextents; i++) { printf("(s: 0x%llx, l: %d) ", (unsigned long long)ex->ext_start, ex->ext_len); if (i % 4 == 3) printf("\n"); ex++; } if (i % 4 != 0) printf("\n"); error: free(src_f); free(f); return error; } /* xlog_print_trans_efi */ void xlog_recover_print_efi( xlog_recover_item_t *item) { xfs_efi_log_format_t *f, *src_f; xfs_extent_t *ex; int i; uint src_len, dst_len; src_f = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; src_len = item->ri_buf[0].i_len; /* * An xfs_efi_log_format structure contains a variable length array * as the last field. * Each element is of size xfs_extent_32_t or xfs_extent_64_t. * Need to convert to native format. */ dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"), progname); exit(1); } if (xfs_efi_copy_format((char*)src_f, src_len, f, 0)) { free(f); return; } printf(_(" EFI: #regs:%d num_extents:%d id:0x%llx\n"), f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); ex = f->efi_extents; printf(" "); for (i=0; i< f->efi_nextents; i++) { printf("(s: 0x%llx, l: %d) ", (unsigned long long)ex->ext_start, ex->ext_len); if (i % 4 == 3) printf("\n"); ex++; } if (i % 4 != 0) printf("\n"); free(f); } int xlog_print_trans_efd(char **ptr, uint len) { xfs_efd_log_format_t *f; xfs_efd_log_format_t lbuf; /* size without extents at end */ uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t); /* * memmove to ensure 8-byte alignment for the long longs in * xfs_efd_log_format_t structure */ memmove(&lbuf, *ptr, MIN(core_size, len)); f = &lbuf; *ptr += len; if (len >= core_size) { printf(_("EFD: #regs: %d num_extents: %d id: 0x%llx\n"), f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); /* don't print extents as they are not used */ return 0; } else { printf(_("EFD: Not enough data to decode further\n")); return 1; } } /* xlog_print_trans_efd */ void xlog_recover_print_efd( xlog_recover_item_t *item) { xfs_efd_log_format_t *f; f = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; /* * An xfs_efd_log_format structure contains a variable length array * as the last field. * Each element is of size xfs_extent_32_t or xfs_extent_64_t. * However, the extents are never used and won't be printed. */ printf(_(" EFD: #regs: %d num_extents: %d id: 0x%llx\n"), f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); } /* Reverse Mapping Update Items */ static int xfs_rui_copy_format( char *buf, uint len, struct xfs_rui_log_format *dst_fmt, int continued) { uint nextents = ((struct xfs_rui_log_format *)buf)->rui_nextents; uint dst_len = xfs_rui_log_format_sizeof(nextents); if (len == dst_len || continued) { memcpy((char *)dst_fmt, buf, len); return 0; } fprintf(stderr, _("%s: bad size of RUI format: %u; expected %u; nextents = %u\n"), progname, len, dst_len, nextents); return 1; } int xlog_print_trans_rui( char **ptr, uint src_len, int continued) { struct xfs_rui_log_format *src_f, *f = NULL; uint dst_len; uint nextents; struct xfs_map_extent *ex; int i; int error = 0; int core_size; core_size = offsetof(struct xfs_rui_log_format, rui_extents); /* * memmove to ensure 8-byte alignment for the long longs in * struct xfs_rui_log_format structure */ src_f = malloc(src_len); if (src_f == NULL) { fprintf(stderr, _("%s: %s: malloc failed\n"), progname, __func__); exit(1); } memmove((char*)src_f, *ptr, src_len); *ptr += src_len; /* convert to native format */ nextents = src_f->rui_nextents; dst_len = xfs_rui_log_format_sizeof(nextents); if (continued && src_len < core_size) { printf(_("RUI: Not enough data to decode further\n")); error = 1; goto error; } f = malloc(dst_len); if (f == NULL) { fprintf(stderr, _("%s: %s: malloc failed\n"), progname, __func__); exit(1); } if (xfs_rui_copy_format((char *)src_f, src_len, f, continued)) { error = 1; goto error; } printf(_("RUI: #regs: %d num_extents: %d id: 0x%llx\n"), f->rui_size, f->rui_nextents, (unsigned long long)f->rui_id); if (continued) { printf(_("RUI extent data skipped (CONTINUE set, no space)\n")); goto error; } ex = f->rui_extents; for (i=0; i < f->rui_nextents; i++) { printf("(s: 0x%llx, l: %d, own: %lld, off: %llu, f: 0x%x) ", (unsigned long long)ex->me_startblock, ex->me_len, (long long)ex->me_owner, (unsigned long long)ex->me_startoff, ex->me_flags); printf("\n"); ex++; } error: free(src_f); free(f); return error; } void xlog_recover_print_rui( struct xlog_recover_item *item) { char *src_f; uint src_len; src_f = item->ri_buf[0].i_addr; src_len = item->ri_buf[0].i_len; xlog_print_trans_rui(&src_f, src_len, 0); } int xlog_print_trans_rud( char **ptr, uint len) { struct xfs_rud_log_format *f; struct xfs_rud_log_format lbuf; /* size without extents at end */ uint core_size = sizeof(struct xfs_rud_log_format); /* * memmove to ensure 8-byte alignment for the long longs in * xfs_efd_log_format_t structure */ memmove(&lbuf, *ptr, MIN(core_size, len)); f = &lbuf; *ptr += len; if (len >= core_size) { printf(_("RUD: #regs: %d id: 0x%llx\n"), f->rud_size, (unsigned long long)f->rud_rui_id); /* don't print extents as they are not used */ return 0; } else { printf(_("RUD: Not enough data to decode further\n")); return 1; } } void xlog_recover_print_rud( struct xlog_recover_item *item) { char *f; f = item->ri_buf[0].i_addr; xlog_print_trans_rud(&f, sizeof(struct xfs_rud_log_format)); } /* Reference Count Update Items */ static int xfs_cui_copy_format( struct xfs_cui_log_format *cui, uint len, struct xfs_cui_log_format *dst_fmt, int continued) { uint nextents; uint dst_len; nextents = cui->cui_nextents; dst_len = xfs_cui_log_format_sizeof(nextents); if (len == dst_len || continued) { memcpy(dst_fmt, cui, len); return 0; } fprintf(stderr, _("%s: bad size of CUI format: %u; expected %u; nextents = %u\n"), progname, len, dst_len, nextents); return 1; } int xlog_print_trans_cui( char **ptr, uint src_len, int continued) { struct xfs_cui_log_format *src_f, *f = NULL; uint dst_len; uint nextents; struct xfs_phys_extent *ex; int i; int error = 0; int core_size; core_size = offsetof(struct xfs_cui_log_format, cui_extents); src_f = malloc(src_len); if (src_f == NULL) { fprintf(stderr, _("%s: %s: malloc failed\n"), progname, __func__); exit(1); } memcpy(src_f, *ptr, src_len); *ptr += src_len; /* convert to native format */ nextents = src_f->cui_nextents; dst_len = xfs_cui_log_format_sizeof(nextents); if (continued && src_len < core_size) { printf(_("CUI: Not enough data to decode further\n")); error = 1; goto error; } f = malloc(dst_len); if (f == NULL) { fprintf(stderr, _("%s: %s: malloc failed\n"), progname, __func__); exit(1); } if (xfs_cui_copy_format(src_f, src_len, f, continued)) { error = 1; goto error; } printf(_("CUI: #regs: %d num_extents: %d id: 0x%llx\n"), f->cui_size, f->cui_nextents, (unsigned long long)f->cui_id); if (continued) { printf(_("CUI extent data skipped (CONTINUE set, no space)\n")); goto error; } ex = f->cui_extents; for (i=0; i < f->cui_nextents; i++) { printf("(s: 0x%llx, l: %d, f: 0x%x) ", (unsigned long long)ex->pe_startblock, ex->pe_len, ex->pe_flags); printf("\n"); ex++; } error: free(src_f); free(f); return error; } void xlog_recover_print_cui( struct xlog_recover_item *item) { char *src_f; uint src_len; src_f = item->ri_buf[0].i_addr; src_len = item->ri_buf[0].i_len; xlog_print_trans_cui(&src_f, src_len, 0); } int xlog_print_trans_cud( char **ptr, uint len) { struct xfs_cud_log_format *f; struct xfs_cud_log_format lbuf; /* size without extents at end */ uint core_size = sizeof(struct xfs_cud_log_format); memcpy(&lbuf, *ptr, MIN(core_size, len)); f = &lbuf; *ptr += len; if (len >= core_size) { printf(_("CUD: #regs: %d id: 0x%llx\n"), f->cud_size, (unsigned long long)f->cud_cui_id); /* don't print extents as they are not used */ return 0; } else { printf(_("CUD: Not enough data to decode further\n")); return 1; } } void xlog_recover_print_cud( struct xlog_recover_item *item) { char *f; f = item->ri_buf[0].i_addr; xlog_print_trans_cud(&f, sizeof(struct xfs_cud_log_format)); } /* Block Mapping Update Items */ static int xfs_bui_copy_format( struct xfs_bui_log_format *bui, uint len, struct xfs_bui_log_format *dst_fmt, int continued) { uint nextents; uint dst_len; nextents = bui->bui_nextents; dst_len = xfs_bui_log_format_sizeof(nextents); if (len == dst_len || continued) { memcpy(dst_fmt, bui, len); return 0; } fprintf(stderr, _("%s: bad size of BUI format: %u; expected %u; nextents = %u\n"), progname, len, dst_len, nextents); return 1; } int xlog_print_trans_bui( char **ptr, uint src_len, int continued) { struct xfs_bui_log_format *src_f, *f = NULL; uint dst_len; uint nextents; struct xfs_map_extent *ex; int i; int error = 0; int core_size; core_size = offsetof(struct xfs_bui_log_format, bui_extents); src_f = malloc(src_len); if (src_f == NULL) { fprintf(stderr, _("%s: %s: malloc failed\n"), progname, __func__); exit(1); } memcpy(src_f, *ptr, src_len); *ptr += src_len; /* convert to native format */ nextents = src_f->bui_nextents; dst_len = xfs_bui_log_format_sizeof(nextents); if (continued && src_len < core_size) { printf(_("BUI: Not enough data to decode further\n")); error = 1; goto error; } f = malloc(dst_len); if (f == NULL) { fprintf(stderr, _("%s: %s: malloc failed\n"), progname, __func__); exit(1); } if (xfs_bui_copy_format(src_f, src_len, f, continued)) { error = 1; goto error; } printf(_("BUI: #regs: %d num_extents: %d id: 0x%llx\n"), f->bui_size, f->bui_nextents, (unsigned long long)f->bui_id); if (continued) { printf(_("BUI extent data skipped (CONTINUE set, no space)\n")); goto error; } ex = f->bui_extents; for (i=0; i < f->bui_nextents; i++) { printf("(s: 0x%llx, l: %d, own: %lld, off: %llu, f: 0x%x) ", (unsigned long long)ex->me_startblock, ex->me_len, (long long)ex->me_owner, (unsigned long long)ex->me_startoff, ex->me_flags); printf("\n"); ex++; } error: free(src_f); free(f); return error; } void xlog_recover_print_bui( struct xlog_recover_item *item) { char *src_f; uint src_len; src_f = item->ri_buf[0].i_addr; src_len = item->ri_buf[0].i_len; xlog_print_trans_bui(&src_f, src_len, 0); } int xlog_print_trans_bud( char **ptr, uint len) { struct xfs_bud_log_format *f; struct xfs_bud_log_format lbuf; /* size without extents at end */ uint core_size = sizeof(struct xfs_bud_log_format); memcpy(&lbuf, *ptr, MIN(core_size, len)); f = &lbuf; *ptr += len; if (len >= core_size) { printf(_("BUD: #regs: %d id: 0x%llx\n"), f->bud_size, (unsigned long long)f->bud_bui_id); /* don't print extents as they are not used */ return 0; } else { printf(_("BUD: Not enough data to decode further\n")); return 1; } } void xlog_recover_print_bud( struct xlog_recover_item *item) { char *f; f = item->ri_buf[0].i_addr; xlog_print_trans_bud(&f, sizeof(struct xfs_bud_log_format)); } xfsprogs-4.9.0+nmu1ubuntu2/logprint/logprint.c0000644000000000000000000001417713063067173016346 0ustar /* * Copyright (c) 2000-2004 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "libxfs.h" #include "libxlog.h" #include "logprint.h" #define OP_PRINT 0 #define OP_PRINT_TRANS 1 #define OP_DUMP 2 #define OP_COPY 3 int print_data; int print_only_data; int print_inode; int print_quota; int print_buffer; int print_overwrite; int print_no_data; int print_no_print; int print_exit = 1; /* -e is now default. specify -c to override */ int print_operation = OP_PRINT; void usage(void) { fprintf(stderr, _("Usage: %s [options...] \n\n\ Options:\n\ -c try to continue if error found in log\n\ -C copy the log from the filesystem to filename\n\ -d dump the log in log-record format\n\ -e exit when an error is found in the log\n\ -f specified device is actually a file\n\ -l filename of external log\n\ -n don't try and interpret log data\n\ -o print buffer data in hex\n\ -s block # to start printing\n\ -v print \"overwrite\" data\n\ -t print out transactional view\n\ -b in transactional view, extract buffer info\n\ -i in transactional view, extract inode info\n\ -q in transactional view, extract quota info\n\ -D print only data; no decoding\n\ -V print version information\n"), progname); exit(1); } int logstat(xfs_mount_t *mp) { int fd; char buf[BBSIZE]; xfs_sb_t *sb; /* On Linux we always read the superblock of the * filesystem. We need this to get the length of the * log. Otherwise we end up seeking forever. -- mkp */ if ((fd = open(x.dname, O_RDONLY)) == -1) { fprintf(stderr, _(" Can't open device %s: %s\n"), x.dname, strerror(errno)); exit(1); } lseek(fd, 0, SEEK_SET); if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { fprintf(stderr, _(" read of XFS superblock failed\n")); exit(1); } close (fd); if (!x.disfile) { /* * Conjure up a mount structure */ sb = &mp->m_sb; libxfs_sb_from_disk(sb, (xfs_dsb_t *)buf); mp->m_blkbb_log = sb->sb_blocklog - BBSHIFT; x.logBBsize = XFS_FSB_TO_BB(mp, sb->sb_logblocks); x.logBBstart = XFS_FSB_TO_DADDR(mp, sb->sb_logstart); x.lbsize = BBSIZE; if (xfs_sb_version_hassector(sb)) x.lbsize <<= (sb->sb_logsectlog - BBSHIFT); if (!x.logname && sb->sb_logstart == 0) { fprintf(stderr, _(" external log device not specified\n\n")); usage(); /*NOTREACHED*/ } } else { struct stat s; stat(x.dname, &s); x.logBBsize = s.st_size >> 9; x.logBBstart = 0; x.lbsize = BBSIZE; } if (x.logname && *x.logname) { /* External log */ if ((fd = open(x.logname, O_RDONLY)) == -1) { fprintf(stderr, _("Can't open file %s: %s\n"), x.logname, strerror(errno)); exit(1); } close(fd); } else { /* Internal log */ x.logdev = x.ddev; } return 0; } int main(int argc, char **argv) { int print_start = -1; int c; int logfd; char *copy_file = NULL; struct xlog log = {0}; xfs_mount_t mount; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); memset(&mount, 0, sizeof(mount)); progname = basename(argv[0]); while ((c = getopt(argc, argv, "bC:cdefl:iqnors:tDVv")) != EOF) { switch (c) { case 'D': print_only_data++; print_data++; break; case 'b': print_buffer++; break; case 'c': /* default is to stop on error. * -c turns this off. */ print_exit = 0; break; case 'e': /* -e is now default */ print_exit++; break; case 'C': print_operation = OP_COPY; copy_file = optarg; break; case 'd': print_operation = OP_DUMP; break; case 'f': print_skip_uuid++; x.disfile = 1; break; case 'l': x.logname = optarg; x.lisfile = 1; break; case 'i': print_inode++; break; case 'q': print_quota++; break; case 'n': print_no_data++; break; case 'o': print_data++; break; case 's': print_start = atoi(optarg); break; case 't': print_operation = OP_PRINT_TRANS; break; case 'v': print_overwrite++; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); case '?': usage(); } } if (argc - optind != 1) usage(); x.dname = argv[optind]; if (x.dname == NULL) usage(); x.isreadonly = LIBXFS_ISINACTIVE; printf(_("xfs_logprint:\n")); if (!libxfs_init(&x)) exit(1); logstat(&mount); libxfs_buftarg_init(&mount, x.ddev, x.logdev, x.rtdev); logfd = (x.logfd < 0) ? x.dfd : x.logfd; printf(_(" data device: 0x%llx\n"), (unsigned long long)x.ddev); if (x.logname) { printf(_(" log file: \"%s\" "), x.logname); } else { printf(_(" log device: 0x%llx "), (unsigned long long)x.logdev); } printf(_("daddr: %lld length: %lld\n\n"), (long long)x.logBBstart, (long long)x.logBBsize); ASSERT(x.logBBsize <= INT_MAX); log.l_dev = mount.m_logdev_targp; log.l_logBBstart = x.logBBstart; log.l_logBBsize = x.logBBsize; log.l_sectBBsize = BTOBB(x.lbsize); log.l_mp = &mount; switch (print_operation) { case OP_PRINT: xfs_log_print(&log, logfd, print_start); break; case OP_PRINT_TRANS: xfs_log_print_trans(&log, print_start); break; case OP_DUMP: xfs_log_dump(&log, logfd, print_start); break; case OP_COPY: xfs_log_copy(&log, logfd, copy_file); break; } exit(0); } xfsprogs-4.9.0+nmu1ubuntu2/logprint/logprint.h0000644000000000000000000000507613063067173016351 0ustar /* * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LOGPRINT_H #define LOGPRINT_H /* command line flags */ extern int print_data; extern int print_only_data; extern int print_inode; extern int print_quota; extern int print_buffer; extern int print_transactions; extern int print_overwrite; extern int print_no_data; extern int print_no_print; /* exports */ extern void xlog_print_lseek(struct xlog *, int, xfs_daddr_t, int); extern void xfs_log_copy(struct xlog *, int, char *); extern void xfs_log_dump(struct xlog *, int, int); extern void xfs_log_print(struct xlog *, int, int); extern void xfs_log_print_trans(struct xlog *, int); extern void print_xlog_record_line(void); extern void print_xlog_op_line(void); extern void print_stars(void); extern xfs_inode_log_format_t * xfs_inode_item_format_convert(char *, uint, xfs_inode_log_format_t *); extern int xlog_print_trans_efi(char **ptr, uint src_len, int continued); extern void xlog_recover_print_efi(xlog_recover_item_t *item); extern int xlog_print_trans_efd(char **ptr, uint len); extern void xlog_recover_print_efd(xlog_recover_item_t *item); extern int xlog_print_trans_rui(char **ptr, uint src_len, int continued); extern void xlog_recover_print_rui(struct xlog_recover_item *item); extern int xlog_print_trans_rud(char **ptr, uint len); extern void xlog_recover_print_rud(struct xlog_recover_item *item); extern int xlog_print_trans_cui(char **ptr, uint src_len, int continued); extern void xlog_recover_print_cui(struct xlog_recover_item *item); extern int xlog_print_trans_cud(char **ptr, uint len); extern void xlog_recover_print_cud(struct xlog_recover_item *item); extern int xlog_print_trans_bui(char **ptr, uint src_len, int continued); extern void xlog_recover_print_bui(struct xlog_recover_item *item); extern int xlog_print_trans_bud(char **ptr, uint len); extern void xlog_recover_print_bud(struct xlog_recover_item *item); #endif /* LOGPRINT_H */ xfsprogs-4.9.0+nmu1ubuntu2/ltmain.sh0000644000000000000000000117147413063067167014336 0ustar #! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2014-01-03.01 # libtool (GNU libtool) 2.4.6 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.6 Debian-2.4.6-2" package_revision=2.4.6 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2015-01-20.17; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # Copyright (C) 2004-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # As a special exception to the GNU General Public License, if you distribute # this file as part of a program or library that is built using GNU Libtool, # you may include this file under the same distribution terms that you use # for the rest of that program. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1+=\\ \$func_quote_for_eval_result" }' else func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1=\$$1\\ \$func_quote_for_eval_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_for_eval ARG... # -------------------------- # Aesthetically quote ARGs to be evaled later. # This function returns two values: # i) func_quote_for_eval_result # double-quoted, suitable for a subsequent eval # ii) func_quote_for_eval_unquoted_result # has all characters that are still active within double # quotes backslashified. func_quote_for_eval () { $debug_cmd func_quote_for_eval_unquoted_result= func_quote_for_eval_result= while test 0 -lt $#; do case $1 in *[\\\`\"\$]*) _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; *) _G_unquoted_arg=$1 ;; esac if test -n "$func_quote_for_eval_unquoted_result"; then func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" else func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" fi case $_G_unquoted_arg in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_quoted_arg=\"$_G_unquoted_arg\" ;; *) _G_quoted_arg=$_G_unquoted_arg ;; esac if test -n "$func_quote_for_eval_result"; then func_append func_quote_for_eval_result " $_G_quoted_arg" else func_append func_quote_for_eval_result "$_G_quoted_arg" fi shift done } # func_quote_for_expand ARG # ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { $debug_cmd case $1 in *[\\\`\"]*) _G_arg=`$ECHO "$1" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) _G_arg=$1 ;; esac case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_arg=\"$_G_arg\" ;; esac func_quote_for_expand_result=$_G_arg } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_for_expand "$_G_cmd" eval "func_notquiet $func_quote_for_expand_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # Set a version string for this script. scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # Copyright (C) 2010-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# warranty; '. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # to the main code. A hook is just a named list of of function, that can # be run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of functions called by FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It is assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do eval $_G_hook '"$@"' # store returned options list back into positional # parameters for next 'cmd' execution. eval _G_hook_result=\$${_G_hook}_result eval set dummy "$_G_hook_result"; shift done func_quote_for_eval ${1+"$@"} func_run_hooks_result=$func_quote_for_eval_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, remove any # options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # func_quote_for_eval ${1+"$@"} # my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # ;; # *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # # func_quote_for_eval ${1+"$@"} # my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # # You'll alse need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd func_options_prep ${1+"$@"} eval func_parse_options \ ${func_options_prep_result+"$func_options_prep_result"} eval func_validate_options \ ${func_parse_options_result+"$func_parse_options_result"} eval func_run_hooks func_options \ ${func_validate_options_result+"$func_validate_options_result"} # save modified positional parameters for caller func_options_result=$func_run_hooks_result } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propogate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} # Adjust func_parse_options positional parameters to match eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) test $# = 0 && func_missing_arg $_G_opt && break case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables after # splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} test "x$func_split_equals_lhs" = "x$1" \ && func_split_equals_rhs= }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /(C)/!b go :more /\./!{ N s|\n# | | b more } :go /^# Written by /,/# warranty; / { s|^# || s|^# *$|| s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| p } /^# Written by / { s|^# || p } /^warranty; /q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.6' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname $scriptversion Debian-2.4.6-2 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func__fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote_for_eval ${1+"$@"} libtool_validate_options_result=$func_quote_for_eval_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: xfsprogs-4.9.0+nmu1ubuntu2/m4/0000755000000000000000000000000013063067174013015 5ustar xfsprogs-4.9.0+nmu1ubuntu2/m4/Makefile0000644000000000000000000000104213063067171014447 0ustar # # Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs CONFIGURE = \ libtool.m4 \ ltoptions.m4 \ ltsugar.m4 \ ltversion.m4 \ lt~obsolete.m4 LSRCFILES = \ manual_format.m4 \ package_blkid.m4 \ package_globals.m4 \ package_libcdev.m4 \ package_pthread.m4 \ package_types.m4 \ package_utilies.m4 \ package_uuiddev.m4 \ multilib.m4 \ $(CONFIGURE) default: include $(BUILDRULES) install install-dev install-lib: default realclean: distclean rm -f $(CONFIGURE) xfsprogs-4.9.0+nmu1ubuntu2/m4/libtool.m40000644000000000000000000112617113063067171014731 0ustar # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS xfsprogs-4.9.0+nmu1ubuntu2/m4/ltoptions.m40000644000000000000000000003426213063067171015316 0ustar # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) xfsprogs-4.9.0+nmu1ubuntu2/m4/ltsugar.m40000644000000000000000000001044013063067171014734 0ustar # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/ltversion.m40000644000000000000000000000127313063067171015304 0ustar # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/lt~obsolete.m40000644000000000000000000001377413063067171015642 0ustar # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) xfsprogs-4.9.0+nmu1ubuntu2/m4/manual_format.m40000644000000000000000000000075013063067171016103 0ustar # # Find format of installed man pages. # Always gzipped on Debian, but not Redhat pre-7.0. # We don't deal with bzip2'd man pages, which Mandrake uses, # someone will send us a patch sometime hopefully. :-) # AC_DEFUN([AC_MANUAL_FORMAT], [ have_zipped_manpages=false for d in ${prefix}/share/man ${prefix}/man ; do if test -f $d/man1/man.1.gz then have_zipped_manpages=true break fi done AC_SUBST(have_zipped_manpages) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/multilib.m40000644000000000000000000000345413063067171015103 0ustar # The AC_MULTILIB macro was extracted and modified from # gettext-0.15's AC_LIB_PREPARE_MULTILIB macro in the lib-prefix.m4 file # so that the correct paths can be used for 64-bit libraries. # dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_MULTILIB creates a variable libdirsuffix, containing dnl the suffix of the libdir, either "" or "64". dnl Only do this if the given enable parameter is "yes". AC_DEFUN([AC_MULTILIB], [ dnl There is no formal standard regarding lib and lib64. The current dnl practice is that on a system supporting 32-bit and 64-bit instruction dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit dnl libraries go under $prefix/lib. We determine the compiler's default dnl mode by looking at the compiler's library search path. If at least dnl of its elements ends in /lib64 or points to a directory whose absolute dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the dnl default, namely "lib". enable_lib64="$1" libdirsuffix="" searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test "$enable_lib64" = "yes" -a -n "$searchpath"; then save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) libdirsuffix=64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) libdirsuffix=64 ;; esac ;; esac fi done IFS="$save_IFS" fi AC_SUBST(libdirsuffix) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_aiodev.m40000644000000000000000000000000013063067171016164 0ustar xfsprogs-4.9.0+nmu1ubuntu2/m4/package_blkid.m40000644000000000000000000000064613063067171016022 0ustar # # See if blkid has the topology bits # AC_DEFUN([AC_HAVE_BLKID_TOPO], [ AC_SEARCH_LIBS([blkid_probe_all], [blkid]) AC_CHECK_FUNCS(blkid_probe_get_topology) if test $ac_cv_func_blkid_probe_get_topology = yes; then libblkid="-lblkid" else echo echo 'FATAL ERROR: could not find a valid BLKID header.' echo 'Install the Block device ID development package.' exit 1 fi AC_SUBST(libblkid) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_globals.m40000644000000000000000000000250013063067171016347 0ustar # # Generic macro, sets up all of the global packaging variables. # The following environment variables may be set to override defaults: # DEBUG OPTIMIZER MALLOCLIB PLATFORM DISTRIBUTION INSTALL_USER INSTALL_GROUP # BUILD_VERSION # AC_DEFUN([AC_PACKAGE_GLOBALS], [ pkg_name="$1" AC_SUBST(pkg_name) AC_PROG_CC . ./VERSION pkg_version=${PKG_MAJOR}.${PKG_MINOR}.${PKG_REVISION} AC_SUBST(pkg_version) pkg_release=$PKG_BUILD test -z "$BUILD_VERSION" || pkg_release="$BUILD_VERSION" AC_SUBST(pkg_release) DEBUG=${DEBUG:-'-DDEBUG'} dnl -DNDEBUG debug_build="$DEBUG" AC_SUBST(debug_build) OPTIMIZER=${OPTIMIZER:-'-g -O2'} opt_build="$OPTIMIZER" AC_SUBST(opt_build) MALLOCLIB=${MALLOCLIB:-''} dnl /usr/lib/libefence.a malloc_lib="$MALLOCLIB" AC_SUBST(malloc_lib) pkg_user=`id -u -n` test -z "$INSTALL_USER" || pkg_user="$INSTALL_USER" AC_SUBST(pkg_user) pkg_group=`id -g -n` test -z "$INSTALL_GROUP" || pkg_group="$INSTALL_GROUP" AC_SUBST(pkg_group) pkg_distribution=`uname -s` test -z "$DISTRIBUTION" || pkg_distribution="$DISTRIBUTION" AC_SUBST(pkg_distribution) pkg_platform=`uname -s | tr 'A-Z' 'a-z' | tr -d / | sed -e 's/irix64/irix/'` test -z "$PLATFORM" || pkg_platform="$PLATFORM" AC_SUBST(pkg_platform) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_libcdev.m40000644000000000000000000001327613063067171016350 0ustar # # Check if we have a working fadvise system call # AC_DEFUN([AC_HAVE_FADVISE], [ AC_MSG_CHECKING([for fadvise ]) AC_TRY_COMPILE([ #define _GNU_SOURCE #include ], [ posix_fadvise(0, 1, 0, POSIX_FADV_NORMAL); ], have_fadvise=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_fadvise) ]) # # Check if we have a working madvise system call # AC_DEFUN([AC_HAVE_MADVISE], [ AC_MSG_CHECKING([for madvise ]) AC_TRY_COMPILE([ #define _GNU_SOURCE #include ], [ posix_madvise(0, 0, MADV_NORMAL); ], have_madvise=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_madvise) ]) # # Check if we have a working mincore system call # AC_DEFUN([AC_HAVE_MINCORE], [ AC_MSG_CHECKING([for mincore ]) AC_TRY_COMPILE([ #define _GNU_SOURCE #include ], [ mincore(0, 0, 0); ], have_mincore=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_mincore) ]) # # Check if we have a working sendfile system call # AC_DEFUN([AC_HAVE_SENDFILE], [ AC_MSG_CHECKING([for sendfile ]) AC_TRY_COMPILE([ #define _GNU_SOURCE #include ], [ sendfile(0, 0, 0, 0); ], have_sendfile=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_sendfile) ]) # # Check if we have a getmntent libc call (IRIX, Linux) # AC_DEFUN([AC_HAVE_GETMNTENT], [ AC_MSG_CHECKING([for getmntent ]) AC_TRY_COMPILE([ #include #include ], [ getmntent(0); ], have_getmntent=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_getmntent) ]) # # Check if we have a getmntinfo libc call (FreeBSD, Mac OS X) # AC_DEFUN([AC_HAVE_GETMNTINFO], [ AC_MSG_CHECKING([for getmntinfo ]) AC_TRY_COMPILE([ #include #include #include ], [ getmntinfo(0, 0); ], have_getmntinfo=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_getmntinfo) ]) # # Check if we have a fallocate libc call (Linux) # AC_DEFUN([AC_HAVE_FALLOCATE], [ AC_MSG_CHECKING([for fallocate]) AC_TRY_LINK([ #define _GNU_SOURCE #include #include ], [ fallocate(0, 0, 0, 0); ], have_fallocate=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_fallocate) ]) # # Check if we have the fiemap ioctl (Linux) # AC_DEFUN([AC_HAVE_FIEMAP], [ AC_MSG_CHECKING([for fiemap]) AC_TRY_LINK([ #define _GNU_SOURCE #include #include ], [ struct fiemap *fiemap; ioctl(0, FS_IOC_FIEMAP, (unsigned long)fiemap); ], have_fiemap=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_fiemap) ]) # # Check if we have a preadv libc call (Linux) # AC_DEFUN([AC_HAVE_PREADV], [ AC_MSG_CHECKING([for preadv]) AC_TRY_LINK([ #define _BSD_SOURCE #include ], [ preadv(0, 0, 0, 0); ], have_preadv=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_preadv) ]) # # Check if we have a copy_file_range system call (Linux) # AC_DEFUN([AC_HAVE_COPY_FILE_RANGE], [ AC_MSG_CHECKING([for copy_file_range]) AC_TRY_LINK([ #define _GNU_SOURCE #include #include ], [ syscall(__NR_copy_file_range, 0, 0, 0, 0, 0, 0); ], have_copy_file_range=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_copy_file_range) ]) # # Check if we have a sync_file_range libc call (Linux) # AC_DEFUN([AC_HAVE_SYNC_FILE_RANGE], [ AC_MSG_CHECKING([for sync_file_range]) AC_TRY_LINK([ #define _GNU_SOURCE #include ], [ sync_file_range(0, 0, 0, 0); ], have_sync_file_range=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_sync_file_range) ]) # # Check if we have a syncfs libc call (Linux) # AC_DEFUN([AC_HAVE_SYNCFS], [ AC_MSG_CHECKING([for syncfs]) AC_TRY_LINK([ #define _GNU_SOURCE #include ], [ syncfs(0); ], have_sync_fs=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_syncfs) ]) # # Check if we have a readdir libc call # AC_DEFUN([AC_HAVE_READDIR], [ AC_MSG_CHECKING([for readdir]) AC_TRY_LINK([ #include ], [ readdir(0); ], have_readdir=yes AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_SUBST(have_readdir) ]) # # Check if we have a flc call (Mac OS X) # AC_DEFUN([AC_HAVE_FLS], [ AC_CHECK_DECL([fls], have_fls=yes, [], [#include ] ) AC_SUBST(have_fls) ]) # # Check if we have a fsetxattr call (Mac OS X) # AC_DEFUN([AC_HAVE_FSETXATTR], [ AC_CHECK_DECL([fsetxattr], have_fsetxattr=yes, [], [#include #include ] ) AC_SUBST(have_fsetxattr) ]) # # Check if there is mntent.h # AC_DEFUN([AC_HAVE_MNTENT], [ AC_CHECK_HEADERS(mntent.h, have_mntent=yes) AC_SUBST(have_mntent) ]) # # Check if we have a mremap call (not on Mac OS X) # AC_DEFUN([AC_HAVE_MREMAP], [ AC_CHECK_DECL([mremap], have_mremap=yes, [], [#define _GNU_SOURCE #include ] ) AC_SUBST(have_mremap) ]) # # Check if we need to override the system struct fsxattr with # the internal definition. This /only/ happens if the system # actually defines struct fsxattr /and/ the system definition # is missing certain fields. # AC_DEFUN([AC_NEED_INTERNAL_FSXATTR], [ AC_CHECK_TYPE(struct fsxattr, [ AC_CHECK_MEMBER(struct fsxattr.fsx_cowextsize, , need_internal_fsxattr=yes, [#include ] ) ],, [#include ] ) AC_SUBST(need_internal_fsxattr) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_pthread.m40000644000000000000000000000072513063067171016362 0ustar AC_DEFUN([AC_PACKAGE_NEED_PTHREAD_H], [ AC_CHECK_HEADERS(pthread.h) if test $ac_cv_header_pthread_h = no; then AC_CHECK_HEADERS(pthread.h,, [ echo echo 'FATAL ERROR: could not find a valid pthread header.' exit 1]) fi ]) AC_DEFUN([AC_PACKAGE_NEED_PTHREADMUTEXINIT], [ AC_CHECK_LIB(pthread, pthread_mutex_init,, [ echo echo 'FATAL ERROR: could not find a valid pthread library.' exit 1 ]) libpthread=-lpthread AC_SUBST(libpthread) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_rt.m40000644000000000000000000000024013033541503015341 0ustar # Check if the platform has librt # AC_DEFUN([AC_RT], [ if test "$enable_librt" = "yes"; then librt="-lrt" else librt="" fi AC_SUBST(librt) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_types.m40000644000000000000000000000036713063067171016101 0ustar # # Check if we have umode_t # AC_DEFUN([AC_TYPE_UMODE_T], [ AC_MSG_CHECKING([for umode_t]) AC_TRY_COMPILE([ #include ], [ umode_t umode; ], AC_DEFINE(HAVE_UMODE_T) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no)) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_utilies.m40000644000000000000000000000733713063067171016417 0ustar # Path to search an utility PATH=/bin:/usr/bin:/usr/local/bin:/usr/freeware/bin:/opt/local/bin # # Check for specified utility (env var) - if unset, fail. # AC_DEFUN([AC_PACKAGE_NEED_UTILITY], [ if test -z "$2"; then echo echo FATAL ERROR: $3 does not seem to be installed. echo $1 cannot be built without a working $4 installation. exit 1 fi ]) # #check compiler can generate dependencies # AC_DEFUN([AC_PACKAGE_GCC_DEPS], [AC_CACHE_CHECK(whether gcc -MM is supported, ac_cv_gcc_nodeps, [cat > conftest.c < int main() { exit(0); } EOF ac_cv_gcc_nodeps=no if ${CC} -MM conftest.c >/dev/null 2>&1; then ac_cv_gcc_nodeps=yes fi rm -f conftest.c a.out ]) ]) # # Generic macro, sets up all of the global build variables. # The following environment variables may be set to override defaults: # CC MAKE LIBTOOL TAR ZIP MAKEDEPEND AWK SED ECHO SORT # MSGFMT MSGMERGE XGETTEXT RPM # AC_DEFUN([AC_PACKAGE_UTILITIES], [ AC_PROG_CC cc="$CC" AC_SUBST(cc) AC_PACKAGE_NEED_UTILITY($1, "$cc", cc, [C compiler]) if test -z "$MAKE"; then AC_PATH_PROG(MAKE, gmake,, $PATH) fi if test -z "$MAKE"; then AC_PATH_PROG(MAKE, make,, $PATH) fi make=$MAKE AC_SUBST(make) AC_PACKAGE_NEED_UTILITY($1, "$make", make, [GNU make]) if test -z "$TAR"; then AC_PATH_PROG(TAR, tar,, $PATH) fi tar=$TAR AC_SUBST(tar) if test -z "$ZIP"; then AC_PATH_PROG(ZIP, gzip,, $PATH) fi zip=$ZIP AC_SUBST(zip) AC_PACKAGE_GCC_DEPS() makedepend="$cc -MM" if test $ac_cv_gcc_nodeps = no; then makedepend=/bin/true fi AC_SUBST(makedepend) if test -z "$AWK"; then AC_PATH_PROG(AWK, awk,, /bin:/usr/bin) fi awk=$AWK AC_SUBST(awk) if test -z "$SED"; then AC_PATH_PROG(SED, sed,, /bin:/usr/bin) fi sed=$SED AC_SUBST(sed) if test -z "$ECHO"; then AC_PATH_PROG(ECHO, echo,, /bin:/usr/bin) fi echo=$ECHO AC_SUBST(echo) if test -z "$SORT"; then AC_PATH_PROG(SORT, sort,, /bin:/usr/bin) fi sort=$SORT AC_SUBST(sort) dnl check if symbolic links are supported AC_PROG_LN_S if test "$enable_gettext" = yes; then if test -z "$MSGFMT"; then AC_PATH_PROG(MSGFMT, msgfmt,, $PATH) fi msgfmt=$MSGFMT AC_SUBST(msgfmt) AC_PACKAGE_NEED_UTILITY($1, "$msgfmt", msgfmt, gettext) if test -z "$MSGMERGE"; then AC_PATH_PROG(MSGMERGE, msgmerge,, $PATH) fi msgmerge=$MSGMERGE AC_SUBST(msgmerge) AC_PACKAGE_NEED_UTILITY($1, "$msgmerge", msgmerge, gettext) if test -z "$XGETTEXT"; then AC_PATH_PROG(XGETTEXT, xgettext,, $PATH) fi xgettext=$XGETTEXT AC_SUBST(xgettext) AC_PACKAGE_NEED_UTILITY($1, "$xgettext", xgettext, gettext) fi if test -z "$RPM"; then AC_PATH_PROG(RPM, rpm,, $PATH) fi rpm=$RPM AC_SUBST(rpm) dnl .. and what version is rpm rpm_version=0 test -n "$RPM" && test -x "$RPM" && rpm_version=`$RPM --version \ | awk '{print $NF}' | awk -F. '{V=1; print $V}'` AC_SUBST(rpm_version) dnl At some point in rpm 4.0, rpm can no longer build rpms, and dnl rpmbuild is needed (rpmbuild may go way back; not sure) dnl So, if rpm version >= 4.0, look for rpmbuild. Otherwise build w/ rpm if test $rpm_version -ge 4; then AC_PATH_PROG(RPMBUILD, rpmbuild) rpmbuild=$RPMBUILD else rpmbuild=$RPM fi AC_SUBST(rpmbuild) ]) xfsprogs-4.9.0+nmu1ubuntu2/m4/package_uuiddev.m40000644000000000000000000000137013063067171016375 0ustar AC_DEFUN([AC_PACKAGE_NEED_UUID_H], [ AC_CHECK_HEADERS([uuid.h sys/uuid.h uuid/uuid.h]) if test $ac_cv_header_uuid_h = no -a \ $ac_cv_header_sys_uuid_h = no -a \ $ac_cv_header_uuid_uuid_h = no; then echo echo 'FATAL ERROR: could not find a valid UUID header.' echo 'Install the Universally Unique Identifiers development package.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_NEED_UUIDCOMPARE], [ AC_CHECK_FUNCS(uuid_compare) if test $ac_cv_func_uuid_compare = yes; then libuuid="" else AC_CHECK_LIB(uuid, uuid_compare,, [ echo echo 'FATAL ERROR: could not find a valid UUID library.' echo 'Install the Universally Unique Identifiers library package.' exit 1]) libuuid="-luuid" fi AC_SUBST(libuuid) ]) xfsprogs-4.9.0+nmu1ubuntu2/man/0000755000000000000000000000000013063067174013250 5ustar xfsprogs-4.9.0+nmu1ubuntu2/man/Makefile0000644000000000000000000000062113063067171014704 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs SUBDIRS = man3 man5 man8 default : $(SUBDIRS) install : $(addsuffix -install,$(SUBDIRS)) install-dev : $(addsuffix -install-dev,$(SUBDIRS)) %-install: $(Q)$(MAKE) $(MAKEOPTS) -C $* install %-install-dev: $(Q)$(MAKE) $(MAKEOPTS) -C $* install-dev include $(BUILDRULES) xfsprogs-4.9.0+nmu1ubuntu2/man/man3/0000755000000000000000000000000013063067174014106 5ustar xfsprogs-4.9.0+nmu1ubuntu2/man/man3/Makefile0000644000000000000000000000060413063067171015543 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = ../.. include $(TOPDIR)/include/builddefs MAN_SECTION = 3 MAN_PAGES = $(shell echo *.$(MAN_SECTION)) MAN_DEST = $(PKG_MAN_DIR)/man$(MAN_SECTION) LSRCFILES = $(MAN_PAGES) default : $(MAN_PAGES) include $(BUILDRULES) install : install-dev : default $(INSTALL) -m 755 -d $(MAN_DEST) $(INSTALL_MAN) xfsprogs-4.9.0+nmu1ubuntu2/man/man3/handle.30000644000000000000000000001363713063067171015434 0ustar .TH HANDLE 3 .SH NAME path_to_handle, path_to_fshandle, fd_to_handle, handle_to_fshandle, open_by_handle, readlink_by_handle, attr_multi_by_handle, attr_list_by_handle, fssetdm_by_handle, free_handle, getparents_by_handle, getparentpaths_by_handle \- file handle operations .SH C SYNOPSIS .B #include .br .B #include .HP .BI "int\ path_to_handle(char *" path ", void **" hanp ", size_t *" hlen ); .HP .BI "int\ path_to_fshandle(char *" path ", void **" hanp ", size_t *" hlen ); .HP .BI "int\ fd_to_handle(int " fd ", void **" hanp ", size_t *" hlen ); .HP .BI "int\ handle_to_fshandle(void *" hanp ", size_t " hlen ", void **" fshanp , .BI "size_t *" fshlen ); .HP .BI "int\ open_by_handle(void *" hanp ", size_t " hlen ", int " oflag ); .HP .BI "int\ readlink_by_handle(void *" hanp ", size_t " hlen ", void *" buf , .BI "size_t " bs ); .HP .BI "int\ attr_multi_by_handle(void *" hanp ", size_t " hlen ", void *" buf , .BI "int " rtrvcnt ", int " flags ); .HP .BI "int\ attr_list_by_handle(void *" hanp ", size_t " hlen ", char *" buf , .BI "size_t " bufsiz ", int " flags ", struct attrlist_cursor *" cursor ); .HP .BI "int\ fssetdm_by_handle(void *" hanp ", size_t " hlen ", struct fsdmidata" .BI * fssetdm ); .HP .BI "void\ free_handle(void *" hanp ", size_t " hlen ); .HP .BI "int\ getparents_by_handle(void *" hanp ", size_t " hlen ", parent_t *" buf , .BI "size_t " bufsiz ", parent_cursor_t *" cursor ", unsigned int *" count , .BI "unsigned int *" more ); .HP .BI "int\ getparentpaths_by_handle(void *" hanp ", size_t " hlen ", parent_t" .BI * buf ", size_t " bufsiz ", parent_cursor_t *" cursor ", unsigned int " .BI * count ", unsigned int *" more ); .SH DESCRIPTION These functions provide a way to perform certain filesystem operations without using a file descriptor to access filesystem objects. They are intended for use by a limited set of system utilities such as backup programs. They are supported only by the XFS filesystem. Link with the .B libhandle library to access these functions. .PP A handle, .IR hanp , uniquely identifies a filesystem object or an entire filesystem. There is one and only one handle per filesystem or filesystem object. Handles consist of some number of bytes. The size of a handle (i.e. the number of bytes comprising it) varies by the type of handle and may vary for different objects of the same type. The content of a handle is opaque to applications. Since handle sizes vary and their contents are opaque, handles are described by two quantities, a pointer .RI ( hanp ") and a size (" hlen ). The size, .IR hlen , indicates the number of bytes in the handle which are pointed to by the pointer. .PP The .BR path_to_handle () function returns the handle for the object given by the .I path argument. If the final component of the path name is a symbolic link, the handle returned is that of the link itself. .PP The .BR path_to_fshandle () function returns the handle for the filesystem in which the object given by the .I path argument resides. .PP The .BR fd_to_handle () function returns the handle for the object referenced by the .I fd argument, which must be a valid file descriptor. .PP The .BR handle_to_fshandle () function returns the handle for the filesystem in which the object referenced by the handle given by the .I hanp and .I hlen arguments resides. .PP The .BR open_by_handle () function opens a file descriptor for the object referenced by a handle. It is analogous and identical to .BR open (2) with the exception of accepting handles instead of path names. .PP The .BR readlink_by_handle () function returns the contents of a symbolic link referenced by a handle. .PP The .BR attr_multi_by_handle () function manipulates multiple user attributes on a filesystem object. It is analogous and identical to .BR attr_multif (3) except that a handle is specified instead of a file descriptor. .PP The .BR attr_list_by_handle () function returns the names of the user attributes of a filesystem object. It is analogous and identical to .BR attr_listf (3) except that a handle is specified instead of a file descriptor. .PP The .BR fssetdm_by_handle () function sets the .B di_dmevmask and .B di_dmstate fields in an XFS on-disk inode. It is analogous to the .BR "XFS_IOC_FSSETDM xfsctl" (3) command, except that a handle is specified instead of a file. .PP The .BR free_handle () function frees the storage allocated for handles returned by the following functions: .BR path_to_handle (), .BR path_to_fshandle (), .BR fd_to_handle (), and .BR handle_to_fshandle (). .PP The .BR getparents_by_handle () function returns an array of .B parent_t structures for each hardlink to the inode represented by the given handle. The parent structure encodes the parent inode number, generation number and the basename of the link. .B This function is not operational on Linux. .PP The .BR getparentpaths_by_handle () function is identical to the .BR getparents_by_handle () function except that instead of returning the basename it returns the path of the link up to the mount point. .B This function is also not operational on Linux. .SH RETURN VALUE The function .BR free_handle () has no failure indication. The other functions return the value 0 to the calling process if they succeed; otherwise, they return the value \-1 and set .I errno to indicate the error. .SH ERRORS .TP .B EACCES Search permission was denied for a component of .IR path . .TP .B EBADF .I fd is not a valid and open file descriptor. .TP .B EFAULT An argument pointed to an invalid address. .TP .B EINVAL .I path is in a filesystem that does not support these functions. .TP .B ELOOP Too many symbolic links were encountered in translating the path name. .TP .B ENAMETOOLONG A component of .I path or the entire length of .I path exceeds filesystem limits. .TP .B ENOENT A component of .I path does not exist. .TP .B EPERM The caller does not have sufficient privileges. .SH SEE ALSO .BR open (2), .BR readlink (2), .BR attr_multi (3), .BR attr_list (3), .BR xfsctl (3), .BR xfs (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man3/xfsctl.30000644000000000000000000005057413063067171015505 0ustar .TH XFSCTL 3 .SH NAME xfsctl \- control XFS filesystems and individual files .SH C SYNOPSIS .B #include .HP .BI "int\ xfsctl(const char *" path ", int " fd ", int " cmd ", void *" ptr ); .PP .BI "int platform_test_xfs_fd(int " fd ); .br .BI "int platform_test_xfs_path(const char *" path ); .SH DESCRIPTION Some functionality specific to the XFS filesystem is accessible to applications through platform-specific system call interfaces. These operations can be divided into two sections \- operations that operate on individual files, and operations that operate on the filesystem itself. Care should be taken when issuing .BR xfsctl () calls to ensure the target path and file descriptor (both must be supplied) do indeed represent a file from an XFS filesystem. The .BR statfs (2) and .BR fstatfs (2) system calls can be used to determine whether or not an arbitrary path or file descriptor belong to an XFS filesystem. These are not portable however, so the routines .BR platform_test_xfs_fd () and .BR platform_test_xfs_path () provide a platform-independent mechanism. .SS File Operations In order to effect an operation on an individual file, the pathname and descriptor arguments passed to .B xfsctl identifies the file being operated on. The final argument described below refers to the final argument of .BR xfsctl . All of the data structures and macros mentioned below are defined in the .RI < xfs/xfs_fs.h > header file. .PP .B XFS_IOC_ALLOCSP .br .B XFS_IOC_ALLOCSP64 .br .B XFS_IOC_FREESP .PD 0 .TP .B XFS_IOC_FREESP64 Alter storage space associated with a section of the ordinary file specified. The section is specified by a variable of type .BR xfs_flock64_t , pointed to by the final argument. The data type .B xfs_flock64_t contains the following members: .B l_whence is 0, 1, or 2 to indicate that the relative offset .B l_start will be measured from the start of the file, the current position, or the end of the file, respectively (i.e., .B l_start is the offset from the position specified in .BR l_whence ). If the offset specified is before the current end of file, any data previously written into this section is no longer accessible. If the offset specified is beyond the current end of file, the file is grown and filled with zeroes. The .B l_len field is currently ignored, and should be set to zero. .BR XFS_IOC_ALLOCSP , .BR XFS_IOC_ALLOCSP64 , .B XFS_IOC_FREESP and .B XFS_IOC_FREESP64 operations are all identical. .TP .B XFS_IOC_FSSETDM Set the di_dmevmask and di_dmstate fields in an XFS on-disk inode. The only legitimate values for these fields are those previously returned in the .B bs_dmevmask and .B bs_dmstate fields of the bulkstat structure. The data referred to by the final argument is a .BR "struct fsdmidata" . This structure's members are .B fsd_dmevmask and .BR fsd_dmstate . The di_dmevmask field is set to the value in .BR fsd_dmevmask . The di_dmstate field is set to the value in .BR fsd_dmstate . This command is restricted to root or to processes with device management capabilities. Its sole purpose is to allow backup and restore programs to restore the aforementioned critical on-disk inode fields. .TP .B XFS_IOC_DIOINFO Get information required to perform direct I/O on the specified file descriptor. Direct I/O is performed directly to and from a user's data buffer. Since the kernel's buffer cache is no longer between the two, the user's data buffer must conform to the same type of constraints as required for accessing a raw disk partition. The final argument points to a variable of type .BR "struct dioattr" , which contains the following members: .B d_mem is the memory alignment requirement of the user's data buffer. .B d_miniosz specifies block size, minimum I/O request size, and I/O alignment. The size of all I/O requests must be a multiple of this amount and the value of the seek pointer at the time of the I/O request must also be an integer multiple of this amount. .B d_maxiosz is the maximum I/O request size which can be performed on the file descriptor. If an I/O request does not meet these constraints, the .BR read (2) or .BR write (2) will fail with EINVAL. All I/O requests are kept consistent with any data brought into the cache with an access through a non-direct I/O file descriptor. .TP .B XFS_IOC_FSGETXATTR Get additional attributes associated with files in XFS file systems. The final argument points to a variable of type .BR "struct fsxattr" , whose fields include: .B fsx_xflags (extended flag bits), .B fsx_extsize (nominal extent size in file system blocks), .B fsx_nextents (number of data extents in the file). A .B fsx_extsize value returned indicates that a preferred extent size was previously set on the file, a .B fsx_extsize of zero indicates that the defaults for that filesystem will be used. A .B fsx_cowextsize value returned indicates that a preferred copy on write extent size was previously set on the file, whereas a .B fsx_cowextsize of zero indicates that the defaults for that filesystem will be used. The current default for .B fsx_cowextsize is 128 blocks. Currently the meaningful bits for the .B fsx_xflags field are: .PD 0 .RS .TP 1.0i .SM "Bit 0 (0x1) \- XFS_XFLAG_REALTIME" The file is a realtime file. .TP .SM "Bit 1 (0x2) \- XFS_XFLAG_PREALLOC" The file has preallocated space. .TP .SM "Bit 3 (0x8) \- XFS_XFLAG_IMMUTABLE" The file is immutable - it cannot be modified, deleted or renamed, no link can be created to this file and no data can be written to the file. Only the superuser or a process possessing the CAP_LINUX_IMMUTABLE capability can set or clear this flag. .TP .SM "Bit 4 (0x10) \- XFS_XFLAG_APPEND" The file is append-only - it can only be open in append mode for writing. Only the superuser or a process possessing the CAP_LINUX_IMMUTABLE capability can set or clear this flag. .TP .SM "Bit 5 (0x20) \- XFS_XFLAG_SYNC" All writes to the file are synchronous. .TP .SM "Bit 6 (0x40) \- XFS_XFLAG_NOATIME" When the file is accessed, its atime record is not modified. .TP .SM "Bit 7 (0x80) \- XFS_XFLAG_NODUMP" The file should be skipped by backup utilities. .TP .SM "Bit 8 (0x100) \- XFS_XFLAG_RTINHERIT" Realtime inheritance bit - new files created in the directory will be automatically realtime, and new directories created in the directory will inherit the inheritance bit. .TP .SM "Bit 9 (0x200) \- XFS_XFLAG_PROJINHERIT" Project inheritance bit - new files and directories created in the directory will inherit the parents project ID. New directories also inherit the project inheritance bit. .TP .SM "Bit 10 (0x400) \- XFS_XFLAG_NOSYMLINKS" Can only be set on a directory and disallows creation of symbolic links in that directory. .TP .SM "Bit 11 (0x800) \- XFS_XFLAG_EXTSIZE" Extent size bit - if a basic extent size value is set on the file then the allocator will allocate in multiples of the set size for this file (see .B XFS_IOC_FSSETXATTR below). .TP .SM "Bit 12 (0x1000) \- XFS_XFLAG_EXTSZINHERIT" Extent size inheritance bit - new files and directories created in the directory will inherit the parents basic extent size value (see .B XFS_IOC_FSSETXATTR below). Can only be set on a directory. .TP .SM "Bit 13 (0x2000) \- XFS_XFLAG_NODEFRAG" No defragment file bit - the file should be skipped during a defragmentation operation. When applied to a directory, new files and directories created will inherit the no\-defrag bit. .TP .SM "Bit 14 (0x4000) \- XFS_XFLAG_FILESTREAM" Filestream allocator bit - allows a directory to reserve an allocation group for exclusive use by files created within that directory. Files being written in other directories will not use the same allocation group and so files within different directories will not interleave extents on disk. The reservation is only active while files are being created and written into the directory. .TP .SM "Bit 15 (0x8000) \- XFS_XFLAG_DAX" If the filesystem lives on directly accessible persistent memory, reads and writes to this file will go straight to the persistent memory, bypassing the page cache. A file cannot be reflinked and have the .BR XFS_XFLAG_DAX set at the same time. That is to say that DAX files cannot share blocks. .TP .SM "Bit 16 (0x10000) \- XFS_XFLAG_COWEXTSIZE" Copy on Write Extent size bit - if a CoW extent size value is set on the file, the allocator will allocate extents for staging a copy on write operation in multiples of the set size for this file (see .B XFS_IOC_FSSETXATTR below). If the CoW extent size is set on a directory, then new file and directories created in the directory will inherit the parent's CoW extent size value. .TP .SM "Bit 31 (0x80000000) \- XFS_XFLAG_HASATTR" The file has extended attributes associated with it. .RE .PP .PD .TP .B XFS_IOC_FSGETXATTRA Identical to .B XFS_IOC_FSGETXATTR except that the .B fsx_nextents field contains the number of attribute extents in the file. .TP .B XFS_IOC_FSSETXATTR Set additional attributes associated with files in XFS file systems. The final argument points to a variable of type .BR "struct fsxattr" , but only the following fields are used in this call: .BR fsx_xflags , .BR fsx_extsize , .BR fsx_cowextsize , and .BR fsx_projid . The .B fsx_xflags realtime file bit and the file's extent size may be changed only when the file is empty, except in the case of a directory where the extent size can be set at any time (this value is only used for regular file allocations, so should only be set on a directory in conjunction with the XFS_XFLAG_EXTSZINHERIT flag). The copy on write extent size, .BR fsx_cowextsize , can be set at any time. .TP .B XFS_IOC_GETBMAP Get the block map for a segment of a file in an XFS file system. The final argument points to an arry of variables of type .BR "struct getbmap" . All sizes and offsets in the structure are in units of 512 bytes. The structure fields include: .B bmv_offset (file offset of segment), .B bmv_block (starting block of segment), .B bmv_length (length of segment), .B bmv_count (number of array entries, including the first), and .B bmv_entries (number of entries filled in). The first structure in the array is a header, and the remaining structures in the array contain block map information on return. The header controls iterative calls to the .B XFS_IOC_GETBMAP command. The caller fills in the .B bmv_offset and .B bmv_length fields of the header to indicate the area of interest in the file, and fills in the .B bmv_count field to indicate the length of the array. If the .B bmv_length value is set to \-1 then the length of the interesting area is the rest of the file. On return from a call, the header is updated so that the command can be reused to obtain more information, without re-initializing the structures. Also on return, the .B bmv_entries field of the header is set to the number of array entries actually filled in. The non-header structures will be filled in with .BR bmv_offset , .BR bmv_block , and .BR bmv_length . If a region of the file has no blocks (is a hole in the file) then the .B bmv_block field is set to \-1. .TP .B XFS_IOC_GETBMAPA Identical to .B XFS_IOC_GETBMAP except that information about the attribute fork of the file is returned. .PP .B XFS_IOC_RESVSP .TP .B XFS_IOC_RESVSP64 This command is used to allocate space to a file. A range of bytes is specified using a pointer to a variable of type .B xfs_flock64_t in the final argument. The blocks are allocated, but not zeroed, and the file size does not change. If the XFS filesystem is configured to flag unwritten file extents, performance will be negatively affected when writing to preallocated space, since extra filesystem transactions are required to convert extent flags on the range of the file written. If .BR xfs_info (8) reports unwritten=1, then the filesystem was made to flag unwritten extents. .PP .B XFS_IOC_UNRESVSP .TP .B XFS_IOC_UNRESVSP64 This command is used to free space from a file. A range of bytes is specified using a pointer to a variable of type .B xfs_flock64_t in the final argument. Partial filesystem blocks are zeroed, and whole filesystem blocks are removed from the file. The file size does not change. .TP .B XFS_IOC_ZERO_RANGE This command is used to convert a range of a file to zeros without issuing data IO. A range of bytes is specified using a pointer to a variable of type .B xfs_flock64_t in the final argument. Blocks are preallocated for regions that span holes in the file, and the entire range is converted to unwritten extents. This operation is a fast method of overwriting any from the range specified with zeros without removing any blocks or having to write zeros to disk. Any subsequent read in the given range will return zeros until new data is written. This functionality requires filesystems to support unwritten extents. If .BR xfs_info (8) reports unwritten=1, then the filesystem was made to flag unwritten extents. .\" .TP .\" .B XFS_IOC_GETBIOSIZE .\" This command gets information about the preferred buffered I/O .\" size used by the system when performing buffered I/O (e.g. .\" standard Unix non-direct I/O) to and from the file. .\" The information is passed back in a structure of type .\" .B "struct biosize" .\" pointed to by the final argument. .\" biosize lengths are expressed in log base 2. .\" That is if the value is 14, then the true size is 2^14 (2 raised to .\" the 14th power). .\" The .\" .B biosz_read .\" field will contain the current value used by the system when reading .\" from the file. .\" Except at the end-of-file, the system will read from the file in .\" multiples of this length. .\" The .\" .B biosz_write .\" field will contain the current value used by the system when writing .\" to the file. .\" Except at the end-of-file, the system will write to the file in .\" multiples of this length. .\" The .\" .B dfl_biosz_read .\" and .\" .B dfl_biosz_write .\" will be set to the system default values for the opened file. .\" The .\" .B biosz_flags .\" field will be set to 1 if the current read or write value has been .\" explicitly set. .\" .\" .TP .\" .B XFS_IOC_SETBIOSIZE .\" This command sets information about the preferred buffered I/O size .\" used by the system when performing buffered I/O (e.g. standard Unix .\" non-direct I/O) to and from the file. .\" The information is passed in a structure of type .\" .B "struct biosize" .\" pointed to by the final argument. .\" Using smaller preferred I/O sizes can result in performance .\" improvements if the file is typically accessed using small .\" synchronous I/Os or if only a small amount of the file is accessed .\" using small random I/Os, resulting in little or no use of the .\" additional data read in near the random I/Os. .\" .\" To explicitly set the preferred I/O sizes, the .\" .B biosz_flags .\" field should be set to zero and the .\" .B biosz_read .\" and .\" .B biosz_write .\" fields should be set to the log base 2 of the desired read and .\" write lengths, respectively (e.g. 13 for 8K bytes, 14 for 16K .\" bytes, 15 for 32K bytes, etc.). Valid values are 13-16 .\" inclusive for machines with a 4K byte pagesize and 14-16 for .\" machines with a 16K byte pagesize. The specified read and .\" write values must also result in lengths that are greater than .\" or equal to the filesystem block size. .\" The .\" .B dfl_biosz_read .\" and .\" .B dfl_biosz_write .\" fields are ignored. .\" .\" If biosizes have already been explicitly set due to a prior use .\" of .\" .BR XFS_IOC_SETBIOSIZE , .\" and the requested sizes are larger than the .\" existing sizes, the .\" .I xfsctl .\" call will return successfully and the .\" system will use the smaller of the two sizes. However, if .\" .B biosz_flags .\" is set to 1, the system will use the new values .\" regardless of whether the new sizes are larger or smaller than the old. .\" .\" To reset the biosize values to the defaults for the filesystem .\" that the file resides in, the .\" .B biosz_flags .\" field should be set to 2. .\" The remainder of the fields will be ignored in that case. .\" .\" Changes made by .\" .B XFS_IOC_SETBIOSIZE .\" are transient. .\" The sizes are reset to the default values once the reference count on the .\" file drops to zero (e.g. all open file descriptors to that file .\" have been closed). .\" See .\" .I mount(8) .\" for details on how to set the .\" default biosize values for a filesystem. .PP .nf .B XFS_IOC_PATH_TO_HANDLE .B XFS_IOC_PATH_TO_FSHANDLE .B XFS_IOC_FD_TO_HANDLE .B XFS_IOC_OPEN_BY_HANDLE .B XFS_IOC_READLINK_BY_HANDLE .B XFS_IOC_ATTR_LIST_BY_HANDLE .B XFS_IOC_ATTR_MULTI_BY_HANDLE .fi .PD 0 .TP .B XFS_IOC_FSSETDM_BY_HANDLE These are all interfaces that are used to implement various .I libhandle functions (see .BR open_by_handle (3)). They are all subject to change and should not be called directly by applications. .SS Filesystem Operations In order to effect one of the following operations, the pathname and descriptor arguments passed to .BR xfsctl () can be any open file in the XFS filesystem in question. .PP .TP .B XFS_IOC_FSINUMBERS This interface is used to extract a list of valid inode numbers from an XFS filesystem. It is intended to be called iteratively, to obtain the entire set of inodes. The information is passed in and out via a structure of type .B xfs_fsop_bulkreq_t pointed to by the final argument. .B lastip is a pointer to a variable containing the last inode number returned, initially it should be zero. .B icount is the size of the array of structures specified by .BR ubuffer . .B ubuffer is the address of an array of structures, of type .BR xfs_inogrp_t . This structure has the following elements: .B xi_startino (starting inode number), .B xi_alloccount (count of bits set in xi_allocmask), and .B xi_allocmask (mask of allocated inodes in this group). The bitmask is 64 bits long, and the least significant bit corresponds to inode .B xi_startino. Each bit is set if the corresponding inode is in use. .B ocount is a pointer to a count of returned values, filled in by the call. An output .B ocount value of zero means that the inode table has been exhausted. .TP .B XFS_IOC_FSBULKSTAT This interface is used to extract inode information (stat information) "in bulk" from a filesystem. It is intended to be called iteratively, to obtain information about the entire set of inodes in a filesystem. The information is passed in and out via a structure of type .B xfs_fsop_bulkreq_t pointed to by the final argument. .B lastip is a pointer to a variable containing the last inode number returned, initially it should be zero. .B icount indicates the size of the array of structures specified by .B ubuffer. .B ubuffer is the address of an array of structures of type .BR xfs_bstat_t . Many of the elements in the structure are the same as for the stat structure. The structure has the following elements: .B bs_ino (inode number), .B bs_mode (type and mode), .B bs_nlink (number of links), .B bs_uid (user id), .B bs_gid (group id), .B bs_rdev (device value), .B bs_blksize (block size of the filesystem), .B bs_size (file size in bytes), .B bs_atime (access time), .B bs_mtime (modify time), .B bs_ctime (inode change time), .B bs_blocks (number of blocks used by the file), .B bs_xflags (extended flags), .B bs_extsize (extent size), .B bs_extents (number of extents), .B bs_gen (generation count), .B bs_projid_lo (project id - low word), .B bs_projid_hi (project id - high word, used when projid32bit feature is enabled), .B bs_dmevmask (DMIG event mask), .B bs_dmstate (DMIG state information), and .B bs_aextents (attribute extent count). .B ocount is a pointer to a count of returned values, filled in by the call. An output .B ocount value of zero means that the inode table has been exhausted. .TP .B XFS_IOC_FSBULKSTAT_SINGLE This interface is a variant of the .B XFS_IOC_FSBULKSTAT interface, used to obtain information about a single inode. for an open file in the filesystem of interest. The same structure is used to pass information in and out of the kernel, except no output count parameter is used (should be initialized to zero). An error is returned if the inode number is invalid. .PP .nf .B XFS_IOC_THAW .B XFS_IOC_FREEZE .B XFS_IOC_GET_RESBLKS .B XFS_IOC_SET_RESBLKS .B XFS_IOC_FSGROWFSDATA .B XFS_IOC_FSGROWFSLOG .B XFS_IOC_FSGROWFSRT .fi .TP .B XFS_IOC_FSCOUNTS These interfaces are used to implement various filesystem internal operations on XFS filesystems. For .B XFS_IOC_FSGEOMETRY (get filesystem mkfs time information), the output structure is of type .BR xfs_fsop_geom_t . For .B XFS_FS_COUNTS (get filesystem dynamic global information), the output structure is of type .BR xfs_fsop_counts_t . The remainder of these operations will not be described further as they are not of general use to applications. .SH SEE ALSO .BR fstatfs (2), .BR statfs (2), .BR xfs (5), .BR xfs_info (8). xfsprogs-4.9.0+nmu1ubuntu2/man/man5/0000755000000000000000000000000013063067174014110 5ustar xfsprogs-4.9.0+nmu1ubuntu2/man/man5/Makefile0000644000000000000000000000060313063067171015544 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = ../.. include $(TOPDIR)/include/builddefs MAN_SECTION = 5 MAN_PAGES = $(shell echo *.$(MAN_SECTION)) MAN_DEST = $(PKG_MAN_DIR)/man$(MAN_SECTION) LSRCFILES = $(MAN_PAGES) default : $(MAN_PAGES) include $(BUILDRULES) install : default $(INSTALL) -m 755 -d $(MAN_DEST) $(INSTALL_MAN) install-dev : xfsprogs-4.9.0+nmu1ubuntu2/man/man5/projects.50000644000000000000000000000107013063067171016022 0ustar .TH projects 5 .SH NAME projects \- persistent project root definition .SH DESCRIPTION The .I /etc/projects file provides a mapping between numeric project identifiers and those directories which are the roots of the quota tree. Its format is simply: .nf .sp .in +5 # comments are hash-prefixed # ... 10:/export/cage 42:/var/log .in -5 .fi .PP The .I /etc/projects file is optional, instead .BR xfs_quota (8) can be used with the .B \-p argument to specify a project root directly for each operation. .SH SEE ALSO .BR xfs_quota (8), .BR xfsctl (3), .BR projid (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man5/projid.50000644000000000000000000000106713063067171015466 0ustar .TH projid 5 .SH NAME projid \- the project name mapping file .SH DESCRIPTION The .I /etc/projid file provides a mapping between numeric project identifiers and a simple human readable name (similar relationship to the one that exists between usernames and uids). Its format is simply: .nf .sp .in +5 # comments are hash-prefixed # ... cage:10 logfiles:42 .in -5 .fi .PP This file is optional, if a project identifier cannot be mapped to a name, it will be parsed and displayed as a numeric value. .SH SEE ALSO .BR xfs_quota (8), .BR xfsctl (3), .BR projects (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man5/xfs.50000644000000000000000000003021313063067171014772 0ustar .TH xfs 5 .SH NAME xfs \- layout, mount options, and supported file attributes for the XFS filesystem .SH DESCRIPTION An XFS filesystem can reside on a regular disk partition or on a logical volume. An XFS filesystem has up to three parts: a data section, a log section, and a realtime section. Using the default .BR mkfs.xfs (8) options, the realtime section is absent, and the log area is contained within the data section. The log section can be either separate from the data section or contained within it. The filesystem sections are divided into a certain number of .IR blocks , whose size is specified at .BR mkfs.xfs (8) time with the .B \-b option. .PP The data section contains all the filesystem metadata (inodes, directories, indirect blocks) as well as the user file data for ordinary (non-realtime) files and the log area if the log is .I internal to the data section. The data section is divided into a number of .IR "allocation groups" . The number and size of the allocation groups are chosen by .BR mkfs.xfs (8) so that there is normally a small number of equal-sized groups. The number of allocation groups controls the amount of parallelism available in file and block allocation. It should be increased from the default if there is sufficient memory and a lot of allocation activity. The number of allocation groups should not be set very high, since this can cause large amounts of CPU time to be used by the filesystem, especially when the filesystem is nearly full. More allocation groups are added (of the original size) when .BR xfs_growfs (8) is run. .PP The log section (or area, if it is internal to the data section) is used to store changes to filesystem metadata while the filesystem is running until those changes are made to the data section. It is written sequentially during normal operation and read only during mount. When mounting a filesystem after a crash, the log is read to complete operations that were in progress at the time of the crash. .PP The realtime section is used to store the data of realtime files. These files had an attribute bit set through .BR xfsctl (3) after file creation, before any data was written to the file. The realtime section is divided into a number of .I extents of fixed size (specified at .BR mkfs.xfs (8) time). Each file in the realtime section has an extent size that is a multiple of the realtime section extent size. .PP Each allocation group contains several data structures. The first sector contains the superblock. For allocation groups after the first, the superblock is just a copy and is not updated after .BR mkfs.xfs (8). The next three sectors contain information for block and inode allocation within the allocation group. Also contained within each allocation group are data structures to locate free blocks and inodes; these are located through the header structures. .PP Each XFS filesystem is labeled with a Universal Unique Identifier (UUID). The UUID is stored in every allocation group header and is used to help distinguish one XFS filesystem from another, therefore you should avoid using .BR dd (1) or other block-by-block copying programs to copy XFS filesystems. If two XFS filesystems on the same machine have the same UUID, .BR xfsdump (8) may become confused when doing incremental and resumed dumps. .BR xfsdump (8) and .BR xfsrestore (8) are recommended for making copies of XFS filesystems. .SH OPERATIONS Some functionality specific to the XFS filesystem is accessible to applications through the .BR xfsctl (3) and by-handle (see .BR open_by_handle (3)) interfaces. .SH MOUNT OPTIONS The following XFS-specific mount options may be used when mounting an XFS filesystem. Other generic options may be used as well; refer to the .BR mount (8) manual page for more details. .TP .B allocsize=size Sets the buffered I/O end-of-file preallocation size when doing delayed allocation writeout. Valid values for this option are page size (typically 4KiB) through to 1GiB, inclusive, in power-of-2 increments. .sp The default behavior is for dynamic end-of-file preallocation size, which uses a set of heuristics to optimise the preallocation size based on the current allocation patterns within the file and the access patterns to the file. Specifying a fixed allocsize value turns off the dynamic behavior. .TP .BR attr2 | noattr2 The options enable/disable an "opportunistic" improvement to be made in the way inline extended attributes are stored on-disk. When the new form is used for the first time when attr2 is selected (either when setting or removing extended attributes) the on-disk superblock feature bit field will be updated to reflect this format being in use. .sp The default behavior is determined by the on-disk feature bit indicating that attr2 behavior is active. If either mount option it set, then that becomes the new default used by the filesystem. .sp CRC enabled filesystems always use the attr2 format, and so will reject the noattr2 mount option if it is set. .TP .BR barrier | nobarrier Enables/disables the use of block layer write barriers for writes into the journal and for data integrity operations. This allows for drive level write caching to be enabled, for devices that support write barriers. .sp Barriers are enabled by default. .TP .BR discard | nodiscard Enable/disable the issuing of commands to let the block device reclaim space freed by the filesystem. This is useful for SSD devices, thinly provisioned LUNs and virtual machine images, but may have a performance impact. .sp Note: It is currently recommended that you use the fstrim application to discard unused blocks rather than the discard mount option because the performance impact of this option is quite severe. For this reason, nodiscard is the default. .TP .BR grpid | bsdgroups | nogrpid | sysvgroups These options define what group ID a newly created file gets. When grpid is set, it takes the group ID of the directory in which it is created; otherwise it takes the fsgid of the current process, unless the directory has the setgid bit set, in which case it takes the gid from the parent directory, and also gets the setgid bit set if it is a directory itself. .TP .B filestreams Make the data allocator use the filestreams allocation mode across the entire filesystem rather than just on directories configured to use it. .TP .BR ikeep | noikeep When ikeep is specified, XFS does not delete empty inode clusters and keeps them around on disk. When noikeep is specified, empty inode clusters are returned to the free space pool. noikeep is the default. .TP .BR inode32 | inode64 When inode32 is specified, it indicates that XFS limits inode creation to locations which will not result in inode numbers with more than 32 bits of significance. .sp When inode64 is specified, it indicates that XFS is allowed to create inodes at any location in the filesystem, including those which will result in inode numbers occupying more than 32 bits of significance. .sp inode32 is provided for backwards compatibility with older systems and applications, since 64 bits inode numbers might cause problems for some applications that cannot handle large inode numbers. If applications are in use which do not handle inode numbers bigger than 32 bits, the inode32 option should be specified. .sp For kernel v3.7 and later, inode64 is the default. .TP .BR largeio | nolargeio If "nolargeio" is specified, the optimal I/O reported in st_blksize by stat(2) will be as small as possible to allow user applications to avoid inefficient read/modify/write I/O. This is typically the page size of the machine, as this is the granularity of the page cache. .sp If "largeio" specified, a filesystem that was created with a "swidth" specified will return the "swidth" value (in bytes) in st_blksize. If the filesystem does not have a "swidth" specified but does specify an "allocsize" then "allocsize" (in bytes) will be returned instead. Otherwise the behavior is the same as if "nolargeio" was specified. nolargeio is the default. .TP .B logbufs=value Set the number of in-memory log buffers. Valid numbers range from 2\(en8 inclusive. .sp The default value is 8 buffers. .sp If the memory cost of 8 log buffers is too high on small systems, then it may be reduced at some cost to performance on metadata intensive workloads. The logbsize option below controls the size of each buffer and so is also relevant to this case. .TP .B logbsize=value Set the size of each in-memory log buffer. The size may be specified in bytes, or in kibibytes (KiB) with a "k" suffix. Valid sizes for version 1 and version 2 logs are 16384 (value=16k) and 32768 (value=32k). Valid sizes for version 2 logs also include 65536 (value=64k), 131072 (value=128k) and 262144 (value=256k). The logbsize must be an integer multiple of the log stripe unit configured at mkfs time. .sp The default value for version 1 logs is 32768, while the default value for version 2 logs is MAX(32768, log_sunit). .TP .BR logdev=device " and " rtdev=device Use an external log (metadata journal) and/or real-time device. An XFS filesystem has up to three parts: a data section, a log section, and a real-time section. The real-time section is optional, and the log section can be separate from the data section or contained within it. .TP .B noalign Data allocations will not be aligned at stripe unit boundaries. This is only relevant to filesystems created with non-zero data alignment parameters (sunit, swidth) by mkfs. .TP .B norecovery The filesystem will be mounted without running log recovery. If the filesystem was not cleanly unmounted, it is likely to be inconsistent when mounted in "norecovery" mode. Some files or directories may not be accessible because of this. Filesystems mounted "norecovery" must be mounted read-only or the mount will fail. .TP .B nouuid Don't check for double mounted file systems using the file system uuid. This is useful to mount LVM snapshot volumes, and often used in combination with "norecovery" for mounting read-only snapshots. .TP .B noquota Forcibly turns off all quota accounting and enforcement within the filesystem. .TP .B uquota/usrquota/quota/uqnoenforce/qnoenforce User disk quota accounting enabled, and limits (optionally) enforced. Refer to xfs_quota(8) for further details. .TP .B gquota/grpquota/gqnoenforce Group disk quota accounting enabled and limits (optionally) enforced. Refer to xfs_quota(8) for further details. .TP .B pquota/prjquota/pqnoenforce Project disk quota accounting enabled and limits (optionally) enforced. Refer to xfs_quota(8) for further details. .TP .BR sunit=value " and " swidth=value Used to specify the stripe unit and width for a RAID device or a stripe volume. "value" must be specified in 512-byte block units. These options are only relevant to filesystems that were created with non-zero data alignment parameters. .sp The sunit and swidth parameters specified must be compatible with the existing filesystem alignment characteristics. In general, that means the only valid changes to sunit are increasing it by a power-of-2 multiple. Valid swidth values are any integer multiple of a valid sunit value. .sp Typically the only time these mount options are necessary if after an underlying RAID device has had it's geometry modified, such as adding a new disk to a RAID5 lun and reshaping it. .TP .B swalloc Data allocations will be rounded up to stripe width boundaries when the current end of file is being extended and the file size is larger than the stripe width size. .TP .B wsync When specified, all filesystem namespace operations are executed synchronously. This ensures that when the namespace operation (create, unlink, etc) completes, the change to the namespace is on stable storage. This is useful in HA setups where failover must not result in clients seeing inconsistent namespace presentation during or after a failover event. .SH FILE ATTRIBUTES The XFS filesystem supports setting the following file attributes on Linux systems using the .BR chattr (1) utility: .sp .BR a " - append only" .sp .BR A " - no atime updates" .sp .BR d " - no dump" .sp .BR i " - immutable" .sp .BR S " - synchronous updates" .sp For descriptions of these attribute flags, please refer to the .BR chattr (1) man page. .SH SEE ALSO .BR chattr (1), .BR xfsctl (3), .BR mount (8), .BR mkfs.xfs (8), .BR xfs_info (8), .BR xfs_admin (8), .BR xfsdump (8), .BR xfsrestore (8). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/0000755000000000000000000000000013063067174014113 5ustar xfsprogs-4.9.0+nmu1ubuntu2/man/man8/Makefile0000644000000000000000000000060313063067171015547 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = ../.. include $(TOPDIR)/include/builddefs MAN_SECTION = 8 MAN_PAGES = $(shell echo *.$(MAN_SECTION)) MAN_DEST = $(PKG_MAN_DIR)/man$(MAN_SECTION) LSRCFILES = $(MAN_PAGES) default : $(MAN_PAGES) include $(BUILDRULES) install : default $(INSTALL) -m 755 -d $(MAN_DEST) $(INSTALL_MAN) install-dev : xfsprogs-4.9.0+nmu1ubuntu2/man/man8/fsck.xfs.80000644000000000000000000000115113063067171015724 0ustar .TH fsck.xfs 8 .SH NAME fsck.xfs \- do nothing, successfully .SH SYNOPSIS .B fsck.xfs [ .I filesys \&... ] .SH DESCRIPTION .B fsck.xfs is called by the generic Linux .BR fsck (8) program at startup to check and repair an XFS filesystem. XFS is a journaling filesystem and performs recovery at .BR mount (8) time if necessary, so .B fsck.xfs simply exits with a zero exit status. .PP If you wish to check the consistency of an XFS filesystem, or repair a damaged or corrupt XFS filesystem, see .BR xfs_repair (8). . .SH FILES .IR /etc/fstab . .SH SEE ALSO .BR fsck (8), .BR fstab (5), .BR xfs (5), .BR xfs_repair (8). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/mkfs.xfs.80000644000000000000000000006763013063067171015754 0ustar .TH mkfs.xfs 8 .SH NAME mkfs.xfs \- construct an XFS filesystem .SH SYNOPSIS .B mkfs.xfs [ .B \-b .I block_size ] [ .B \-m .I global_metadata_options ] [ .B \-d .I data_section_options ] [ .B \-f ] [ .B \-i .I inode_options ] [ .B \-l .I log_section_options ] [ .B \-n .I naming_options ] [ .B \-p .I protofile ] [ .B \-q ] [ .B \-r .I realtime_section_options ] [ .B \-s .I sector_size ] [ .B \-L .I label ] [ .B \-N ] [ .B \-K ] .I device .br .B mkfs.xfs \-V .SH DESCRIPTION .B mkfs.xfs constructs an XFS filesystem by writing on a special file using the values found in the arguments of the command line. It is invoked automatically by .BR mkfs (8) when it is given the .B \-t xfs option. .PP In its simplest (and most commonly used form), the size of the filesystem is determined from the disk driver. As an example, to make a filesystem with an internal log on the first partition on the first SCSI disk, use: .IP .B mkfs.xfs /dev/sda1 .PP The metadata log can be placed on another device to reduce the number of disk seeks. To create a filesystem on the first partition on the first SCSI disk with a 10MiB log located on the first partition on the second SCSI disk, use: .RS .HP .B mkfs.xfs\ \-l\ logdev=/dev/sdb1,size=10m /dev/sda1 .RE .PP Each of the .I option elements in the argument list above can be given as multiple comma-separated suboptions if multiple suboptions apply to the same option. Equivalently, each main option can be given multiple times with different suboptions. For example, .B \-l internal,size=10m and .B \-l internal \-l size=10m are equivalent. .PP In the descriptions below, sizes are given in sectors, bytes, blocks, kilobytes, megabytes, gigabytes, etc. Sizes are treated as hexadecimal if prefixed by 0x or 0X, octal if prefixed by 0, or decimal otherwise. The following lists possible multiplication suffixes: .RS .PD 0 .HP .BR s "\ \-\ multiply by sector size (default = 512, see " \-s option below). .HP .BR b "\ \-\ multiply by filesystem block size (default = 4K, see " \-b option below). .HP .BR k "\ \-\ multiply by one kilobyte (1,024 bytes)." .HP .BR m "\ \-\ multiply by one megabyte (1,048,576 bytes)." .HP .BR g "\ \-\ multiply by one gigabyte (1,073,741,824 bytes)." .HP .BR t "\ \-\ multiply by one terabyte (1,099,511,627,776 bytes)." .HP .BR p "\ \-\ multiply by one petabyte (1,024 terabytes)." .HP .BR e "\ \-\ multiply by one exabyte (1,048,576 terabytes)." .PD .RE .PP When specifying parameters in units of sectors or filesystem blocks, the .B \-s option or the .B \-b option first needs to be added to the command line. Failure to specify the size of the units will result in illegal value errors when parameters are quantified in those units. .PP Many feature options allow an optional argument of 0 or 1, to explicitly disable or enable the functionality. .SH OPTIONS .TP .BI \-b " block_size_options" This option specifies the fundamental block size of the filesystem. The valid .I block_size_options are: .BI log= value or .BI size= value and only one can be supplied. The block size is specified either as a base two logarithm value with .BR log= , or in bytes with .BR size= . The default value is 4096 bytes (4 KiB), the minimum is 512, and the maximum is 65536 (64 KiB). .IP To specify any options on the command line in units of filesystem blocks, this option must be specified first so that the filesystem block size is applied consistently to all options. .IP Although .B mkfs.xfs will accept any of these values and create a valid filesystem, XFS on Linux can only mount filesystems with pagesize or smaller blocks. .TP .BI \-m " global_metadata_options" These options specify metadata format options that either apply to the entire filesystem or aren't easily characterised by a specific functionality group. The valid .I global_metadata_options are: .RS 1.2i .TP .BI crc= value This is used to create a filesystem which maintains and checks CRC information in all metadata objects on disk. The value is either 0 to disable the feature, or 1 to enable the use of CRCs. .IP CRCs enable enhanced error detection due to hardware issues, whilst the format changes also improves crash recovery algorithms and the ability of various tools to validate and repair metadata corruptions when they are found. The CRC algorithm used is CRC32c, so the overhead is dependent on CPU architecture as some CPUs have hardware acceleration of this algorithm. Typically the overhead of calculating and checking the CRCs is not noticeable in normal operation. .IP By default, .B mkfs.xfs will enable metadata CRCs. .TP .BI finobt= value This option enables the use of a separate free inode btree index in each allocation group. The value is either 0 to disable the feature, or 1 to create a free inode btree in each allocation group. .IP The free inode btree mirrors the existing allocated inode btree index which indexes both used and free inodes. The free inode btree does not index used inodes, allowing faster, more consistent inode allocation performance as filesystems age. .IP By default, .B mkfs.xfs will create free inode btrees for filesystems created with the (default) .B \-m crc=1 option set. When the option .B \-m crc=0 is used, the free inode btree feature is not supported and is disabled. .TP .BI uuid= value Use the given value as the filesystem UUID for the newly created filesystem. The default is to generate a random UUID. .TP .BI rmapbt= value This option enables the creation of a reverse-mapping btree index in each allocation group. The value is either 0 to disable the feature, or 1 to create the btree. .IP The reverse mapping btree maps filesystem blocks to the owner of the filesystem block. Most of the mappings will be to an inode number and an offset, though there will also be mappings to filesystem metadata. This secondary metadata can be used to validate the primary metadata or to pinpoint exactly which data has been lost when a disk error occurs. .IP By default, .B mkfs.xfs will not create reverse mapping btrees. This feature is only available for filesystems created with the (default) .B \-m crc=1 option set. When the option .B \-m crc=0 is used, the reverse mapping btree feature is not supported and is disabled. .TP .BI reflink= value This option enables the use of a separate reference count btree index in each allocation group. The value is either 0 to disable the feature, or 1 to create a reference count btree in each allocation group. .IP The reference count btree enables the sharing of physical extents between the data forks of different files, which is commonly known as "reflink". Unlike traditional Unix filesystems which assume that every inode and logical block pair map to a unique physical block, a reflink-capable XFS filesystem removes the uniqueness requirement, allowing up to four billion arbitrary inode/logical block pairs to map to a physical block. If a program tries to write to a multiply-referenced block in a file, the write will be redirected to a new block, and that file's logical-to-physical mapping will be changed to the new block ("copy on write"). This feature enables the creation of per-file snapshots and deduplication. It is only available for the data forks of regular files. .IP By default, .B mkfs.xfs will not create reference count btrees and therefore will not enable the reflink feature. This feature is only available for filesystems created with the (default) .B \-m crc=1 option set. When the option .B \-m crc=0 is used, the reference count btree feature is not supported and reflink is disabled. .RE .TP .BI \-d " data_section_options" These options specify the location, size, and other parameters of the data section of the filesystem. The valid .I data_section_options are: .RS 1.2i .TP .BI agcount= value This is used to specify the number of allocation groups. The data section of the filesystem is divided into allocation groups to improve the performance of XFS. More allocation groups imply that more parallelism can be achieved when allocating blocks and inodes. The minimum allocation group size is 16 MiB; the maximum size is just under 1 TiB. The data section of the filesystem is divided into .I value allocation groups (default value is scaled automatically based on the underlying device size). .TP .BI agsize= value This is an alternative to using the .B agcount suboption. The .I value is the desired size of the allocation group expressed in bytes (usually using the .BR m " or " g suffixes). This value must be a multiple of the filesystem block size, and must be at least 16MiB, and no more than 1TiB, and may be automatically adjusted to properly align with the stripe geometry. The .B agcount and .B agsize suboptions are mutually exclusive. .TP .BI name= value This can be used to specify the name of the special file containing the filesystem. In this case, the log section must be specified as .B internal (with a size, see the .B \-l option below) and there can be no real-time section. .TP .BI file[= value ] This is used to specify that the file given by the .B name suboption is a regular file. The .I value is either 0 or 1, with 1 signifying that the file is regular. This suboption is used only to make a filesystem image. If the .I value is omitted then 1 is assumed. .TP .BI size= value This is used to specify the size of the data section. This suboption is required if .B \-d file[=1] is given. Otherwise, it is only needed if the filesystem should occupy less space than the size of the special file. .TP .BI sunit= value This is used to specify the stripe unit for a RAID device or a logical volume. The .I value has to be specified in 512-byte block units. Use the .B su suboption to specify the stripe unit size in bytes. This suboption ensures that data allocations will be stripe unit aligned when the current end of file is being extended and the file size is larger than 512KiB. Also inode allocations and the internal log will be stripe unit aligned. .TP .BI su= value This is an alternative to using .B sunit. The .B su suboption is used to specify the stripe unit for a RAID device or a striped logical volume. The .I value has to be specified in bytes, (usually using the .BR m " or " g suffixes). This .I value must be a multiple of the filesystem block size. .TP .BI swidth= value This is used to specify the stripe width for a RAID device or a striped logical volume. The .I value has to be specified in 512-byte block units. Use the .B sw suboption to specify the stripe width size in bytes. This suboption is required if .B \-d sunit has been specified and it has to be a multiple of the .B \-d sunit suboption. .TP .BI sw= value suboption is an alternative to using .B swidth. The .B sw suboption is used to specify the stripe width for a RAID device or striped logical volume. The .I value is expressed as a multiplier of the stripe unit, usually the same as the number of stripe members in the logical volume configuration, or data disks in a RAID device. .IP When a filesystem is created on a logical volume device, .B mkfs.xfs will automatically query the logical volume for appropriate .B sunit and .B swidth values. .TP .BI noalign This option disables automatic geometry detection and creates the filesystem without stripe geometry alignment even if the underlying storage device provides this information. .RE .TP .B \-f Force overwrite when an existing filesystem is detected on the device. By default, .B mkfs.xfs will not write to the device if it suspects that there is a filesystem or partition table on the device already. .TP .BI \-i " inode_options" This option specifies the inode size of the filesystem, and other inode allocation parameters. The XFS inode contains a fixed-size part and a variable-size part. The variable-size part, whose size is affected by this option, can contain: directory data, for small directories; attribute data, for small attribute sets; symbolic link data, for small symbolic links; the extent list for the file, for files with a small number of extents; and the root of a tree describing the location of extents for the file, for files with a large number of extents. .IP The valid .I inode_options are: .RS 1.2i .TP .BI size= value " | log=" value " | perblock=" value The inode size is specified either as a .I value in bytes with .BR size= , a base two logarithm .I value with .BR log= , or as the number fitting in a filesystem block with .BR perblock= . The minimum (and default) .I value is 256 bytes without crc, 512 bytes with crc enabled. The maximum .I value is 2048 (2 KiB) subject to the restriction that the inode size cannot exceed one half of the filesystem block size. .IP XFS uses 64-bit inode numbers internally; however, the number of significant bits in an inode number is affected by filesystem geometry. In practice, filesystem size and inode size are the predominant factors. The Linux kernel (on 32 bit hardware platforms) and most applications cannot currently handle inode numbers greater than 32 significant bits, so if no inode size is given on the command line, .B mkfs.xfs will attempt to choose a size such that inode numbers will be < 32 bits. If an inode size is specified, or if a filesystem is sufficiently large, .B mkfs.xfs will warn if this will create inode numbers > 32 significant bits. .TP .BI maxpct= value This specifies the maximum percentage of space in the filesystem that can be allocated to inodes. The default .I value is 25% for filesystems under 1TB, 5% for filesystems under 50TB and 1% for filesystems over 50TB. .IP In the default inode allocation mode, inode blocks are chosen such that inode numbers will not exceed 32 bits, which restricts the inode blocks to the lower portion of the filesystem. The data block allocator will avoid these low blocks to accommodate the specified maxpct, so a high value may result in a filesystem with nothing but inodes in a significant portion of the lower blocks of the filesystem. (This restriction is not present when the filesystem is mounted with the .I "inode64" option on 64-bit platforms). .IP Setting the value to 0 means that essentially all of the filesystem can become inode blocks, subject to inode32 restrictions. .IP This value can be modified with .IR xfs_growfs(8) . .TP .BI align[= value ] This is used to specify that inode allocation is or is not aligned. The .I value is either 0 or 1, with 1 signifying that inodes are allocated aligned. If the .I value is omitted, 1 is assumed. The default is that inodes are aligned. Aligned inode access is normally more efficient than unaligned access; alignment must be established at the time the filesystem is created, since inodes are allocated at that time. This option can be used to turn off inode alignment when the filesystem needs to be mountable by a version of IRIX that does not have the inode alignment feature (any release of IRIX before 6.2, and IRIX 6.2 without XFS patches). .TP .BI attr= value This is used to specify the version of extended attribute inline allocation policy to be used. By default, this is 2, which uses an efficient algorithm for managing the available inline inode space between attribute and extent data. .IP The previous version 1, which has fixed regions for attribute and extent data, is kept for backwards compatibility with kernels older than version 2.6.16. .TP .BI projid32bit[= value ] This is used to enable 32bit quota project identifiers. The .I value is either 0 or 1, with 1 signifying that 32bit projid are to be enabled. If the value is omitted, 1 is assumed. (This default changed in release version 3.2.0.) .TP .BI sparse[= value ] Enable sparse inode chunk allocation. The .I value is either 0 or 1, with 1 signifying that sparse allocation is enabled. If the value is omitted, 1 is assumed. Sparse inode allocation is disabled by default. This feature is only available for filesystems formatted with .B \-m crc=1. .IP When enabled, sparse inode allocation allows the filesystem to allocate smaller than the standard 64-inode chunk when free space is severely limited. This feature is useful for filesystems that might fragment free space over time such that no free extents are large enough to accommodate a chunk of 64 inodes. Without this feature enabled, inode allocations can fail with out of space errors under severe fragmented free space conditions. .RE .TP .BI \-l " log_section_options" These options specify the location, size, and other parameters of the log section of the filesystem. The valid .I log_section_options are: .RS 1.2i .TP .BI internal[= value ] This is used to specify that the log section is a piece of the data section instead of being another device or logical volume. The .I value is either 0 or 1, with 1 signifying that the log is internal. If the .I value is omitted, 1 is assumed. .TP .BI logdev= device This is used to specify that the log section should reside on the .I device separate from the data section. The .B internal=1 and .B logdev options are mutually exclusive. .TP .BI size= value This is used to specify the size of the log section. .IP If the log is contained within the data section and .B size isn't specified, .B mkfs.xfs will try to select a suitable log size depending on the size of the filesystem. The actual logsize depends on the filesystem block size and the directory block size. .IP Otherwise, the .B size suboption is only needed if the log section of the filesystem should occupy less space than the size of the special file. The .I value is specified in bytes or blocks, with a .B b suffix meaning multiplication by the filesystem block size, as described above. The overriding minimum value for size is 512 blocks. With some combinations of filesystem block size, inode size, and directory block size, the minimum log size is larger than 512 blocks. .TP .BI version= value This specifies the version of the log. The current default is 2, which allows for larger log buffer sizes, as well as supporting stripe-aligned log writes (see the sunit and su options, below). .IP The previous version 1, which is limited to 32k log buffers and does not support stripe-aligned writes, is kept for backwards compatibility with very old 2.4 kernels. .TP .BI sunit= value This specifies the alignment to be used for log writes. The .I value has to be specified in 512-byte block units. Use the .B su suboption to specify the log stripe unit size in bytes. Log writes will be aligned on this boundary, and rounded up to this boundary. This gives major improvements in performance on some configurations such as software RAID5 when the .B sunit is specified as the filesystem block size. The equivalent byte value must be a multiple of the filesystem block size. Version 2 logs are automatically selected if the log .B sunit suboption is specified. .IP The .B su suboption is an alternative to using .B sunit. .TP .BI su= value This is used to specify the log stripe. The .I value has to be specified in bytes, (usually using the .BR s " or " b suffixes). This value must be a multiple of the filesystem block size. Version 2 logs are automatically selected if the log .B su suboption is specified. .TP .BI lazy-count= value This changes the method of logging various persistent counters in the superblock. Under metadata intensive workloads, these counters are updated and logged frequently enough that the superblock updates become a serialization point in the filesystem. The .I value can be either 0 or 1. .IP With .BR lazy-count=1 , the superblock is not modified or logged on every change of the persistent counters. Instead, enough information is kept in other parts of the filesystem to be able to maintain the persistent counter values without needed to keep them in the superblock. This gives significant improvements in performance on some configurations. The default .I value is 1 (on) so you must specify .B lazy-count=0 if you want to disable this feature for older kernels which don't support it. .RE .TP .BI \-n " naming_options" These options specify the version and size parameters for the naming (directory) area of the filesystem. The valid .I naming_options are: .RS 1.2i .TP .BI size= value " | log=" value The block size is specified either as a .I value in bytes with .BR size= , or as a base two logarithm .I value .RB "with " log= . The block size must be a power of 2 and cannot be less than the filesystem block size. The default size .I value for version 2 directories is 4096 bytes (4 KiB), unless the filesystem block size is larger than 4096, in which case the default .I value is the filesystem block size. For version 1 directories the block size is the same as the filesystem block size. .TP .BI version= value The naming (directory) version .I value can be either 2 or 'ci', defaulting to 2 if unspecified. With version 2 directories, the directory block size can be any power of 2 size from the filesystem block size up to 65536. .IP The .B version=ci option enables ASCII only case-insensitive filename lookup and version 2 directories. Filenames are case-preserving, that is, the names are stored in directories using the case they were created with. .IP Note: Version 1 directories are not supported. .TP .BI ftype= value This feature allows the inode type to be stored in the directory structure so that the .BR readdir (3) and .BR getdents (2) do not need to look up the inode to determine the inode type. The .I value is either 0 or 1, with 1 signifying that filetype information will be stored in the directory structure. The default value is 1. When CRCs are enabled (the default), the ftype functionality is always enabled, and cannot be turned off. .IP .RE .TP .BI \-p " protofile" If the optional .BI \-p " protofile" argument is given, .B mkfs.xfs uses .I protofile as a prototype file and takes its directions from that file. The blocks and inodes specifiers in the .I protofile are provided for backwards compatibility, but are otherwise unused. The syntax of the protofile is defined by a number of tokens separated by spaces or newlines. Note that the line numbers are not part of the syntax but are meant to help you in the following discussion of the file contents. .nf .sp .8v .in +5 \f71 /stand/\f1\f2diskboot\f1\f7 2 4872 110 3 d\-\-777 3 1 4 usr d\-\-777 3 1 5 sh \-\-\-755 3 1 /bin/sh 6 ken d\-\-755 6 1 7 $ 8 b0 b\-\-644 3 1 0 0 9 c0 c\-\-644 3 1 0 0 10 fifo p\-\-644 3 1 11 slink l\-\-644 3 1 /a/symbolic/link 12 : This is a comment line 13 $ 14 $\f1 .in -5 .fi .IP Line 1 is a dummy string. (It was formerly the bootfilename.) It is present for backward compatibility; boot blocks are not used on SGI systems. .IP Note that some string of characters must be present as the first line of the proto file to cause it to be parsed correctly; the value of this string is immaterial since it is ignored. .IP Line 2 contains two numeric values (formerly the numbers of blocks and inodes). These are also merely for backward compatibility: two numeric values must appear at this point for the proto file to be correctly parsed, but their values are immaterial since they are ignored. .IP The lines 3 through 11 specify the files and directories you want to include in this filesystem. Line 3 defines the root directory. Other directories and files that you want in the filesystem are indicated by lines 4 through 6 and lines 8 through 10. Line 11 contains symbolic link syntax. .IP Notice the dollar sign .RB ( $ ) syntax on line 7. This syntax directs the .B mkfs.xfs command to terminate the branch of the filesystem it is currently on and then continue from the directory specified by the next line, in this case line 8. It must be the last character on a line. The colon on line 12 introduces a comment; all characters up until the following newline are ignored. Note that this means you cannot have a file in a prototype file whose name contains a colon. The .B $ on lines 13 and 14 end the process, since no additional specifications follow. .IP File specifications provide the following: .IP * file mode .br * user ID .br * group ID .br * the file's beginning contents .P .IP A 6-character string defines the mode for a file. The first character of this string defines the file type. The character range for this first character is .B \-bcdpl. A file may be a regular file, a block special file, a character special file, directory files, named pipes (first-in, first out files), and symbolic links. The second character of the mode string is used to specify setuserID mode, in which case it is .BR u . If setuserID mode is not specified, the second character is .BR \- . The third character of the mode string is used to specify the setgroupID mode, in which case it is .BR g . If setgroupID mode is not specified, the third character is .BR \- . The remaining characters of the mode string are a three digit octal number. This octal number defines the owner, group, and other read, write, and execute permissions for the file, respectively. For more information on file permissions, see the .BR chmod (1) command. .IP Following the mode character string are two decimal number tokens that specify the user and group IDs of the file's owner. .IP In a regular file, the next token specifies the pathname from which the contents and size of the file are copied. In a block or character special file, the next token are two decimal numbers that specify the major and minor device numbers. When a file is a symbolic link, the next token specifies the contents of the link. When the file is a directory, the .B mkfs.xfs command creates the entries .B dot (.) and .B dot-dot (..) and then reads the list of names and file specifications in a recursive manner for all of the entries in the directory. A scan of the protofile is always terminated with the dollar ( .B $ ) token. .TP .B \-q Quiet option. Normally .B mkfs.xfs prints the parameters of the filesystem to be constructed; the .B \-q flag suppresses this. .TP .BI \-r " realtime_section_options" These options specify the location, size, and other parameters of the real-time section of the filesystem. The valid .I realtime_section_options are: .RS 1.2i .TP .BI rtdev= device This is used to specify the .I device which should contain the real-time section of the filesystem. The suboption value is the name of a block device. .TP .BI extsize= value This is used to specify the size of the blocks in the real-time section of the filesystem. This .I value must be a multiple of the filesystem block size. The minimum allowed size is the filesystem block size or 4 KiB (whichever is larger); the default size is the stripe width for striped volumes or 64 KiB for non-striped volumes; the maximum allowed size is 1 GiB. The real-time extent size should be carefully chosen to match the parameters of the physical media used. .TP .BI size= value This is used to specify the size of the real-time section. This suboption is only needed if the real-time section of the filesystem should occupy less space than the size of the partition or logical volume containing the section. .TP .BI noalign This option disables stripe size detection, enforcing a realtime device with no stripe geometry. .RE .TP .BI \-s " sector_size" This option specifies the fundamental sector size of the filesystem. The .I sector_size is specified either as a value in bytes with .BI size= value or as a base two logarithm value with .BI log= value. The default .I sector_size is 512 bytes. The minimum value for sector size is 512; the maximum is 32768 (32 KiB). The .I sector_size must be a power of 2 size and cannot be made larger than the filesystem block size. .IP To specify any options on the command line in units of sectors, this option must be specified first so that the sector size is applied consistently to all options. .TP .BI \-L " label" Set the filesystem .IR label . XFS filesystem labels can be at most 12 characters long; if .I label is longer than 12 characters, .B mkfs.xfs will not proceed with creating the filesystem. Refer to the .BR mount "(8) and " xfs_admin (8) manual entries for additional information. .TP .B \-N Causes the file system parameters to be printed out without really creating the file system. .TP .B \-K Do not attempt to discard blocks at mkfs time. .TP .B \-V Prints the version number and exits. .SH SEE ALSO .BR xfs (5), .BR mkfs (8), .BR mount (8), .BR xfs_info (8), .BR xfs_admin (8). .SH BUGS With a prototype file, it is not possible to specify hard links. xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_admin.80000644000000000000000000000607613063067171016162 0ustar .TH xfs_admin 8 .SH NAME xfs_admin \- change parameters of an XFS filesystem .SH SYNOPSIS .B xfs_admin [ .B \-eflpu ] [ .BR "\-c 0" | 1 ] [ .B \-L .I label ] [ .B \-U .I uuid ] .I device .br .B xfs_admin \-V .SH DESCRIPTION .B xfs_admin uses the .BR xfs_db (8) command to modify various parameters of a filesystem. .PP Devices that are mounted cannot be modified. Administrators must unmount filesystems before .BR xfs_admin " or " xfs_db (8) can convert parameters. A number of parameters of a mounted filesystem can be examined and modified using the .BR xfs_growfs (8) command. .SH OPTIONS .TP .B \-e Enables unwritten extent support on a filesystem that does not already have this enabled (for legacy filesystems, it can't be disabled anymore at mkfs time). .TP .B \-f Specifies that the filesystem image to be processed is stored in a regular file at .I device (see the .B mkfs.xfs \-d .I file option). .TP .B \-j Enables version 2 log format (journal format supporting larger log buffers). .TP .B \-l Print the current filesystem label. .TP .B \-p Enable 32bit project identifier support (PROJID32BIT feature). .TP .B \-u Print the current filesystem UUID (Universally Unique IDentifier). .TP .BR "\-c 0" | 1 Enable (1) or disable (0) lazy-counters in the filesystem. .IP Lazy-counters may not be disabled on Version 5 superblock filesystems (i.e. those with metadata CRCs enabled). .IP This operation may take quite a bit of time on large filesystems as the entire filesystem needs to be scanned when this option is changed. .IP With lazy-counters enabled, the superblock is not modified or logged on every change of the free-space and inode counters. Instead, enough information is kept in other parts of the filesystem to be able to maintain the counter values without needing to keep them in the superblock. This gives significant improvements in performance on some configurations and metadata intensive workloads. .TP .BI \-L " label" Set the filesystem label to .IR label . XFS filesystem labels can be at most 12 characters long; if .I label is longer than 12 characters, .B xfs_admin will truncate it and print a warning message. The filesystem label can be cleared using the special "\c .B \-\-\c " value for .IR label . .TP .BI \-U " uuid" Set the UUID of the filesystem to .IR uuid . A sample UUID looks like this: "c1b9d5a2-f162-11cf-9ece-0020afc76f16". The .I uuid may also be .BR nil , which will set the filesystem UUID to the null UUID. The .I uuid may also be .BR generate , which will generate a new UUID for the filesystem. Note that on CRC-enabled filesystems, this will set an incompatible flag such that older kernels will not be able to mount the filesystem. To remove this incompatible flag, use .BR restore , which will restore the original UUID and remove the incompatible feature flag as needed. .TP .B \-V Prints the version number and exits. .PP The .BR mount (8) manual entry describes how to mount a filesystem using its label or UUID, rather than its block special device name. .SH SEE ALSO .BR mkfs.xfs (8), .BR mount (8), .BR xfs_db (8), .BR xfs_growfs (8), .BR xfs_repair (8), .BR xfs (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_bmap.80000644000000000000000000000527313063067171016007 0ustar .TH xfs_bmap 8 .SH NAME xfs_bmap \- print block mapping for an XFS file .SH SYNOPSIS .B xfs_bmap [ .B \-adlpv ] [ .B \-n .I num_extents ] .I file .br .B xfs_bmap \-V .SH DESCRIPTION .B xfs_bmap prints the map of disk blocks used by files in an XFS filesystem. The map lists each .I extent used by the file, as well as regions in the file that do not have any corresponding blocks (holes). Each line of the listings takes the following form: .PP .RS .IR extent ": [" startoffset .. endoffset "]: " startblock .. endblock .RE .PP Holes are marked by replacing the .IR startblock .. endblock " with " hole . All the file offsets and disk blocks are in units of 512-byte blocks, no matter what the filesystem's block size is. .PP .SH OPTIONS .TP .B \-a If this option is specified, information about the file's attribute fork is printed instead of the default data fork. .TP .B \-c If this option is specified, information about the file's copy on write fork is printed instead of the default data fork. .TP .B \-d If portions of the file have been migrated offline by a DMAPI application, a DMAPI read event will be generated to bring those portions back online before the disk block map is printed. However if the .B \-d option is used, no DMAPI read event will be generated for a DMAPI file and offline portions will be reported as holes. .TP .B \-e If this option is used, .B xfs_bmap obtains all delayed allocation extents, and does not flush dirty pages to disk before querying extent data. With the .B \-v option, the .I flags column will show which extents have not yet been allocated. .TP .B \-l If this option is used, then .IP .RS 1.2i .RI < nblocks "> blocks" .RE .IP will be appended to each line. .I nblocks is the length of the extent described on the line in units of 512-byte blocks. .IP This flag has no effect if the .B \-v option is used. .TP .BI \-n " num_extents" If this option is given, .B xfs_bmap obtains the extent list of the file in groups of .I num_extents extents. In the absence of .BR \-n ", " xfs_bmap queries the system for the number of extents in the file and uses that value to compute the group size. .TP .B \-p If this option is used, .B xfs_bmap obtains all unwritten (preallocated) extents that do not contain written data. With the .B \-v option, the .I flags column will show which extents are preallocated/unwritten. .TP .B \-v Shows verbose information. When this flag is specified, additional AG specific information is appended to each line in the following form: .IP .RS 1.2i .IR agno " (" startagoffset .. endagoffset ") " nblocks " " flags .RE .IP A second .B \-v option will print out the .I flags legend. .TP .B \-V Prints the version number and exits. .SH SEE ALSO .BR xfs_fsr (8), .BR xfs (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_copy.80000644000000000000000000001051513063067171016035 0ustar .TH xfs_copy 8 .SH NAME xfs_copy \- copy the contents of an XFS filesystem .SH SYNOPSIS .B xfs_copy [ .B \-bd ] [ .B \-L .I log ] .I source target1 [ .I target2 \&... ] .br .B xfs_copy \-V .SH DESCRIPTION .B xfs_copy copies an XFS filesystem to one or more targets in parallel (see .BR xfs (5)). The first .RI ( source ) argument must be the pathname of the device or file containing the XFS filesystem. The remaining arguments specify one or more .I target devices or file names. If the pathnames specify devices, a copy of the source XFS filesystem is created on each device. The .I target can also be the name of a regular file, in which case an image of the source XFS filesystem is created in that file. If the file does not exist, .B xfs_copy creates the file. The length of the resulting file is equal to the size of the source filesystem. However, if the file is created on an XFS filesystem, the file consumes roughly the amount of space actually used in the source filesystem by the filesystem and the XFS log. The space saving is because .B xfs_copy seeks over free blocks instead of copying them and the XFS filesystem supports sparse files efficiently. .PP .B xfs_copy should only be used to copy unmounted filesystems, read-only mounted filesystems, or frozen filesystems (see .BR xfs_freeze (8)). Otherwise, the generated filesystem(s) would be inconsistent or corrupt. .PP .B xfs_copy does not alter the source filesystem in any way. Each new (target) filesystem is identical to the original filesystem except that new filesystems each have a new unique filesystem identifier (UUID). Therefore, if both the old and new filesystems will be used as separate distinct filesystems, .B xfs_copy or .BR xfsdump (8)/ xfsrestore (8) should be used to generate the new filesystem(s) instead of .BR dd (1) or other programs that do block-by-block disk copying. .PP .B xfs_copy uses synchronous writes to ensure that write errors are detected. .PP .B xfs_copy uses .BR pthreads (7) to perform simultaneous parallel writes. .B xfs_copy creates one additional thread for each target to be written. All threads die if .B xfs_copy terminates or aborts. .SH OPTIONS .TP .B \-d Create a duplicate (true clone) filesystem. This should be done only if the new filesystem will be used as a replacement for the original filesystem (such as in the case of disk replacement). .TP .B \-b The buffered option can be used to ensure direct IO is not attempted to any of the target files. This is useful when the filesystem holding the target file does not support direct IO. .TP .BI \-L " log" Specifies the location of the .I log if the default location of .I /var/tmp/xfs_copy.log.XXXXXX is not desired. .TP .B \-V Prints the version number and exits. .SH DIAGNOSTICS .B xfs_copy reports errors to both .B stderr and in more detailed form to a generated log file whose name is of the form .I /var/tmp/xfs_copy.log.XXXXXX or a log file specified by the .B \-L option. If .B xfs_copy detects a write error on a target, the copy of that one target is aborted and an error message is issued to both stderr and the log file, but the rest of the copies continue. When .B xfs_copy terminates, all aborted targets are reported to both .B stderr and the log file. .PP If all targets abort or if there is an error reading the source filesystem, .B xfs_copy immediately aborts. .PP .B xfs_copy returns an exit code of 0 if all targets are successfully copied and an exit code of 1 if any target fails. .SH NOTES When moving filesystems from one disk to another, if the original filesystem is significantly smaller than the new filesystem, and will be made larger, we recommend that .BR mkfs.xfs "(8) and " xfsdump (8)/ xfsrestore (8) be used instead of using .B xfs_copy and .BR xfs_growfs (8). The filesystem layout resulting from using .BR xfs_copy / xfs_growfs is almost always worse than the result of using .BR mkfs.xfs / xfsdump / xfsrestore but in the case of small filesystems, the differences can have a significant performance impact. This is due to the way .BR xfs_growfs (8) works, and not due to any shortcoming in .B xfs_copy itself. .SH CAVEATS .B xfs_copy does not copy XFS filesystems that have a real-time section or XFS filesystems with external logs. In both cases, .B xfs_copy aborts with an error message. .SH SEE ALSO .BR mkfs.xfs (8), .BR xfsdump (8), .BR xfsrestore (8), .BR xfs_freeze (8), .BR xfs_growfs (8), .BR xfs (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_db.80000644000000000000000000014111613063067171015452 0ustar .TH xfs_db 8 .SH NAME xfs_db \- debug an XFS filesystem .SH SYNOPSIS .B xfs_db [ .B \-c .I cmd ] ... [ .BR \-i | r | x | F ] [ .B \-f ] [ .B \-l .I logdev ] [ .B \-p .I progname ] .I device .br .B xfs_db \-V .SH DESCRIPTION .B xfs_db is used to examine an XFS filesystem. Under rare circumstances it can also be used to modify an XFS filesystem, but that task is normally left to .BR xfs_repair (8) or to scripts such as .BR xfs_admin (8) that run .BR xfs_db . .PP .SH OPTIONS .TP .BI \-c " cmd" .B xfs_db commands may be run interactively (the default) or as arguments on the command line. Multiple .B \-c arguments may be given. The commands are run in the sequence given, then the program exits. .TP .B \-f Specifies that the filesystem image to be processed is stored in a regular file at .I device (see the .BR mkfs.xfs "(8) " -d .I file option). This might happen if an image copy of a filesystem has been made into an ordinary file with .BR xfs_copy (8). .TP .B \-F Specifies that we want to continue even if the superblock magic is not correct. For use in .BR xfs_metadump . .TP .B \-i Allows execution on a mounted filesystem, provided it is mounted read-only. Useful for shell scripts which must only operate on filesystems in a guaranteed consistent state (either unmounted or mounted read-only). These semantics are slightly different to that of the .B -r option. .TP .BI \-l " logdev" Specifies the device where the filesystems external log resides. Only for those filesystems which use an external log. See the .BR mkfs.xfs "(8) " \-l option, and refer to .BR xfs (5) for a detailed description of the XFS log. .TP .BI \-p " progname" Set the program name to .I progname for prompts and some error messages, the default value is .BR xfs_db . .TP .B -r Open .I device or .I filename read-only. This option is required if the filesystem is mounted. It is only necessary to omit this flag if a command that changes data .RB ( write ", " blocktrash ", " crc ) is to be used. .TP .B \-x Specifies expert mode. This enables the .RB ( write ", " blocktrash ", " crc invalidate/revalidate) commands. .TP .B \-V Prints the version number and exits. .SH CONCEPTS .B xfs_db commands can be broken up into two classes. Most commands are for the navigation and display of data structures in the filesystem. Other commands are for scanning the filesystem in some way. .PP Commands which are used to navigate the filesystem structure take arguments which reflect the names of filesystem structure fields. There can be multiple field names separated by dots when the underlying structures are nested, as in C. The field names can be indexed (as an array index) if the underlying field is an array. The array indices can be specified as a range, two numbers separated by a dash. .PP .B xfs_db maintains a current address in the filesystem. The granularity of the address is a filesystem structure. This can be a filesystem block, an inode or quota (smaller than a filesystem block), or a directory block (could be larger than a filesystem block). There are a variety of commands to set the current address. Associated with the current address is the current data type, which is the structural type of this data. Commands which follow the structure of the filesystem always set the type as well as the address. Commands which examine pieces of an individual file (inode) need the current inode to be set, this is done with the .B inode command. .PP The current address/type information is actually maintained in a stack that can be explicitly manipulated with the .BR push ", " pop ", and " stack commands. This allows for easy examination of a nested filesystem structure. Also, the last several locations visited are stored in a ring buffer which can be manipulated with the .BR forward ", " back ", and " ring commands. .PP XFS filesystems are divided into a small number of allocation groups. .B xfs_db maintains a notion of the current allocation group which is manipulated by some commands. The initial allocation group is 0. .SH COMMANDS .PP Many commands have extensive online help. Use the .B help command for more details on any command. .TP .B a See the .B addr command. .TP .BI ablock " filoff" Set current address to the offset .I filoff (a filesystem block number) in the attribute area of the current inode. .TP .BI "addr [" field-expression ] Set current address to the value of the .IR field-expression . This is used to "follow" a reference in one structure to the object being referred to. If no argument is given, the current address is printed. .TP .BI "agf [" agno ] Set current address to the AGF block for allocation group .IR agno . If no argument is given, use the current allocation group. .TP .BI "agfl [" agno ] Set current address to the AGFL block for allocation group .IR agno . If no argument is given, use the current allocation group. .TP .BI "agi [" agno ] Set current address to the AGI block for allocation group .IR agno . If no argument is given, use the current allocation group. .TP .B b See the .B back command. .TP .B back Move to the previous location in the position ring. .TP .B blockfree Free block usage information collected by the last execution of the .B blockget command. This must be done before another .B blockget command can be given, presumably with different arguments than the previous one. .TP .BI "blockget [\-npvs] [\-b " bno "] ... [\-i " ino "] ..." Get block usage and check filesystem consistency. The information is saved for use by a subsequent .BR blockuse ", " ncheck ", or " blocktrash command. .RS 1.0i .TP 0.4i .B \-b is used to specify filesystem block numbers about which verbose information should be printed. .TP .B \-i is used to specify inode numbers about which verbose information should be printed. .TP .B \-n is used to save pathnames for inodes visited, this is used to support the .BR xfs_ncheck (8) command. It also means that pathnames will be printed for inodes that have problems. This option uses a lot of memory so is not enabled by default. .TP .B \-p causes error messages to be prefixed with the filesystem name being processed. This is useful if several copies of .B xfs_db are run in parallel. .TP .B \-s restricts output to severe errors only. This is useful if the output is too long otherwise. .TP .B \-v enables verbose output. Messages will be printed for every block and inode processed. .RE .TP .BI "blocktrash [-z] [\-o " offset "] [\-n " count "] [\-x " min "] [\-y " max "] [\-s " seed "] [\-0|1|2|3] [\-t " type "] ..." Trash randomly selected filesystem metadata blocks. Trashing occurs to randomly selected bits in the chosen blocks. This command is available only in debugging versions of .BR xfs_db . It is useful for testing .BR xfs_repair "(8). .RS 1.0i .TP 0.4i .BR \-0 " | " -1 " | " -2 " | " -3 These are used to set the operating mode for .BR blocktrash . Only one can be used: .B \-0 changed bits are cleared; .B \-1 changed bits are set; .B -2 changed bits are inverted; .B -3 changed bits are randomized. .TP .B \-n supplies the .I count of block-trashings to perform (default 1). .TP .B \-o supplies the bit .I offset at which to start trashing the block. If the value is preceded by a '+', the trashing will start at a randomly chosen offset that is larger than the value supplied. The default is to randomly choose an offset anywhere in the block. .TP .B \-s supplies a .I seed to the random processing. .TP .B \-t gives a .I type of blocks to be selected for trashing. Multiple .B \-t options may be given. If no .B \-t options are given then all metadata types can be trashed. .TP .B \-x sets the .I minimum size of bit range to be trashed. The default value is 1. .TP .B \-y sets the .I maximum size of bit range to be trashed. The default value is 1024. .TP .B \-z trashes the block at the top of the stack. It is not necessary to run .BI blockget if this option is supplied. .RE .TP .BI "blockuse [\-n] [\-c " count ] Print usage for current filesystem block(s). For each block, the type and (if any) inode are printed. .RS 1.0i .TP 0.4i .B \-c specifies a .I count of blocks to process. The default value is 1 (the current block only). .TP .B \-n specifies that file names should be printed. The prior .B blockget command must have also specified the .B \-n option. .RE .TP .BI "bmap [\-a] [\-d] [" block " [" len ]] Show the block map for the current inode. The map display can be restricted to an area of the file with the .I block and .I len arguments. If .I block is given and .I len is omitted then 1 is assumed for len. .IP The .B \-a and .B \-d options are used to select the attribute or data area of the inode, if neither option is given then both areas are shown. .TP .B check See the .B blockget command. .TP .BI "convert " "type number" " [" "type number" "] ... " type Convert from one address form to another. The known .IR type s, with alternate names, are: .RS 1.0i .PD 0 .HP .B agblock or .B agbno (filesystem block within an allocation group) .HP .B agino or .B aginode (inode number within an allocation group) .HP .B agnumber or .B agno (allocation group number) .HP .B bboff or .B daddroff (byte offset in a .BR daddr ) .HP .B blkoff or .B fsboff or .B agboff (byte offset in a .B agblock or .BR fsblock ) .HP .B byte or .B fsbyte (byte address in filesystem) .HP .B daddr or .B bb (disk address, 512-byte blocks) .HP .B fsblock or .B fsb or .B fsbno (filesystem block, see the .B fsblock command) .HP .B ino or .B inode (inode number) .HP .B inoidx or .B offset (index of inode in filesystem block) .HP .B inooff or .B inodeoff (byte offset in inode) .PD .RE .IP Only conversions that "make sense" are allowed. The compound form (with more than three arguments) is useful for conversions such as .B convert agno .I ag .B agbno .I agb .BR fsblock . .TP .B crc [\-i|\-r|\-v] Invalidates, revalidates, or validates the CRC (checksum) field of the current structure, if it has one. This command is available only on CRC-enabled filesystems. With no argument, validation is performed. Each command will display the resulting CRC value and state. .RS 1.0i .TP 0.4i .B \-i Invalidate the structure's CRC value (incrementing it by one), and write it to disk. .TP .B \-r Recalculate the current structure's correct CRC value, and write it to disk. .TP .B \-v Validate and display the current value and state of the structure's CRC. .RE .TP .BI "daddr [" d ] Set current address to the daddr (512 byte block) given by .IR d . If no value for .I d is given, the current address is printed, expressed as a daddr. The type is set to .B data (uninterpreted). .TP .BI dblock " filoff" Set current address to the offset .I filoff (a filesystem block number) in the data area of the current inode. .TP .BI "debug [" flagbits ] Set debug option bits. These are used for debugging .BR xfs_db . If no value is given for .IR flagbits , print the current debug option bits. These are for the use of the implementor. .TP .BI "dquot [" \-g | \-p | \-u ] " id" Set current address to a group, project or user quota block for the given ID. Defaults to user quota. .TP .BI "echo [" arg "] ..." Echo the arguments to the output. .TP .B f See the .B forward command. .TP .B forward Move forward to the next entry in the position ring. .TP .B frag [\-adflqRrv] Get file fragmentation data. This prints information about fragmentation of file data in the filesystem (as opposed to fragmentation of freespace, for which see the .B freesp command). Every file in the filesystem is examined to see how far from ideal its extent mappings are. A summary is printed giving the totals. .RS 1.0i .TP 0.4i .B \-v sets verbosity, every inode has information printed for it. The remaining options select which inodes and extents are examined. If no options are given then all are assumed set, otherwise just those given are enabled. .TP .B \-a enables processing of attribute data. .TP .B \-d enables processing of directory data. .TP .B \-f enables processing of regular file data. .TP .B \-l enables processing of symbolic link data. .TP .B \-q enables processing of quota file data. .TP .B \-R enables processing of realtime control file data. .TP .B \-r enables processing of realtime file data. .RE .TP .BI "freesp [\-bcds] [\-a " ag "] ... [\-e " i "] [\-h " h1 "] ... [\-m " m ] Summarize free space for the filesystem. The free blocks are examined and totalled, and displayed in the form of a histogram, with a count of extents in each range of free extent sizes. .RS 1.0i .TP 0.4i .B \-a adds .I ag to the list of allocation groups to be processed. If no .B \-a options are given then all allocation groups are processed. .TP .B \-b specifies that the histogram buckets are binary-sized, with the starting sizes being the powers of 2. .TP .B \-c specifies that .B freesp will search the by-size (cnt) space Btree instead of the default by-block (bno) space Btree. .TP .B \-d specifies that every free extent will be displayed. .TP .B \-e specifies that the histogram buckets are equal-sized, with the size specified as .IR i . .TP .B \-h specifies a starting block number for a histogram bucket as .IR h1 . Multiple .BR \-h 's are given to specify the complete set of buckets. .TP .B \-m specifies that the histogram starting block numbers are powers of .IR m . This is the general case of .BR \-b . .TP .B \-s specifies that a final summary of total free extents, free blocks, and the average free extent size is printed. .RE .TP .B fsb See the .B fsblock command. .TP .BI "fsblock [" fsb ] Set current address to the fsblock value given by .IR fsb . If no value for .I fsb is given the current address is printed, expressed as an fsb. The type is set to .B data (uninterpreted). XFS filesystem block numbers are computed .RI (( agno " << " agshift ") | " agblock ) where .I agshift depends on the size of an allocation group. Use the .B convert command to convert to and from this form. Block numbers given for file blocks (for instance from the .B bmap command) are in this form. .TP .BI "fsmap [ " start " ] [ " end " ] Prints the mapping of disk blocks used by an XFS filesystem. The map lists each extent used by files, allocation group metadata, journalling logs, and static filesystem metadata, as well as any regions that are unused. All blocks, offsets, and lengths are specified in units of 512-byte blocks, no matter what the filesystem's block size is. .BI "The optional " start " and " end " arguments can be used to constrain the output to a particular range of disk blocks. .TP .BI hash " string Prints the hash value of .I string using the hash function of the XFS directory and attribute implementation. .TP .BI "help [" command ] Print help for one or all commands. .TP .BI "inode [" inode# ] Set the current inode number. If no .I inode# is given, print the current inode number. .TP .BI "label [" label ] Set the filesystem label. The filesystem label can be used by .BR mount (8) instead of using a device special file. The maximum length of an XFS label is 12 characters \- use of a longer .I label will result in truncation and a warning will be issued. If no .I label is given, the current filesystem label is printed. .TP .BI "log [stop | start " filename ] Start logging output to .IR filename , stop logging, or print the current logging status. .TP .BI "metadump [\-egow] " filename Dumps metadata to a file. See .BR xfs_metadump (8) for more information. .TP .BI "ncheck [\-s] [\-i " ino "] ..." Print name-inode pairs. A .B blockget \-n command must be run first to gather the information. .RS 1.0i .TP 0.4i .B \-i specifies an inode number to be printed. If no .B \-i options are given then all inodes are printed. .TP .B \-s specifies that only setuid and setgid files are printed. .RE .TP .B p See the .B print command. .TP .B pop Pop location from the stack. .TP .BI "print [" field-expression "] ..." Print field values. If no argument is given, print all fields in the current structure. .TP .BI "push [" command ] Push location to the stack. If .I command is supplied, set the current location to the results of .I command after pushing the old location. .TP .B q See the .B quit command. .TP .B quit Exit .BR xfs_db . .TP .BI "ring [" index ] Show position ring (if no .I index argument is given), or move to a specific entry in the position ring given by .IR index . .TP .BI "sb [" agno ] Set current address to SB header in allocation group .IR agno . If no .I agno is given, use the current allocation group number. .TP .BI "source " source-file Process commands from .IR source-file . .B source commands can be nested. .TP .B stack View the location stack. .TP .BI "type [" type ] Set the current data type to .IR type . If no argument is given, show the current data type. The possible data types are: .BR agf ", " agfl ", " agi ", " attr ", " bmapbta ", " bmapbtd , .BR bnobt ", " cntbt ", " data ", " dir ", " dir2 ", " dqblk , .BR inobt ", " inode ", " log ", " refcntbt ", " rmapbt ", " rtbitmap , .BR rtsummary ", " sb ", " symlink " and " text . See the TYPES section below for more information on these data types. .TP .BI "uuid [" uuid " | " generate " | " rewrite " | " restore ] Set the filesystem universally unique identifier (UUID). The filesystem UUID can be used by .BR mount (8) instead of using a device special file. The .I uuid can be set directly to the desired UUID, or it can be automatically generated using the .B generate option. These options will both write the UUID into every copy of the superblock in the filesystem. On a CRC-enabled filesystem, this will set an incompatible superblock flag, and the filesystem will not be mountable with older kernels. This can be reverted with the .B restore option, which will copy the original UUID back into place and clear the incompatible flag as needed. .B rewrite copies the current UUID from the primary superblock to all secondary copies of the superblock. If no argument is given, the current filesystem UUID is printed. .TP .BI "version [" feature " | " "versionnum features2" ] Enable selected features for a filesystem (certain features can be enabled on an unmounted filesystem, after .BR mkfs.xfs (8) has created the filesystem). Support for unwritten extents can be enabled using the .B extflg option. Support for version 2 log format can be enabled using the .B log2 option. Support for extended attributes can be enabled using the .B attr1 or .B attr2 option. Once enabled, extended attributes cannot be disabled, but the user may toggle between .B attr1 and .B attr2 at will (older kernels may not support the newer version). .IP If no argument is given, the current version and feature bits are printed. With one argument, this command will write the updated version number into every copy of the superblock in the filesystem. If two arguments are given, they will be used as numeric values for the .I versionnum and .I features2 bits respectively, and their string equivalent reported (but no modifications are made). .TP .BI "write [\-c] [" "field value" "] ..." Write a value to disk. Specific fields can be set in structures (struct mode), or a block can be set to data values (data mode), or a block can be set to string values (string mode, for symlink blocks). The operation happens immediately: there is no buffering. .IP Struct mode is in effect when the current type is structural, i.e. not data. For struct mode, the syntax is "\c .B write .I field value\c ". .IP Data mode is in effect when the current type is data. In this case the contents of the block can be shifted or rotated left or right, or filled with a sequence, a constant value, or a random value. In this mode .B write with no arguments gives more information on the allowed commands. .RS 1.0i .TP 0.4i .B \-c Skip write verifiers and CRC recalculation; allows invalid data to be written to disk. .RE .SH TYPES This section gives the fields in each structure type and their meanings. Note that some types of block cover multiple actual structures, for instance directory blocks. .TP 1.0i .B agf The AGF block is the header for block allocation information; it is in the second 512-byte block of each allocation group. The following fields are defined: .RS 1.4i .PD 0 .TP 1.2i .B magicnum AGF block magic number, 0x58414746 ('XAGF'). .TP .B versionnum version number, currently 1. .TP .B seqno sequence number starting from 0. .TP .B length size in filesystem blocks of the allocation group. All allocation groups except the last one of the filesystem have the superblock's .B agblocks value here. .TP .B bnoroot block number of the root of the Btree holding free space information sorted by block number. .TP .B cntroot block number of the root of the Btree holding free space information sorted by block count. .TP .B bnolevel number of levels in the by-block-number Btree. .TP .B cntlevel number of levels in the by-block-count Btree. .TP .B flfirst index into the AGFL block of the first active entry. .TP .B fllast index into the AGFL block of the last active entry. .TP .B flcount count of active entries in the AGFL block. .TP .B freeblks count of blocks represented in the freespace Btrees. .TP .B longest longest free space represented in the freespace Btrees. .TP .B btreeblks number of blocks held in the AGF Btrees. .PD .RE .TP .B agfl The AGFL block contains block numbers for use of the block allocator; it is in the fourth 512-byte block of each allocation group. Each entry in the active list is a block number within the allocation group that can be used for any purpose if space runs low. The AGF block fields .BR flfirst ", " fllast ", and " flcount designate which entries are currently active. Entry space is allocated in a circular manner within the AGFL block. Fields defined: .RS 1.4i .PD 0 .TP 1.2i .B bno array of all block numbers. Even those which are not active are printed. .PD .RE .TP .B agi The AGI block is the header for inode allocation information; it is in the third 512-byte block of each allocation group. Fields defined: .RS 1.4i .PD 0 .TP 1.2i .B magicnum AGI block magic number, 0x58414749 ('XAGI'). .TP .B versionnum version number, currently 1. .TP .B seqno sequence number starting from 0. .TP .B length size in filesystem blocks of the allocation group. .TP .B count count of inodes allocated. .TP .B root block number of the root of the Btree holding inode allocation information. .TP .B level number of levels in the inode allocation Btree. .TP .B freecount count of allocated inodes that are not in use. .TP .B newino last inode number allocated. .TP .B dirino unused. .TP .B unlinked an array of inode numbers within the allocation group. The entries in the AGI block are the heads of lists which run through the inode .B next_unlinked field. These inodes are to be unlinked the next time the filesystem is mounted. .PD .RE .TP .B attr An attribute fork is organized as a Btree with the actual data embedded in the leaf blocks. The root of the Btree is found in block 0 of the fork. The index (sort order) of the Btree is the hash value of the attribute name. All the blocks contain a .B blkinfo structure at the beginning, see type .B dir for a description. Nonleaf blocks are identical in format to those for version 1 and version 2 directories, see type .B dir for a description. Leaf blocks can refer to "local" or "remote" attribute values. Local values are stored directly in the leaf block. Remote values are stored in an independent block in the attribute fork (with no structure). Leaf blocks contain the following fields: .RS 1.4i .PD 0 .TP 1.2i .B hdr header containing a .B blkinfo structure .B info (magic number 0xfbee), a .B count of active entries, .B usedbytes total bytes of names and values, the .B firstused byte in the name area, .B holes set if the block needs compaction, and array .B freemap as for .B dir leaf blocks. .TP .B entries array of structures containing a .BR hashval , .B nameidx (index into the block of the name), and flags .BR incomplete , .BR root , and .BR local . .TP .B nvlist array of structures describing the attribute names and values. Fields always present: .B valuelen (length of value in bytes), .BR namelen , and .BR name . Fields present for local values: .B value (value string). Fields present for remote values: .B valueblk (fork block number of containing the value). .PD .RE .TP .B bmapbt Files with many extents in their data or attribute fork will have the extents described by the contents of a Btree for that fork, instead of being stored directly in the inode. Each bmap Btree starts with a root block contained within the inode. The other levels of the Btree are stored in filesystem blocks. The blocks are linked to sibling left and right blocks at each level, as well as by pointers from parent to child blocks. Each block contains the following fields: .RS 1.4i .PD 0 .TP 1.2i .B magic bmap Btree block magic number, 0x424d4150 ('BMAP'). .TP .B level level of this block above the leaf level. .TP .B numrecs number of records or keys in the block. .TP .B leftsib left (logically lower) sibling block, 0 if none. .TP .B rightsib right (logically higher) sibling block, 0 if none. .TP .B recs [leaf blocks only] array of extent records. Each record contains .BR startoff , .BR startblock , .BR blockcount , and .B extentflag (1 if the extent is unwritten). .TP .B keys [non-leaf blocks only] array of key records. These are the first key value of each block in the level below this one. Each record contains .BR startoff . .TP .B ptrs [non-leaf blocks only] array of child block pointers. Each pointer is a filesystem block number to the next level in the Btree. .PD .RE .TP .B bnobt There is one set of filesystem blocks forming the by-block-number allocation Btree for each allocation group. The root block of this Btree is designated by the .B bnoroot field in the corresponding AGF block. The blocks are linked to sibling left and right blocks at each level, as well as by pointers from parent to child blocks. Each block has the following fields: .RS 1.4i .PD 0 .TP 1.2i .B magic BNOBT block magic number, 0x41425442 ('ABTB'). .TP .B level level number of this block, 0 is a leaf. .TP .B numrecs number of data entries in the block. .TP .B leftsib left (logically lower) sibling block, 0 if none. .TP .B rightsib right (logically higher) sibling block, 0 if none. .TP .B recs [leaf blocks only] array of freespace records. Each record contains .B startblock and .BR blockcount . .TP .B keys [non-leaf blocks only] array of key records. These are the first value of each block in the level below this one. Each record contains .B startblock and .BR blockcount . .TP .B ptrs [non-leaf blocks only] array of child block pointers. Each pointer is a block number within the allocation group to the next level in the Btree. .PD .RE .TP .B cntbt There is one set of filesystem blocks forming the by-block-count allocation Btree for each allocation group. The root block of this Btree is designated by the .B cntroot field in the corresponding AGF block. The blocks are linked to sibling left and right blocks at each level, as well as by pointers from parent to child blocks. Each block has the following fields: .RS 1.4i .PD 0 .TP 1.2i .B magic CNTBT block magic number, 0x41425443 ('ABTC'). .TP .B level level number of this block, 0 is a leaf. .TP .B numrecs number of data entries in the block. .TP .B leftsib left (logically lower) sibling block, 0 if none. .TP .B rightsib right (logically higher) sibling block, 0 if none. .TP .B recs [leaf blocks only] array of freespace records. Each record contains .B startblock and .BR blockcount . .TP .B keys [non-leaf blocks only] array of key records. These are the first value of each block in the level below this one. Each record contains .B blockcount and .BR startblock . .TP .B ptrs [non-leaf blocks only] array of child block pointers. Each pointer is a block number within the allocation group to the next level in the Btree. .PD .RE .TP .B data User file blocks, and other blocks whose type is unknown, have this type for display purposes in .BR xfs_db . The block data is displayed in hexadecimal format. .TP .B dir A version 1 directory is organized as a Btree with the directory data embedded in the leaf blocks. The root of the Btree is found in block 0 of the file. The index (sort order) of the Btree is the hash value of the entry name. All the blocks contain a .B blkinfo structure at the beginning with the following fields: .RS 1.4i .PD 0 .TP 1.2i .B forw next sibling block. .TP .B back previous sibling block. .TP .B magic magic number for this block type. .RE .IP The non-leaf (node) blocks have the following fields: .RS 1.4i .TP 1.2i .B hdr header containing a .B blkinfo structure .B info (magic number 0xfebe), the .B count of active entries, and the .B level of this block above the leaves. .TP .B btree array of entries containing .B hashval and .B before fields. The .B before value is a block number within the directory file to the child block, the .B hashval is the last hash value in that block. .RE .IP The leaf blocks have the following fields: .RS 1.4i .TP 1.2i .B hdr header containing a .B blkinfo structure .B info (magic number 0xfeeb), the .B count of active entries, .B namebytes (total name string bytes), .B holes flag (block needs compaction), and .B freemap (array of .BR base ", " size entries for free regions). .TP .B entries array of structures containing .BR hashval , .B nameidx (byte index into the block of the name string), and .BR namelen . .TP .B namelist array of structures containing .B inumber and .BR name . .RE .PD .TP .B dir2 A version 2 directory has four kinds of blocks. Data blocks start at offset 0 in the file. There are two kinds of data blocks: single-block directories have the leaf information embedded at the end of the block, data blocks in multi-block directories do not. Node and leaf blocks start at offset 32GiB (with either a single leaf block or the root node block). Freespace blocks start at offset 64GiB. The node and leaf blocks form a Btree, with references to the data in the data blocks. The freespace blocks form an index of longest free spaces within the data blocks. .IP A single-block directory block contains the following fields: .RS 1.4i .PD 0 .TP 1.2i .B bhdr header containing .B magic number 0x58443242 ('XD2B') and an array .B bestfree of the longest 3 free spaces in the block .RB ( offset ", " length ). .TP .B bu array of union structures. Each element is either an entry or a freespace. For entries, there are the following fields: .BR inumber , .BR namelen , .BR name , and .BR tag . For freespace, there are the following fields: .B freetag (0xffff), .BR length , and .BR tag . The .B tag value is the byte offset in the block of the start of the entry it is contained in. .TP .B bleaf array of leaf entries containing .B hashval and .BR address . The .B address is a 64-bit word offset into the file. .TP .B btail tail structure containing the total .B count of leaf entries and .B stale count of unused leaf entries. .RE .IP A data block contains the following fields: .RS 1.4i .TP 1.2i .B dhdr header containing .B magic number 0x58443244 ('XD2D') and an array .B bestfree of the longest 3 free spaces in the block .RB ( offset ", " length ). .TP .B du array of union structures as for .BR bu . .RE .IP Leaf blocks have two possible forms. If the Btree consists of a single leaf then the freespace information is in the leaf block, otherwise it is in separate blocks and the root of the Btree is a node block. A leaf block contains the following fields: .RS 1.4i .TP 1.2i .B lhdr header containing a .B blkinfo structure .B info (magic number 0xd2f1 for the single leaf case, 0xd2ff for the true Btree case), the total .B count of leaf entries, and .B stale count of unused leaf entries. .TP .B lents leaf entries, as for .BR bleaf . .TP .B lbests [single leaf only] array of values which represent the longest freespace in each data block in the directory. .TP .B ltail [single leaf only] tail structure containing .B bestcount count of .BR lbests . .RE .IP A node block is identical to that for types .B attr and .BR dir . A freespace block contains the following fields: .RS 1.4i .TP 1.2i .B fhdr header containing .B magic number 0x58443246 ('XD2F'), .B firstdb first data block number covered by this freespace block, .B nvalid number of valid entries, and .B nused number of entries representing real data blocks. .TP .B fbests array of values as for .BR lbests . .PD .RE .TP .B dqblk The quota information is stored in files referred to by the superblock .B uquotino and .B pquotino fields. Each filesystem block in a quota file contains a constant number of quota entries. The quota entry size is currently 136 bytes, so with a 4KiB filesystem block size there are 30 quota entries per block. The .B dquot command is used to locate these entries in the filesystem. The file entries are indexed by the user or project identifier to determine the block and offset. Each quota entry has the following fields: .RS 1.4i .PD 0 .TP 1.5i .B magic magic number, 0x4451 ('DQ'). .TP .B version version number, currently 1. .TP .B flags flags, values include 0x01 for user quota, 0x02 for project quota. .TP .B id user or project identifier. .TP .B blk_hardlimit absolute limit on blocks in use. .TP .B blk_softlimit preferred limit on blocks in use. .TP .B ino_hardlimit absolute limit on inodes in use. .TP .B ino_softlimit preferred limit on inodes in use. .TP .B bcount blocks actually in use. .TP .B icount inodes actually in use. .TP .B itimer time when service will be refused if soft limit is violated for inodes. .TP .B btimer time when service will be refused if soft limit is violated for blocks. .TP .B iwarns number of warnings issued about inode limit violations. .TP .B bwarns number of warnings issued about block limit violations. .TP .B rtb_hardlimit absolute limit on realtime blocks in use. .TP .B rtb_softlimit preferred limit on realtime blocks in use. .TP .B rtbcount realtime blocks actually in use. .TP .B rtbtimer time when service will be refused if soft limit is violated for realtime blocks. .TP .B rtbwarns number of warnings issued about realtime block limit violations. .PD .RE .TP .B inobt There is one set of filesystem blocks forming the inode allocation Btree for each allocation group. The root block of this Btree is designated by the .B root field in the corresponding AGI block. The blocks are linked to sibling left and right blocks at each level, as well as by pointers from parent to child blocks. Each block has the following fields: .RS 1.4i .PD 0 .TP 1.2i .B magic INOBT block magic number, 0x49414254 ('IABT'). .TP .B level level number of this block, 0 is a leaf. .TP .B numrecs number of data entries in the block. .TP .B leftsib left (logically lower) sibling block, 0 if none. .TP .B rightsib right (logically higher) sibling block, 0 if none. .TP .B recs [leaf blocks only] array of inode records. Each record contains .B startino allocation-group relative inode number, .B freecount count of free inodes in this chunk, and .B free bitmap, LSB corresponds to inode 0. .TP .B keys [non-leaf blocks only] array of key records. These are the first value of each block in the level below this one. Each record contains .BR startino . .TP .B ptrs [non-leaf blocks only] array of child block pointers. Each pointer is a block number within the allocation group to the next level in the Btree. .PD .RE .TP .B inode Inodes are allocated in "chunks" of 64 inodes each. Usually a chunk is multiple filesystem blocks, although there are cases with large filesystem blocks where a chunk is less than one block. The inode Btree (see .B inobt above) refers to the inode numbers per allocation group. The inode numbers directly reflect the location of the inode block on disk. Use the .B inode command to point .B xfs_db to a specific inode. Each inode contains four regions: .BR core , .BR next_unlinked , .BR u ", and " .BR a . .B core contains the fixed information. .B next_unlinked is separated from the core due to journaling considerations, see type .B agi field .BR unlinked . .B u is a union structure that is different in size and format depending on the type and representation of the file data ("data fork"). .B a is an optional union structure to describe attribute data, that is different in size, format, and location depending on the presence and representation of attribute data, and the size of the .B u data ("attribute fork"). .B xfs_db automatically selects the proper union members based on information in the inode. .IP The following are fields in the inode core: .RS 1.4i .PD 0 .TP 1.2i .B magic inode magic number, 0x494e ('IN'). .TP .B mode mode and type of file, as described in .BR chmod (2), .BR mknod (2), and .BR stat (2). .TP .B version inode version, 1 or 2. .TP .B format format of .B u union data (0: xfs_dev_t, 1: local file \- in-inode directory or symlink, 2: extent list, 3: Btree root, 4: unique id [unused]). .TP .B nlinkv1 number of links to the file in a version 1 inode. .TP .B nlinkv2 number of links to the file in a version 2 inode. .TP .B projid_lo owner's project id (low word; version 2 inode only). .B projid_hi owner's project id (high word; version 2 inode only). .TP .B uid owner's user id. .TP .B gid owner's group id. .TP .B atime time last accessed (seconds and nanoseconds). .TP .B mtime time last modified. .TP .B ctime time created or inode last modified. .TP .B size number of bytes in the file. .TP .B nblocks total number of blocks in the file including indirect and attribute. .TP .B extsize basic/minimum extent size for the file. .TP .B nextents number of extents in the data fork. .TP .B naextents number of extents in the attribute fork. .TP .B forkoff attribute fork offset in the inode, in 64-bit words from the start of .BR u . .TP .B aformat format of .B a data (1: local attribute data, 2: extent list, 3: Btree root). .TP .B dmevmask DMAPI event mask. .TP .B dmstate DMAPI state information. .TP .B newrtbm file is the realtime bitmap and is "new" format. .TP .B prealloc file has preallocated data space after EOF. .TP .B realtime file data is in the realtime subvolume. .TP .B gen inode generation number. .RE .IP The following fields are in the .B u data fork union: .RS 1.4i .TP 1.2i .B bmbt bmap Btree root. This looks like a .B bmapbtd block with redundant information removed. .TP .B bmx array of extent descriptors. .TP .B dev dev_t for the block or character device. .TP .B sfdir shortform (in-inode) version 1 directory. This consists of a .B hdr containing the .B parent inode number and a .B count of active entries in the directory, followed by an array .B list of .B hdr.count entries. Each such entry contains .BR inumber , .BR namelen , and .B name string. .TP .B sfdir2 shortform (in-inode) version 2 directory. This consists of a .B hdr containing a .B count of active entries in the directory, an .B i8count of entries with inumbers that don't fit in a 32-bit value, and the .B parent inode number, followed by an array .B list of .B hdr.count entries. Each such entry contains .BR namelen , a saved .B offset used when the directory is converted to a larger form, a .B name string, and the .BR inumber . .TP .B symlink symbolic link string value. .RE .IP The following fields are in the .B a attribute fork union if it exists: .RS 1.4i .TP 1.2i .B bmbt bmap Btree root, as above. .TP .B bmx array of extent descriptors. .TP .B sfattr shortform (in-inode) attribute values. This consists of a .B hdr containing a .B totsize (total size in bytes) and a .B count of active entries, followed by an array .B list of .B hdr.count entries. Each such entry contains .BR namelen , .BR valuelen , .BR root flag, .BR name , and .BR value . .PD .RE .TP .B log Log blocks contain the journal entries for XFS. It's not useful to examine these with .BR xfs_db , use .BR xfs_logprint (8) instead. .TP .B refcntbt There is one set of filesystem blocks forming the reference count Btree for each allocation group. The root block of this Btree is designated by the .B refcntroot field in the corresponding AGF block. The blocks are linked to sibling left and right blocks at each level, as well as by pointers from parent to child blocks. Each block has the following fields: .RS 1.4i .PD 0 .TP 1.2i .B magic REFC block magic number, 0x52334643 ('R3FC'). .TP .B level level number of this block, 0 is a leaf. .TP .B numrecs number of data entries in the block. .TP .B leftsib left (logically lower) sibling block, 0 if none. .TP .B rightsib right (logically higher) sibling block, 0 if none. .TP .B recs [leaf blocks only] array of reference count records. Each record contains .BR startblock , .BR blockcount , and .BR refcount . .TP .B keys [non-leaf blocks only] array of key records. These are the first value of each block in the level below this one. Each record contains .BR startblock . .TP .B ptrs [non-leaf blocks only] array of child block pointers. Each pointer is a block number within the allocation group to the next level in the Btree. .PD .RE .TP .B rmapbt There is one set of filesystem blocks forming the reverse mapping Btree for each allocation group. The root block of this Btree is designated by the .B rmaproot field in the corresponding AGF block. The blocks are linked to sibling left and right blocks at each level, as well as by pointers from parent to child blocks. Each block has the following fields: .RS 1.4i .PD 0 .TP 1.2i .B magic RMAP block magic number, 0x524d4233 ('RMB3'). .TP .B level level number of this block, 0 is a leaf. .TP .B numrecs number of data entries in the block. .TP .B leftsib left (logically lower) sibling block, 0 if none. .TP .B rightsib right (logically higher) sibling block, 0 if none. .TP .B recs [leaf blocks only] array of reference count records. Each record contains .BR startblock , .BR blockcount , .BR owner , .BR offset , .BR attr_fork , .BR bmbt_block , and .BR unwritten . .TP .B keys [non-leaf blocks only] array of double-key records. The first ("low") key contains the first value of each block in the level below this one. The second ("high") key contains the largest key that can be used to identify any record in the subtree. Each record contains .BR startblock , .BR owner , .BR offset , .BR attr_fork , and .BR bmbt_block . .TP .B ptrs [non-leaf blocks only] array of child block pointers. Each pointer is a block number within the allocation group to the next level in the Btree. .PD .RE .TP .B rtbitmap If the filesystem has a realtime subvolume, then the .B rbmino field in the superblock refers to a file that contains the realtime bitmap. Each bit in the bitmap file controls the allocation of a single realtime extent (set == free). The bitmap is processed in 32-bit words, the LSB of a word is used for the first extent controlled by that bitmap word. The .B atime field of the realtime bitmap inode contains a counter that is used to control where the next new realtime file will start. .TP .B rtsummary If the filesystem has a realtime subvolume, then the .B rsumino field in the superblock refers to a file that contains the realtime summary data. The summary file contains a two-dimensional array of 16-bit values. Each value counts the number of free extent runs (consecutive free realtime extents) of a given range of sizes that starts in a given bitmap block. The size ranges are binary buckets (low size in the bucket is a power of 2). There are as many size ranges as are necessary given the size of the realtime subvolume. The first dimension is the size range, the second dimension is the starting bitmap block number (adjacent entries are for the same size, adjacent bitmap blocks). .TP .B sb There is one sb (superblock) structure per allocation group. It is the first disk block in the allocation group. Only the first one (block 0 of the filesystem) is actually used; the other blocks are redundant information for .BR xfs_repair (8) to use if the first superblock is damaged. Fields defined: .RS 1.4i .PD 0 .TP 1.2i .B magicnum superblock magic number, 0x58465342 ('XFSB'). .TP .B blocksize filesystem block size in bytes. .TP .B dblocks number of filesystem blocks present in the data subvolume. .TP .B rblocks number of filesystem blocks present in the realtime subvolume. .TP .B rextents number of realtime extents that .B rblocks contain. .TP .B uuid unique identifier of the filesystem. .TP .B logstart starting filesystem block number of the log (journal). If this value is 0 the log is "external". .TP .B rootino root inode number. .TP .B rbmino realtime bitmap inode number. .TP .B rsumino realtime summary data inode number. .TP .B rextsize realtime extent size in filesystem blocks. .TP .B agblocks size of an allocation group in filesystem blocks. .TP .B agcount number of allocation groups. .TP .B rbmblocks number of realtime bitmap blocks. .TP .B logblocks number of log blocks (filesystem blocks). .TP .B versionnum filesystem version information. This value is currently 1, 2, 3, or 4 in the low 4 bits. If the low bits are 4 then the other bits have additional meanings. 1 is the original value. 2 means that attributes were used. 3 means that version 2 inodes (large link counts) were used. 4 is the bitmask version of the version number. In this case, the other bits are used as flags (0x0010: attributes were used, 0x0020: version 2 inodes were used, 0x0040: quotas were used, 0x0080: inode cluster alignment is in force, 0x0100: data stripe alignment is in force, 0x0200: the .B shared_vn field is used, 0x1000: unwritten extent tracking is on, 0x2000: version 2 directories are in use). .TP .B sectsize sector size in bytes, currently always 512. This is the size of the superblock and the other header blocks. .TP .B inodesize inode size in bytes. .TP .B inopblock number of inodes per filesystem block. .TP .B fname obsolete, filesystem name. .TP .B fpack obsolete, filesystem pack name. .TP .B blocklog log2 of .BR blocksize . .TP .B sectlog log2 of .BR sectsize . .TP .B inodelog log2 of .BR inodesize . .TP .B inopblog log2 of .BR inopblock . .TP .B agblklog log2 of .B agblocks (rounded up). .TP .B rextslog log2 of .BR rextents . .TP .B inprogress .BR mkfs.xfs (8) or .BR xfs_copy (8) aborted before completing this filesystem. .TP .B imax_pct maximum percentage of filesystem space used for inode blocks. .TP .B icount number of allocated inodes. .TP .B ifree number of allocated inodes that are not in use. .TP .B fdblocks number of free data blocks. .TP .B frextents number of free realtime extents. .TP .B uquotino user quota inode number. .TP .B pquotino project quota inode number; this is currently unused. .TP .B qflags quota status flags (0x01: user quota accounting is on, 0x02: user quota limits are enforced, 0x04: quotacheck has been run on user quotas, 0x08: project quota accounting is on, 0x10: project quota limits are enforced, 0x20: quotacheck has been run on project quotas). .TP .B flags random flags. 0x01: only read-only mounts are allowed. .TP .B shared_vn shared version number (shared readonly filesystems). .TP .B inoalignmt inode chunk alignment in filesystem blocks. .TP .B unit stripe or RAID unit. .TP .B width stripe or RAID width. .TP .B dirblklog log2 of directory block size (filesystem blocks). .PD .RE .TP .B symlink Symbolic link blocks are used only when the symbolic link value does not fit inside the inode. The block content is just the string value. Bytes past the logical end of the symbolic link value have arbitrary values. .TP .B text User file blocks, and other blocks whose type is unknown, have this type for display purposes in .BR xfs_db . The block data is displayed in two columns: Hexadecimal format and printable ASCII chars. .SH DIAGNOSTICS Many messages can come from the .B check .RB ( blockget ) command. If the filesystem is completely corrupt, a core dump might be produced instead of the message .RS .I device .B is not a valid filesystem .RE .PP If the filesystem is very large (has many files) then .B check might run out of memory. In this case the message .RS .B out of memory .RE is printed. .PP The following is a description of the most likely problems and the associated messages. Most of the diagnostics produced are only meaningful with an understanding of the structure of the filesystem. .TP .BI "agf_freeblks " n ", counted " m " in ag " a The freeblocks count in the allocation group header for allocation group .I a doesn't match the number of blocks counted free. .TP .BI "agf_longest " n ", counted " m " in ag " a The longest free extent in the allocation group header for allocation group .I a doesn't match the longest free extent found in the allocation group. .TP .BI "agi_count " n ", counted " m " in ag " a The allocated inode count in the allocation group header for allocation group .I a doesn't match the number of inodes counted in the allocation group. .TP .BI "agi_freecount " n ", counted " m " in ag " a The free inode count in the allocation group header for allocation group .I a doesn't match the number of inodes counted free in the allocation group. .TP .BI "block " a/b " expected inum 0 got " i The block number is specified as a pair (allocation group number, block in the allocation group). The block is used multiple times (shared), between multiple inodes. This message usually follows a message of the next type. .TP .BI "block " a/b " expected type unknown got " y The block is used multiple times (shared). .TP .BI "block " a/b " type unknown not expected .SH SEE ALSO .BR mkfs.xfs (8), .BR xfs_admin (8), .BR xfs_copy (8), .BR xfs_logprint (8), .BR xfs_metadump (8), .BR xfs_ncheck (8), .BR xfs_repair (8), .BR mount (8), .BR chmod (2), .BR mknod (2), .BR stat (2), .BR xfs (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_estimate.80000644000000000000000000000430113063067171016672 0ustar .TH xfs_estimate 8 .SH NAME xfs_estimate \- estimate the space that an XFS filesystem will take .SH SYNOPSIS .nf \f3xfs_estimate\f1 [ \f3\-h\f1 ] [ \f3\-b\f1 blocksize ] [ \f3\-i\f1 logsize ] [ \f3\-e\f1 logsize ] [ \f3\-v\f1 ] directory ... .br .B xfs_estimate \-V .fi .SH DESCRIPTION For each \f2directory\f1 argument, .I xfs_estimate estimates the space that directory would take if it were copied to an XFS filesystem. .I xfs_estimate does not cross mount points. The following definitions are used: .PD 0 .IP KB = *1024 .IP MB = *1024*1024 .IP GB = *1024*1024*1024 .PD .PP The .I xfs_estimate options are: .TP \f3\-b\f1 \f2blocksize\f1 Use .I blocksize instead of the default blocksize of 4096 bytes. The modifier .B k can be used after the number to indicate multiplication by 1024. For example, .sp .8v .RS \f4xfs_estimate \-b 64k /\f1 .RE .IP requests an estimate of the space required by the directory / on an XFS filesystem using a blocksize of 64K (65536) bytes. .TP .B \-v Display more information, formatted. .TP .B \-h Display usage message. .TP \f3\-i, \-e\f1 \f2logsize\f1 Use .I logsize instead of the default log size of 1000 blocks. .B \-i refers to an internal log, while .B \-e refers to an external log. The modifiers .B k or .B m can be used after the number to indicate multiplication by 1024 or 1048576, respectively. .IP For example, .sp .8v .RS \f4xfs_estimate \-i 1m /\f1 .RE .IP requests an estimate of the space required by the directory / on an XFS filesystem using an internal log of 1 megabyte. .TP .B \-V Print the version number and exits. .SH EXAMPLES .nf .sp 8v % \f4xfs_estimate \-e 10m /var/tmp\f1\f7 /var/tmp will take about 4.2 megabytes with the external log using 2560 blocks or about 10.0 megabytes .fi .nf .sp .8v % \f4xfs_estimate \-v \-e 10m /var/tmp\f1\f7 directory bsize blocks megabytes logsize /var/tmp 4096 792 4.0MB 10485760 .fi .nf .sp .8v % \f4xfs_estimate \-v /var/tmp\f1\f7 directory bsize blocks megabytes logsize /var/tmp 4096 3352 14.0MB 10485760 .fi .nf .sp .8v % \f4xfs_estimate /var/tmp\f1\f7 /var/tmp will take about 14.0 megabytes .fi xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_freeze.80000644000000000000000000000415613063067171016347 0ustar .TH xfs_freeze 8 .SH NAME xfs_freeze \- suspend access to an XFS filesystem .SH SYNOPSIS .B xfs_freeze [ .B \-f | .B \-u ] .I mount-point .br .B xfs_freeze \-V .fi .SH DESCRIPTION .B xfs_freeze suspends and resumes access to an XFS filesystem (see .BR xfs (5)). .PP .B xfs_freeze halts new access to the filesystem and creates a stable image on disk. .B xfs_freeze is intended to be used with volume managers and hardware RAID devices that support the creation of snapshots. .PP The .I mount-point argument is the pathname of the directory where the filesystem is mounted. The filesystem must be mounted to be frozen (see .BR mount (8)). .PP .PP The .B \-f flag requests the specified XFS filesystem to be frozen from new modifications. When this is selected, all ongoing transactions in the filesystem are allowed to complete, new write system calls are halted, other calls which modify the filesystem are halted, and all dirty data, metadata, and log information are written to disk. Any process attempting to write to the frozen filesystem will block waiting for the filesystem to be unfrozen. .PP Note that even after freezing, the on-disk filesystem can contain information on files that are still in the process of unlinking. These files will not be unlinked until the filesystem is unfrozen or a clean mount of the snapshot is complete. .PP The .B \-u flag is used to un-freeze the filesystem and allow operations to continue. Any filesystem modifications that were blocked by the freeze are unblocked and allowed to complete. .PP The .B \-V flag prints the version number and exits. .PP Unless .B \-V is specified, one of .B \-f or .B \-u must be supplied to .BR xfs_freeze . .SH NOTES A copy of a frozen XFS filesystem will usually have the same universally unique identifier (UUID) as the original, and thus may be prevented from being mounted. The XFS .B nouuid mount option can be used to circumvent this issue. .PP In Linux kernel version 2.6.29, the interface which XFS uses to freeze and unfreeze was elevated to the VFS, so that this tool can now be used on many other Linux filesystems. .SH SEE ALSO .BR xfs (5), .BR lvm (8), .BR mount (8). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_fsr.80000644000000000000000000001210013063067171015645 0ustar .TH xfs_fsr 8 .SH NAME xfs_fsr \- filesystem reorganizer for XFS .SH SYNOPSIS .nf \f3xfs_fsr\f1 [\f3\-vdg\f1] \c [\f3\-t\f1 seconds] [\f3\-p\f1 passes] [\f3\-f\f1 leftoff] [\f3\-m\f1 mtab] \f3xfs_fsr\f1 [\f3\-vdg\f1] \c [xfsdev | file] ... .br .B xfs_fsr \-V .fi .SH DESCRIPTION .I xfs_fsr is applicable only to XFS filesystems. .PP .I xfs_fsr improves the organization of mounted filesystems. The reorganization algorithm operates on one file at a time, compacting or otherwise improving the layout of the file extents (contiguous blocks of file data). .PP The following options are accepted by .IR xfs_fsr . The .BR \-m , .BR \-t , and .B \-f options have no meaning if any filesystems or files are specified on the command line. .TP 13 .BI \-m " mtab" Use this file for the list of filesystems to reorganize. The default is to use .IR /etc/mtab . .TP .BI \-t " seconds" How long to reorganize. The default is 7200 seconds (2 hours). .TP .BI \-p " passes" Number of passes before terminating global re-org. The default is 10 passes. .TP .BI \-f " leftoff" Use this file instead of .I /var/tmp/.fsrlast to read the state of where to start and as the file to store the state of where reorganization left off. .TP .B \-v Verbose. Print cryptic information about each file being reorganized. .TP .B \-d Debug. Print even more cryptic information. .TP .B \-g Print to syslog (default if stdout not a tty). .TP .B \-V Prints the version number and exits. .PP When invoked with no arguments .I xfs_fsr reorganizes all regular files in all mounted filesystems. .I xfs_fsr makes many cycles over .I /etc/mtab each time making a single pass over each XFS filesystem. Each pass goes through and selects files that have the largest number of extents. It attempts to defragment the top 10% of these files on each pass. .PP It runs for up to two hours after which it records the filesystem where it left off, so it can start there the next time. This information is stored in the file .I /var/tmp/.fsrlast_xfs. If the information found here is somehow inconsistent or out of date it is ignored and reorganization starts at the beginning of the first filesystem found in .IR /etc/mtab . .PP .I xfs_fsr can be called with one or more arguments naming filesystems (block device name), and files to reorganize. In this mode .I xfs_fsr does not read or write .I /var/tmp/.fsrlast_xfs nor does it run for a fixed time interval. It makes one pass through each specified regular file and all regular files in each specified filesystem. A command line name referring to a symbolic link (except to a file system device), FIFO, or UNIX domain socket generates a warning message, but is otherwise ignored. While traversing the filesystem these types of files are silently skipped. .SH FILES .PD 0 .TP 21 /etc/mtab contains default list of filesystems to reorganize. .TP 21 /var/tmp/.fsrlast_xfs records the state where reorganization left off. .PD .SH "SEE ALSO" xfs_fsr(8), mkfs.xfs(8), xfs_ncheck(8), xfs(5). .SH "NOTES" .I xfs_fsr improves the layout of extents for each file by copying the entire file to a temporary location and then interchanging the data extents of the target and temporary files in an atomic manner. This method requires that enough free disk space be available to copy any given file and that the space be less fragmented than the original file. It also requires the owner of the file to have enough remaining filespace quota to do the copy on systems running quotas. .I xfs_fsr generates a warning message if space is not sufficient to improve the target file. .PP A temporary file used in improving a file given on the command line is created in the same parent directory of the target file and is prefixed by the string '\f3.fsr\f1'. The temporary files used in improving an entire XFS device are stored in a directory at the root of the target device and use the same naming scheme. The temporary files are unlinked upon creation so data will not be readable by any other process. .PP .I xfs_fsr does not operate on files that are currently mapped in memory. A 'file busy' error can be seen for these files if the verbose flag (\f3-v\f1) is set. .PP Files marked as no\-defrag will be skipped. The .IR xfs_io (8) chattr command with the f attribute can be used to set or clear this flag. Files and directories created in a directory with the no\-defrag flag will inherit the attribute. .PP An entry in .I /etc/mtab or the file specified using the .B \-m option must have the .B rw option specified for read and write access. If this option is not present, then .I xfs_fsr skips the filesystem described by that line. See the .IR fstab (5) reference page for more details. .PP In general we do not foresee the need to run .I xfs_fsr on system partitions such as .IR / , .I /boot and .I /usr as in general these will not suffer from fragmentation. There are also issues with defragmenting files .IR lilo (8) uses to boot your system. It is recommended that these files should be flagged as no\-defrag with the .IR xfs_io (8) chattr command. Should these files be moved by .I xfs_fsr then you must rerun .I lilo before you reboot or you may have an unbootable system. xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_growfs.80000644000000000000000000001145713063067171016400 0ustar .\" Verbatim blocks taken from openssl req manpage content .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .TH xfs_growfs 8 .SH NAME xfs_growfs, xfs_info \- expand an XFS filesystem .SH SYNOPSIS .B xfs_growfs [ .B \-dilnrx ] [ .B \-D .I size ] [ .B \-e .I rtextsize ] [ .B \-L .I size ] [ .B \-m .I maxpct ] [ .B \-t .I mtab ] [ .B \-R .I size ] .I mount-point .br .B xfs_growfs \-V .PP .br .B xfs_info [ .B \-t .I mtab ] .I mount-point .br .B xfs_info \-V .SH DESCRIPTION .B xfs_growfs expands an existing XFS filesystem (see .BR xfs (5)). The .I mount-point argument is the pathname of the directory where the filesystem is mounted. The filesystem must be mounted to be grown (see .BR mount (8)). The existing contents of the filesystem are undisturbed, and the added space becomes available for additional file storage. .PP .B xfs_info is equivalent to invoking .B xfs_growfs with the .B \-n option (see discussion below). .SH OPTIONS .TP .BI "\-d | \-D " size Specifies that the data section of the filesystem should be grown. If the .B \-D .I size option is given, the data section is grown to that .IR size , otherwise the data section is grown to the largest size possible with the .B \-d option. The size is expressed in filesystem blocks. .TP .B \-e Allows the real-time extent size to be specified. In .BR mkfs.xfs (8) this is specified with .B \-r extsize=\c .IR nnnn . .TP .B \-i The new log is an internal log (inside the data section). .B [NOTE: This option is not implemented] .TP .BI "\-l | \-L " size Specifies that the log section of the filesystem should be grown, shrunk, or moved. If the .B \-L .I size option is given, the log section is changed to be that .IR size , if possible. The size is expressed in filesystem blocks. The size of an internal log must be smaller than the size of an allocation group (this value is printed at .BR mkfs (8) time). If neither .B \-i nor .B \-x is given with .BR \-l , the log continues to be internal or external as it was before. .B [NOTE: These options are not implemented] .TP .B \-m Specify a new value for the maximum percentage of space in the filesystem that can be allocated as inodes. In .BR mkfs.xfs (8) this is specified with .B -i maxpct=\c .IR nn . .TP .B \-n Specifies that no change to the filesystem is to be made. The filesystem geometry is printed, and argument checking is performed, but no growth occurs. .B See output examples below. .TP .BI "\-r | \-R " size Specifies that the real-time section of the filesystem should be grown. If the .B \-R .I size option is given, the real-time section is grown to that size, otherwise the real-time section is grown to the largest size possible with the .B \-r option. The size is expressed in filesystem blocks. The filesystem does not need to have contained a real-time section before the .B xfs_growfs operation. .TP .B \-t Specifies an alternate mount table file (default is .I /proc/mounts if it exists, else .IR /etc/mtab ). This is used when working with filesystems mounted without writing to .I /etc/mtab file - refer to .BR mount (8) for further details. .TP .B \-V Prints the version number and exits. The .I mount-point argument is not required with .BR \-V . .PP .B xfs_growfs is most often used in conjunction with logical volumes (see .BR md (4) and .BR lvm (8) on Linux). However, it can also be used on a regular disk partition, for example if a partition has been enlarged while retaining the same starting block. .SH PRACTICAL USE Filesystems normally occupy all of the space on the device where they reside. In order to grow a filesystem, it is necessary to provide added space for it to occupy. Therefore there must be at least one spare new disk partition available. Adding the space is often done through the use of a logical volume manager. .SH "EXAMPLES" Understanding xfs_info output. .PP Suppose one has the following "xfs_info /dev/sda" output: .PP .RS 2 .Vb \&meta-data=/dev/sda isize=256 agcount=32, agsize=16777184 blks \& = sectsz=512 attr=2 \&data = bsize=4096 blocks=536869888, imaxpct=5 \& = sunit=32 swidth=128 blks \&naming =version 2 bsize=4096 \&log =internal bsize=4096 blocks=32768, version=2 \& = sectsz=512 sunit=32 blks, lazy-count=1 \&realtime =none extsz=524288 blocks=0, rtextents=0 .Ve .RE .PP Here, the data section of the output indicates "bsize=4096", meaning the data block size for this filesystem is 4096 bytes. This section also shows "sunit=32 swidth=128 blks", which means the stripe unit is 32*4096 bytes = 128 kibibytes and the stripe width is 128*4096 bytes = 512 kibibytes. A single stripe of this filesystem therefore consists of four stripe units (128 blocks / 32 blocks per unit). .SH SEE ALSO .BR mkfs.xfs (8), .BR md (4), .BR lvm (8), .BR mount (8). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_io.80000644000000000000000000005502213063067171015474 0ustar .TH xfs_io 8 .SH NAME xfs_io \- debug the I/O path of an XFS filesystem .SH SYNOPSIS .B xfs_io [ .B \-adfimrRstxT ] [ .B \-c .I cmd ] ... [ .B \-p .I prog ] .I file .br .B xfs_io \-V .SH DESCRIPTION .B xfs_io is a debugging tool like .BR xfs_db (8), but is aimed at examining the regular file I/O paths rather than the raw XFS volume itself. These code paths include not only the obvious read/write/mmap interfaces for manipulating files, but also cover all of the XFS extensions (such as space preallocation, additional inode flags, etc). .SH OPTIONS .TP 1.0i .BI \-c " cmd" .B xfs_io commands may be run interactively (the default) or as arguments on the command line. Multiple .B \-c arguments may be given. The commands are run in the sequence given, then the program exits. .TP .BI \-p " prog" Set the program name for prompts and some error messages, the default value is .BR xfs_io . .TP .B \-f Create .I file if it does not already exist. .TP .B \-r Open .I file read-only, initially. This is required if .I file is immutable or append-only. .TP .B \-i Start an idle thread. The purpose of this idle thread is to test io from a multi threaded process. With single threaded process, the file table is not shared and file structs are not reference counted. Spawning an idle thread can help detecting file struct reference leaks. .TP .B \-x Expert mode. Dangerous commands are only available in this mode. These commands also tend to require additional privileges. .TP .B \-V Prints the version number and exits. .PP The other .BR open (2) options described below are also available from the command line. .SH CONCEPTS .B xfs_io maintains a number of open files and memory mappings. Files can be initially opened on the command line (optionally), and additional files can also be opened later. .PP .B xfs_io commands can be broken up into three groups. Some commands are aimed at doing regular file I/O - read, write, sync, space preallocation, etc. .PP The second set of commands exist for manipulating memory mapped regions of a file - mapping, accessing, storing, unmapping, flushing, etc. .PP The remaining commands are for the navigation and display of data structures relating to the open files, mappings, and the filesystems where they reside. .PP Many commands have extensive online help. Use the .B help command for more details on any command. .SH FILE I/O COMMANDS .TP .BI "file [ " N " ]" Display a list of all open files and (optionally) switch to an alternate current open file. .TP .BI "open [[ \-acdfrstRT ] " path " ]" Closes the current file, and opens the file specified by .I path instead. Without any arguments, displays statistics about the current file \- see the .B stat command. .RS 1.0i .PD 0 .TP 0.4i .B \-a opens append-only (O_APPEND). .TP .B \-d opens for direct I/O (O_DIRECT). .TP .B \-f creates the file if it doesn't already exist (O_CREAT). .TP .B \-r opens read-only (O_RDONLY). .TP .B \-s opens for synchronous I/O (O_SYNC). .TP .B \-t truncates on open (O_TRUNC). .TP .B \-n opens in non-blocking mode if possible (O_NONBLOCK). .TP .B \-T create a temporary file not linked into the filesystem namespace (O_TMPFILE). The pathname passed must refer to a directory which is treated as virtual parent for the newly created invisible file. Can not be used together with the .B \-r option. .TP .B \-R marks the file as a realtime XFS file after opening it, if it is not already marked as such. .PD .RE .TP .B o See the .B open command. .TP .B close Closes the current open file, marking the next open file as current (if one exists). .TP .B c See the .B close command. .TP .BI "pread [ \-b " bsize " ] [ \-v ] [ \-FBR [ \-Z " seed " ] ] [ \-V " vectors " ] " "offset length" Reads a range of bytes in a specified blocksize from the given .IR offset . .RS 1.0i .PD 0 .TP 0.4i .B \-b can be used to set the blocksize into which the .BR read (2) requests will be split. The default blocksize is 4096 bytes. .TP .B \-v dump the contents of the buffer after reading, by default only the count of bytes actually read is dumped. .TP .B \-F read the buffers in a forwards sequential direction. .TP .B \-B read the buffers in a reserve sequential direction. .TP .B \-R read the buffers in the give range in a random order. .TP .B \-Z seed specify the random number seed used for random reads. .TP .B \-V vectors Use the vectored IO read syscall .BR preadv (2) with a number of blocksize length iovecs. The number of iovecs is set by the .I vectors parameter. .PD .RE .TP .B r See the .B pread command. .TP .BI "pwrite [ \-i " file " ] [ \-d ] [ \-s " skip " ] [ \-b " size " ] [ \-S " seed " ] [ \-FBR [ \-Z " zeed " ] ] [ \-wW ] [ \-V " vectors " ] " "offset length" Writes a range of bytes in a specified blocksize from the given .IR offset . The bytes written can be either a set pattern or read in from another file before writing. .RS 1.0i .PD 0 .TP 0.4i .B \-i allows an input .I file to be specified as the source of the data to be written. .TP .B \-d causes direct I/O, rather than the usual buffered I/O, to be used when reading the input file. .TP .B \-s specifies the number of bytes to .I skip from the start of the input file before starting to read. .TP .B \-b used to set the blocksize into which the .BR write (2) requests will be split. The default blocksize is 4096 bytes. .TP .B \-S used to set the (repeated) fill pattern which is used when the data to write is not coming from a file. The default buffer fill pattern value is 0xcdcdcdcd. .TP .B \-F write the buffers in a forwards sequential direction. .TP .B \-B write the buffers in a reserve sequential direction. .TP .B \-R write the buffers in the give range in a random order. .TP .B \-Z seed specify the random number seed used for random write .TP .B \-w call .BR fdatasync (2) once all writes are complete (included in timing results) .TP .B \-W call .BR fsync (2) once all writes are complete (included in timing results) .TP .B \-V vectors Use the vectored IO write syscall .BR pwritev (2) with a number of blocksize length iovecs. The number of iovecs is set by the .I vectors parameter. .RE .PD .TP .B w See the .B pwrite command. .TP .BI "bmap [ \-acdelpv ] [ \-n " nx " ]" Prints the block mapping for the current open file. Refer to the .BR xfs_bmap (8) manual page for complete documentation. .TP .BI "fiemap [ \-alv ] [ \-n " nx " ]" Prints the block mapping for the current open file using the fiemap ioctl. Options behave as described in the .BR xfs_bmap (8) manual page. .TP .BI "extsize [ \-R | \-D ] [ " value " ]" Display and/or modify the preferred extent size used when allocating space for the currently open file. If the .B \-R option is specified, a recursive descent is performed for all directory entries below the currently open file .RB ( \-D can be used to restrict the output to directories only). If the target file is a directory, then the inherited extent size is set for that directory (new files created in that directory inherit that extent size). The .I value should be specified in bytes, or using one of the usual units suffixes (k, m, g, b, etc). The extent size is always reported in units of bytes. .TP .BI "cowextsize [ \-R | \-D ] [ " value " ]" Display and/or modify the preferred copy-on-write extent size used when allocating space for the currently open file. If the .B \-R option is specified, a recursive descent is performed for all directory entries below the currently open file .RB ( \-D can be used to restrict the output to directories only). If the target file is a directory, then the inherited CoW extent size is set for that directory (new files created in that directory inherit that CoW extent size). The .I value should be specified in bytes, or using one of the usual units suffixes (k, m, g, b, etc). The extent size is always reported in units of bytes. .TP .BI "allocsp " size " 0" Sets the size of the file to .I size and zeroes any additional space allocated using the XFS_IOC_ALLOCSP/XFS_IOC_FREESP system call described in the .BR xfsctl (3) manual page. .B allocsp and .B freesp do exactly the same thing. .TP .BI "freesp " size " 0" See the .B allocsp command. .TP .BI "fadvise [ \-r | \-s | [[ \-d | \-n | \-w ] " "offset length " ]] On platforms which support it, allows hints be given to the system regarding the expected I/O patterns on the file. The range arguments are required by some advise commands ([*] below), and the others must have no range arguments. With no arguments, the POSIX_FADV_NORMAL advice is implied (default readahead). .RS 1.0i .PD 0 .TP 0.4i .B \-d the data will not be accessed again in the near future (POSIX_FADV_DONTNEED[*]). .TP .B \-n data will be accessed once and not be reused (POSIX_FADV_NOREUSE[*]). .TP .B \-r expect access to data in random order (POSIX_FADV_RANDOM), which sets readahead to zero. .TP .B \-s expect access to data in sequential order (POSIX_FADV_SEQUENTIAL), which doubles the default readahead on the file. .TP .B \-w advises the specified data will be needed again (POSIX_FADV_WILLNEED[*]) which forces the maximum readahead. .RE .PD .TP .B fdatasync Calls .BR fdatasync (2) to flush the file's in-core data to disk. .TP .B fsync Calls .BR fsync (2) to flush all in-core file state to disk. .TP .B s See the .B fsync command. .TP .BI "sync_range [ \-a | \-b | \-w ] offset length " On platforms which support it, allows control of syncing a range of the file to disk. With no options, SYNC_FILE_RANGE_WRITE is implied on the range supplied. .RS 1.0i .PD 0 .TP 0.4i .B \-a wait for IO in the given range to finish after writing (SYNC_FILE_RANGE_WAIT_AFTER). .TP .B \-b wait for IO in the given range to finish before writing (SYNC_FILE_RANGE_WAIT_BEFORE). .TP .B \-w start writeback of dirty data in the given range (SYNC_FILE_RANGE_WRITE). .RE .PD .TP .B sync Calls .BR sync (2) to flush all filesystems' in-core data to disk. .TP .B syncfs Calls .BR syncfs (2) to flush this filesystem's in-core data to disk. .TP .BI resvsp " offset length" Allocates reserved, unwritten space for part of a file using the XFS_IOC_RESVSP system call described in the .BR xfsctl (3) manual page. .TP .BI unresvsp " offset length" Frees reserved space for part of a file using the XFS_IOC_UNRESVSP system call described in the .BR xfsctl (3) manual page. .TP .BI "falloc [ \-k ]" " offset length" Allocates reserved, unwritten space for part of a file using the fallocate routine as described in the .BR fallocate (2) manual page. .RS 1.0i .PD 0 .TP 0.4i .B \-k will set the FALLOC_FL_KEEP_SIZE flag as described in .BR fallocate (2). .PD .RE .TP .BI fcollapse " offset length" Call fallocate with FALLOC_FL_COLLAPSE_RANGE flag as described in the .BR fallocate (2) manual page to de-allocates blocks and eliminates the hole created in this process by shifting data blocks into the hole. .TP .BI finsert " offset length" Call fallocate with FALLOC_FL_INSERT_RANGE flag as described in the .BR fallocate (2) manual page to create the hole by shifting data blocks. .TP .BI fpunch " offset length" Punches (de-allocates) blocks in the file by calling fallocate with the FALLOC_FL_PUNCH_HOLE flag as described in the .BR fallocate (2) manual page. .TP .BI funshare " offset length" Call fallocate with FALLOC_FL_UNSHARE_RANGE flag as described in the .BR fallocate (2) manual page to unshare all shared blocks within the range. .TP .BI fzero " offset length" Call fallocate with FALLOC_FL_ZERO_RANGE flag as described in the .BR fallocate (2) manual page to allocate and zero blocks within the range. .TP .BI zero " offset length" Call xfsctl with .B XFS_IOC_ZERO_RANGE as described in the .BR xfsctl (3) manual page to allocate and zero blocks within the range. .TP .BI truncate " offset" Truncates the current file at the given offset using .BR ftruncate (2). .TP .BI "sendfile \-i " srcfile " | \-f " N " [ " "offset length " ] On platforms which support it, allows a direct in-kernel copy between two file descriptors. The current open file is the target, the source must be specified as another open file .RB ( \-f ) or by path .RB ( \-i ). .TP .BI "readdir [ -v ] [ -o " offset " ] [ -l " length " ] " Read a range of directory entries from a given offset of a directory. .RS 1.0i .PD 0 .TP 0.4i .B \-v verbose mode - dump dirent content as defined in .BR readdir (3) .TP .B \-o specify starting .I offset .TP .B \-l specify total .I length to read (in bytes) .RE .PD .TP .TP .BI "seek \-a | \-d | \-h [ \-r ] [ \-s ] offset" On platforms that support the .BR lseek (2) .B SEEK_DATA and .B SEEK_HOLE options, display the offsets of the specified segments. .RS 1.0i .PD 0 .TP 0.4i .B \-a Display both .B data and .B hole segments starting at the specified .B offset. .TP .B \-d Display the .B data segment starting at the specified .B offset. .TP .B \-h Display the .B hole segment starting at the specified .B offset. .TP .B \-r Recursively display all the specified segments starting at the specified .B offset. .TP .B \-s Display the starting lseek(2) offset. This offset will be a calculated value when both data and holes are displayed together or performing a recusively display. .RE .PD .TP .TP .BI "reflink [ \-C ] [ \-q ] src_file [src_offset dst_offset length]" On filesystems that support the .B XFS_IOC_CLONE_RANGE or .B BTRFS_IOC_CLONE_RANGE ioctls, map .I length bytes at offset .I dst_offset in the open file to the same physical blocks that are mapped at offset .I src_offset in the file .I src_file , replacing any contents that may already have been there. If a program writes into a reflinked block range of either file, the dirty blocks will be cloned, written to, and remapped ("copy on write") in the affected file, leaving the other file(s) unchanged. If src_offset, dst_offset, and length are omitted, all contents of src_file will be reflinked into the open file. .RS 1.0i .PD 0 .TP 0.4i .B \-C Print timing statistics in a condensed format. .TP .B \-q Do not print timing statistics at all. .RE .PD .TP .TP .BI "dedupe [ \-C ] [ \-q ] src_file src_offset dst_offset length" On filesystems that support the .B XFS_IOC_FILE_EXTENT_SAME or .B BTRFS_IOC_FILE_EXTENT_SAME ioctls, map .I length bytes at offset .I dst_offset in the open file to the same physical blocks that are mapped at offset .I src_offset in the file .I src_file , but only if the contents of both ranges are identical. This is known as block-based deduplication. If a program writes into a reflinked block range of either file, the dirty blocks will be cloned, written to, and remapped ("copy on write") in the affected file, leaving the other file(s) unchanged. .RS 1.0i .PD 0 .TP 0.4i .B \-C Print timing statistics in a condensed format. .TP .B \-q Do not print timing statistics at all. .RE .PD .TP .TP .BI "copy_range [ -s " src_offset " ] [ -d " dst_offset " ] [ -l " length " ] src_file" On filesystems that support the .BR copy_file_range (2) system call, copies data from the .I src_file into the open file. If .IR src_offset , .IR dst_offset , and .I length are omitted the contents of src_file will be copied to the beginning of the open file, overwriting any data already there. .RS 1.0i .PD 0 .TP 0.4i .B \-s Copy data from .I src_file beginning from .IR src_offset . .TP .B \-d Copy data into the open file beginning at .IR dst_offset . .TP .B \-l Copy up to .I length bytes of data. .SH MEMORY MAPPED I/O COMMANDS .TP .BI "mmap [ " N " | [[ \-rwx ] [\-s " size " ] " "offset length " ]] With no arguments, .B mmap shows the current mappings. Specifying a single numeric argument .I N sets the current mapping. If two arguments are specified (a range specified by .I offset and .IR length ), a new mapping is created spanning the range, and the protection mode can be given as a combination of PROT_READ .RB ( \-r ), PROT_WRITE .RB ( \-w ), and PROT_EXEC .RB ( \-x ). .BI \-s " size" is used to do a mmap(size) && munmap(size) operation at first, try to reserve some extendible free memory space, if .I size is bigger than .I length parameter. But there's not guarantee that the memory after .I length ( up to .I size ) will stay free. .B e.g. "mmap -rw -s 8192 1024" will mmap 0 ~ 1024 bytes memory, but try to reserve 1024 ~ 8192 free space(no guarantee). This free space will helpful for "mremap 8192" without MREMAP_MAYMOVE flag. .TP .B mm See the .B mmap command. .TP .BI "mremap [ \-f ] [ \-m ] " new_length Changes the current mapping size to .IR new_length . Whether the mapping may be moved is controlled by the flags passed; MREMAP_FIXED .RB ( \-f ), or MREMAP_MAYMOVE .RB ( \-m ). .IR new_length specifies a page-aligned address to which the mapping must be moved. It can be setted to 139946004389888, 4096k or 1g etc. .TP .B mrm See the .B mremap command. .TP .B munmap Unmaps the current memory mapping. .TP .B mu See the .B munmap command. .TP .BI "mread [ \-f | \-v ] [ \-r ] [" " offset length " ] Accesses a segment of the current memory mapping, optionally dumping it to the standard output stream (with .B \-v or .B \-f option) for inspection. The accesses are performed sequentially from the start .I offset by default, but can also be done from the end backwards through the mapping if the .B \-r option in specified. The two verbose modes differ only in the relative offsets they display, the .B \-f option is relative to file start, whereas .B \-v shows offsets relative to the start of the mapping. .TP .B mr See the .B mread command. .TP .BI "mwrite [ \-r ] [ \-S " seed " ] [ " "offset length " ] Stores a byte into memory for a range within a mapping. The default stored value is 'X', repeated to fill the range specified, but this can be changed using the .B \-S option. The memory stores are performed sequentially from the start offset by default, but can also be done from the end backwards through the mapping if the .B \-r option in specified. .TP .B mw See the .B mwrite command. .TP .BI "msync [ \-i ] [ \-a | \-s ] [ " "offset length " ] Writes all modified copies of pages over the specified range (or entire mapping if no range specified) to their backing storage locations. Also, optionally invalidates .RB ( \-i ) so that subsequent references to the pages will be obtained from their backing storage locations (instead of cached copies). The flush can be done synchronously .RB ( \-s) or asynchronously .RB ( \-a ). .TP .B ms See the .B msync command. .TP .BI "madvise [ \-d | \-r | \-s | \-w ] [ " "offset length " ] Modifies page cache behavior when operating on the current mapping. The range arguments are required by some advise commands ([*] below). With no arguments, the POSIX_MADV_NORMAL advice is implied (default readahead). .RS 1.0i .PD 0 .TP 0.4i .B \-d the pages will not be needed (POSIX_MADV_DONTNEED[*]). .TP .B \-r expect random page references (POSIX_MADV_RANDOM), which sets readahead to zero. .TP .B \-s expect sequential page references (POSIX_MADV_SEQUENTIAL), which doubles the default readahead on the file. .TP .B \-w advises the specified pages will be needed again (POSIX_MADV_WILLNEED[*]) which forces the maximum readahead. .RE .PD .TP .B mincore Dumps a list of pages or ranges of pages that are currently in core, for the current memory mapping. .SH OTHER COMMANDS .TP .BR "help [ " command " ]" Display a brief description of one or all commands. .TP .B print Display a list of all open files and memory mapped regions. The current file and current mapping are distinguishable from any others. .TP .B p See the .B print command. .TP .B quit Exit .BR xfs_io . .TP .B q See the .B quit command. .TP .BR lsattr " [ " \-R " | " \-D " | " \-a " | " \-v " ]" List extended inode flags on the currently open file. If the .B \-R option is specified, a recursive descent is performed for all directory entries below the currently open file .RB ( \-D can be used to restrict the output to directories only). This is a depth first descent, it does not follow symlinks and it also does not cross mount points. .TP .BR chattr " [ " \-R " | " \-D " ] [ " + / \-riasAdtPneEfS " ]" Change extended inode flags on the currently open file. The .B \-R and .B \-D options have the same meaning as above. The mapping between each letter and the inode flags (refer to .BR xfsctl (3) for the full list) is available via the .B help command. .TP .B freeze Suspend all write I/O requests to the filesystem of the current file. Only available in expert mode and requires privileges. .TP .B thaw Undo the effects of a filesystem freeze operation. Only available in expert mode and requires privileges. .TP .BI "flink " path Link the currently open file descriptor into the filesystem namespace. .TP .BI "inject [ " tag " ]" Inject errors into a filesystem to observe filesystem behavior at specific points under adverse conditions. Without the .I tag argument, displays the list of error tags available. Only available in expert mode and requires privileges. .TP .BI "resblks [ " blocks " ]" Get and/or set count of reserved filesystem blocks using the XFS_IOC_GET_RESBLKS or XFS_IOC_SET_RESBLKS system calls. Note \-\- this can be useful for exercising out of space behavior. Only available in expert mode and requires privileges. .TP .BR shutdown " [ " \-f " ]" Force the filesystem to shutdown (with or without flushing the log). Only available in expert mode and requires privileges. .TP .BR stat " [ " \-v " ]" Selected statistics from .BR stat (2) and the XFS_IOC_GETXATTR system call on the current file. If the .B \-v option is specified, the atime (last access), mtime (last modify), and ctime (last change) timestamps are also displayed. .TP .B statfs Selected statistics from .BR statfs (2) and the XFS_IOC_FSGEOMETRY system call on the filesystem where the current file resides. .TP .BR chproj " [ " \-R | \-D " ]" Modifies the project identifier associated with the current path. The .B \-R option will recursively descend if the current path is a directory. The .B \-D option will also recursively descend, only setting modifying projects on subdirectories. See the .BR xfs_quota (8) manual page for more information about project identifiers. .TP .BR lsproj " [ " \-R | \-D " ]" Displays the project identifier associated with the current path. The .B \-R and .B \-D options behave as described above, in .B chproj. .TP .BR parent " [ " \-cpv " ]" By default this command prints out the parent inode numbers, inode generation numbers and basenames of all the hardlinks which point to the inode of the current file. .RS 1.0i .PD 0 .TP 0.4i .B \-p the output is similar to the default output except pathnames up to the mount-point are printed out instead of the component name. .TP .B \-c the file's filesystem will check all the parent attributes for consistency. .TP .B \-v verbose output will be printed. .RE .IP .B [NOTE: Not currently operational on Linux.] .PD .SH SEE ALSO .BR mkfs.xfs (8), .BR xfsctl (3), .BR xfs_bmap (8), .BR xfs_db (8), .BR xfs (5), .BR fdatasync (2), .BR fstat (2), .BR fstatfs (2), .BR fsync (2), .BR ftruncate (2), .BR mmap (2), .BR msync (2), .BR open (2), .BR pread (2), .BR pwrite (2), .BR readdir (3). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_logprint.80000644000000000000000000000555713063067171016733 0ustar .TH xfs_logprint 8 .SH NAME xfs_logprint \- print the log of an XFS filesystem .SH SYNOPSIS .B xfs_logprint [ .I options ] .I device .SH DESCRIPTION .B xfs_logprint prints the log of an XFS filesystem (see .BR xfs (5)). The .I device argument is the pathname of the partition or logical volume containing the filesystem. The .I device can be a regular file if the .B \-f option is used. The contents of the filesystem remain undisturbed. There are two major modes of operation in .BR xfs_logprint . .PP One mode is better for filesystem operation debugging. It is called the transactional view and is enabled through the .B \-t option. The transactional view prints only the portion of the log that pertains to recovery. In other words, it prints out complete transactions between the tail and the head. This view tries to display each transaction without regard to how they are split across log records. .PP The second mode starts printing out information from the beginning of the log. Some error blocks might print out in the beginning because the last log record usually overlaps the oldest log record. A message is printed when the physical end of the log is reached and when the logical end of the log is reached. A log record view is displayed one record at a time. Transactions that span log records may not be decoded fully. .SH OPTIONS .TP .B \-b Extract and print buffer information. Only used in transactional view. .TP .B \-c Attempt to continue when an error is detected. .TP .BI \-C " filename" Copy the log from the filesystem to the file .IR filename . The log itself is not printed. .TP .B \-d Dump the log from front to end, printing where each log record is located on disk. .TP .B \-D Do not decode anything; just print data. .TP .B \-e Exit when an error is found in the log. Normally, .B xfs_logprint tries to continue and unwind from bad logs. However, sometimes it just dies in bad ways. Using this option prevents core dumps. .TP .B \-f Specifies that the filesystem image to be processed is stored in a regular file at .I device (see the .BR mkfs.xfs "(8) " -d .I file option). This might happen if an image copy of a filesystem has been made into an ordinary file with .BR xfs_copy (8). .TP .BI \-l " logdev" External log device. Only for those filesystems which use an external log. .TP .B \-i Extract and print inode information. Only used in transactional view. .TP .B \-q Extract and print quota information. Only used in transactional view. .TP .B \-n Do not try and interpret log data; just interpret log header information. .TP .B \-o Also print buffer data in hex. Normally, buffer data is just decoded, so better information can be printed. .TP .BI \-s " start-block" Override any notion of where to start printing. .TP .B \-t Print out the transactional view. .TP .B \-v Print "overwrite" data. .TP .B \-V Prints the version number and exits. .SH SEE ALSO .BR mkfs.xfs (8), .BR mount (8). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_mdrestore.80000644000000000000000000000230713063067171017067 0ustar .TH xfs_mdrestore 8 .SH NAME xfs_mdrestore \- restores an XFS metadump image to a filesystem image .SH SYNOPSIS .B xfs_mdrestore [ .B \-g ] .I source .I target .br .B xfs_mdrestore \-V .SH DESCRIPTION .B xfs_mdrestore is a debugging tool that restores a metadata image generated by .BR xfs_metadump (8) to a filesystem. The .I source argument specifies the location of the metadump image and the .I target argument specifies the destination for the filesystem image. If the .I source is \-, then the metadata image is read from stdin. This allows the output of be another program such as a compression application to be redirected to .BR xfs_mdrestore . The .I target can be either a file or a device. .PP .B xfs_mdrestore should not be used to restore metadata onto an existing filesystem unless you are completely certain the .I target can be destroyed. .PP .SH OPTIONS .TP .B \-g Shows restore progress on stdout. .TP .B \-V Prints the version number and exits. .SH DIAGNOSTICS .B xfs_mdrestore returns an exit code of 0 if all the metadata is successfully restored or 1 if an error occurs. .SH SEE ALSO .BR xfs_metadump (8), .BR xfs_repair (8), .BR xfs (5) .SH BUGS Email bug reports to .BR linux-xfs@vger.kernel.org . xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_metadump.80000644000000000000000000001031513063067171016675 0ustar .TH xfs_metadump 8 .SH NAME xfs_metadump \- copy XFS filesystem metadata to a file .SH SYNOPSIS .B xfs_metadump [ .B \-aefFgow ] [ .B \-m .I max_extents ] ] [ .B \-l .I logdev ] .I source .I target .br .B xfs_metadump \-V .SH DESCRIPTION .B xfs_metadump is a debugging tool that copies the metadata from an XFS filesystem to a file. The .I source argument must be the pathname of the device or file containing the XFS filesystem and the .I target argument specifies the destination file name. If .I target is \-, then the output is sent to stdout. This allows the output to be redirected to another program such as a compression application. .PP .B xfs_metadump may only be used to copy unmounted filesystems, or read-only mounted filesystems. .PP .B xfs_metadump does not alter the source filesystem in any way. The .I target image is a contiguous (non-sparse) file containing all the filesystem's metadata and indexes to where the blocks were copied from. .PP By default, .B xfs_metadump obfuscates most file (regular file, directory and symbolic link) names and extended attribute names to allow the dumps to be sent without revealing confidential information. Extended attribute values are zeroed and no data is copied. The only exceptions are file or attribute names that are 4 or less characters in length. Also file names that span extents (this can only occur with the .BR mkfs.xfs (8) options where .B \-n .I size > .B \-b .IR size ) are not obfuscated. Names between 5 and 8 characters in length inclusively are partially obfuscated. .PP .B xfs_metadump should not be used for any purposes other than for debugging and reporting filesystem problems. The most common usage scenario for this tool is when .BR xfs_repair (8) fails to repair a filesystem and a metadump image can be sent for analysis. .PP The file generated by .B xfs_metadump can be restored to filesystem image (minus the data) using the .BR xfs_mdrestore (8) tool. .PP .SH OPTIONS .TP .B \-a Copies entire metadata blocks. Normally, .B xfs_metadump will zero any stale bytes interspersed with in-use metadata. Use this option to copy full metadata blocks, to provide more debugging information for a corrupted filesystem. Note that the extra data will be unobfuscated. .TP .B \-e Stops the dump on a read error. Normally, it will ignore read errors and copy all the metadata that is accessible. .TP .B \-f Specifies that the filesystem image to be processed is stored in a regular file (see the .B mkfs.xfs -d file option). This can also happen if an image copy of a filesystem has been made into an ordinary file with .BR xfs_copy (8). .TP .B \-F Specifies that we want to continue even if the superblock magic is not correct. If the source is truly not an XFS filesystem, the resulting image will be useless, and xfs_metadump may crash. .TP .B \-g Shows dump progress. This is sent to stdout if the .I target is a file or to stderr if the .I target is stdout. .TP .BI \-l " logdev" For filesystems which use an external log, this specifies the device where the external log resides. The external log is not copied, only internal logs are copied. .TP .B \-m Set the maximum size of an allowed metadata extent. Extremely large metadata extents are likely to be corrupt, and will be skipped if they exceed this value. The default size is 1000 blocks. .TP .B \-o Disables obfuscation of file names and extended attributes. .TP .B \-w Prints warnings of inconsistent metadata encountered to stderr. Bad metadata is still copied. .TP .B \-V Prints the version number and exits. .SH DIAGNOSTICS .B xfs_metadump returns an exit code of 0 if all readable metadata is successfully copied or 1 if a write error occurs or a read error occurs and the .B \-e option used. .SH NOTES As .B xfs_metadump copies metadata only, it does not matter if the .I source filesystem has a realtime section or not. If the filesystem has an external log, it is not copied. Internal logs are copied and any outstanding log transactions are not obfuscated if they contain names. .PP .B xfs_metadump is a shell wrapper around the .BR xfs_db (8) .B metadump command. .SH SEE ALSO .BR xfs_repair (8), .BR xfs_mdrestore (8), .BR xfs_freeze (8), .BR xfs_db (8), .BR xfs_copy (8), .BR xfs (5) .SH BUGS Email bug reports to .BR linux-xfs@vger.kernel.org . xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_mkfile.80000644000000000000000000000146513063067171016336 0ustar .TH xfs_mkfile 8 .SH NAME xfs_mkfile \- create an XFS file .SH SYNOPSIS .B xfs_mkfile [ .B \-v ] [ .B \-n ] [ .B \-p ] .I size\c .RB [ k | b | m | g ] .IR filename " ..." .br .B xfs_mkfile \-V .SH DESCRIPTION .B xfs_mkfile creates one or more files. The file is padded with zeroes by default. The default size is in bytes, but it can be flagged as kilobytes, blocks, megabytes, or gigabytes with the .BR k , .BR b , .BR m , or .B g suffixes, respectively. .SH OPTIONS .TP .B \-v Verbose. Report the names and sizes of created files. .TP .B \-n No bytes. Create a holey file - that is, do not write out any data, just seek to end of file and write a block. .TP .B \-p Preallocate. The file is preallocated, then overwritten with zeroes, then truncated to the desired size. .TP .B \-V Prints the version number and exits. xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_ncheck.80000644000000000000000000000334713063067171016323 0ustar .TH xfs_ncheck 8 .SH NAME xfs_ncheck \- generate pathnames from i-numbers for XFS .SH SYNOPSIS .B xfs_ncheck [ .B \-i .I ino ] ... [ .B \-f ] [ .B \-s ] [ .B \-l .I logdev ] .I device .br .B xfs_ncheck \-V .SH DESCRIPTION .B xfs_ncheck with no .B \-i arguments generates an inode number and pathname list of all files on the given filesystem. Names of directory files are followed by .BR /. . The output is not sorted in any particular order. The filesystem to be examined is specified by the .I device argument, which should be the disk or volume device for the filesystem. Filesystems stored in files can also be checked, using the .B \-f flag. .SH OPTIONS .TP 0.9i .B \-f Specifies that the filesystem image to be processed is stored in a regular file at .I device (see the .B mkfs.xfs \-d .I \f2file\f1 option). This might happen if an image copy of a filesystem has been made into an ordinary file. .TP .BI \-l " logdev" Specifies the device where the filesystem's external log resides. Only for those filesystems which use an external log. See the .B mkfs.xfs \-l option, and refer to .BR xfs (5) for a detailed description of the XFS log. .TP .B \-s Limits the report to special files and files with setuserid mode. This option may be used to detect violations of security policy. .TP .BI \-i " ino" Limits the report to only those files whose inode numbers follow. May be given multiple times to select multiple inode numbers. .TP .B \-V Prints the version number and exits. .PP If the filesystem is seriously corrupted, or very busy and looks like it is corrupt, a message of the form that would be generated by the .BR xfs_db (8) "check" command may appear. .PP .B xfs_ncheck is only useful with XFS filesystems. .SH SEE ALSO .BR mkfs.xfs (8), .BR xfs (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_quota.80000644000000000000000000004710713063067171016223 0ustar .TH xfs_quota 8 .SH NAME xfs_quota \- manage use of quota on XFS filesystems .SH SYNOPSIS .B xfs_quota [ .B \-x ] [ .B \-f ] [ .B \-p .I prog ] [ .B \-c .I cmd ] ... [ .B \-d .I project ] ... [ .B \-D .I projects_file ] [ .B \-P .I projid_file ] [ .IR path " ... ]" .br .B xfs_quota \-V .SH DESCRIPTION .B xfs_quota is a utility for reporting and editing various aspects of filesystem quota. .PP The options to .B xfs_quota are: .TP 1.0i .BI \-c " cmd" .B xfs_quota commands may be run interactively (the default) or as arguments on the command line. Multiple .B \-c arguments may be given. The commands are run in the sequence given, then the program exits. .TP .BI \-p " prog" Set the program name for prompts and some error messages, the default value is .BR xfs_quota . .TP .B \-x Enable expert mode. All of the administrative commands (see the ADMINISTRATOR COMMANDS section below) which allow modifications to the quota system are available only in expert mode. .TP .B \-f Enable foreign filesystem mode. A limited number of user and administrative commands are available for use on some foreign (non-XFS) filesystems. .TP .BI \-d " project" Project names or numeric identifiers may be specified with this option, which restricts the output of the individual .B xfs_quota commands to the set of projects specified. Multiple .B \-d arguments may be given. .TP .BI \-D " projects_file" Specify a file containing the mapping of numeric project identifiers to directory trees. .I /etc/projects as default, if this option is none. .TP .BI \-P " projid_file" Specify a file containing the mapping of numeric project identifiers to project names. .I /etc/projid as default, if this option is none. .TP .B \-V Prints the version number and exits. .PP The optional .I path argument(s) can be used to specify mount points or device files which identify XFS filesystems. The output of the individual .B xfs_quota commands will then be restricted to the set of filesystems specified. .PP This manual page is divided into two sections \- firstly, information for users of filesystems with quota enabled, and the .B xfs_quota commands of interest to such users; and then information which is useful only to administrators of XFS filesystems using quota and the quota commands which allow modifications to the quota system. .PP Note that common to almost all of the individual commands described below are the options for specifying which quota types are of interest \- user quota .RB ( \-u ), group quota .RB ( \-g ), and/or project quota .RB ( \-p ). Also, several commands provide options to operate on "blocks used" .RB ( \-b ), "inodes used" .RB ( \-i ), and/or "realtime blocks used" .RB ( \-r ). .PP Many commands also have extensive online help. Use the .B help command for more details on any command. .SH QUOTA OVERVIEW .PP In most computing environments, disk space is not infinite. The quota subsystem provides a mechanism to control usage of disk space. Quotas can be set for each individual user on any/all of the local filesystems. The quota subsystem warns users when they exceed their allotted limit, but allows some extra space for current work (hard limit/soft limit). In addition, XFS filesystems with limit enforcement turned off can be used as an effective disk usage accounting system. .SS Users' View of Disk Quotas To most users, disk quotas are either of no concern or a fact of life that cannot be avoided. There are two possible quotas that can be imposed \- a limit can be set on the amount of space a user can occupy, and there may be a limit on the number of files (inodes) he can own. .PP The .B quota command provides information on the quotas that have been set by the system administrators and current usage. .PP There are four numbers for each limit: current usage, soft limit (quota), hard limit, and time limit. The soft limit is the number of 1K-blocks (or files) that the user is expected to remain below. The hard limit cannot be exceeded. If a user's usage reaches the hard limit, further requests for space (or attempts to create a file) fail with the "Quota exceeded" (EDQUOT) error. .PP When a user exceeds the soft limit, the timer is enabled. Any time the quota drops below the soft limits, the timer is disabled. If the timer pops, the particular limit that has been exceeded is treated as if the hard limit has been reached, and no more resources are allocated to the user. The only way to reset this condition, short of turning off limit enforcement or increasing the limit, is to reduce usage below quota. Only the superuser (i.e. a sufficiently capable process) can set the time limits and this is done on a per filesystem basis. .SS Surviving When the Quota Limit Is Reached In most cases, the only way for a user to recover from over-quota conditions is to abort whatever activity is in progress on the filesystem that has reached its limit, remove sufficient files to bring the limit back below quota, and retry the failed program. .br However, if a user is in the editor and a write fails because of an over quota situation, that is not a suitable course of action. It is most likely that initially attempting to write the file has truncated its previous contents, so if the editor is aborted without correctly writing the file, not only are the recent changes lost, but possibly much, or even all, of the contents that previously existed. .br There are several possible safe exits for a user caught in this situation. He can use the editor shell escape command to examine his file space and remove surplus files. Alternatively, using .BR sh (1), he can suspend the editor, remove some files, then resume it. A third possibility is to write the file to some other filesystem (perhaps to a file on .IR /tmp ) where the user's quota has not been exceeded. Then after rectifying the quota situation, the file can be moved back to the filesystem it belongs on. .SH USER COMMANDS .TP .B print Lists all paths with devices/project identifiers. The path list can come from several places \- the command line, the mount table, and the .I /etc/projects file. .TP .B df See the .B free command. .HP .B quota [ .BR \-g " | " \-p " | " \-u ] [ .B \-bir ] [ .B \-hnNv ] [ .B \-f .I file ] [ .I ID | .I name ] ... .br Show individual usage and limits, for a single user .I name or numeric user .IR ID . The .B \-h option reports in a "human-readable" format similar to the .BR df (1) command. The .B \-n option reports the numeric IDs rather than the name. The .B \-N option omits the header. The .B \-v option outputs verbose information. The .B \-f option sends the output to .I file instead of stdout. .HP .B free [ .B \-bir ] [ .B \-hN ] [ .B \-f .I file ] .br Reports filesystem usage, much like the .BR df (1) utility. It can show usage for .BR b locks, .BR i node, and/or .BR r ealtime block space, and shows used, free, and total available. If project quota are in use (see the DIRECTORY TREE QUOTA section below), it will also report utilisation for those projects (directory trees). The .B \-h option reports in a "human-readable" format. The .B \-N option omits the header. The .B \-f option outputs the report to .I file instead of stdout. .HP .B help [ .I command ] .br Online help for all commands, or one specific .IR command . .TP .B quit Exit .BR xfs_quota . .TP .B q See the .B quit command. .SH QUOTA ADMINISTRATION The XFS quota system differs to that of other filesystems in a number of ways. Most importantly, XFS considers quota information as filesystem metadata and uses journaling to provide a higher level guarantee of consistency. As such, it is administered differently, in particular: .IP 1. The .B quotacheck command has no effect on XFS filesystems. The first time quota accounting is turned on (at mount time), XFS does an automatic quotacheck internally; afterwards, the quota system will always be completely consistent until quotas are manually turned off. .IP 2. There is no need for quota file(s) in the root of the XFS filesystem. .IP 3. XFS distinguishes between quota accounting and limit enforcement. Quota accounting must be turned on at the time of mounting the XFS filesystem. However, it is possible to turn on/off limit enforcement any time quota accounting is turned on. The "quota" option to the .B mount command turns on both (user) quota accounting and enforcement. The "uqnoenforce" option must be used to turn on user accounting with limit enforcement disabled. .IP 4. Turning on quotas on the root filesystem is slightly different from the above. For IRIX XFS, refer to .BR quotaon (1M). For Linux XFS, the quota mount flags must be passed in with the "rootflags=" boot parameter. .IP 5. It is useful to use the .B state to monitor the XFS quota subsystem at various stages \- it can be used to see if quotas are turned on, and also to monitor the space occupied by the quota system itself.. .IP 6. There is a mechanism built into .B xfsdump that allows quota limit information to be backed up for later restoration, should the need arise. .IP 7. Quota limits cannot be set before turning on quotas on. .IP 8. XFS filesystems keep quota accounting on the superuser (user ID zero), and the tool will display the superuser's usage information. However, limits are never enforced on the superuser (nor are they enforced for group and project ID zero). .IP 9. XFS filesystems perform quota accounting whether the user has quota limits or not. .IP 10. XFS supports the notion of project quota, which can be used to implement a form of directory tree quota (i.e. to restrict a directory tree to only being able to use up a component of the filesystems available space; or simply to keep track of the amount of space used, or number of inodes, within the tree). .SH ADMINISTRATOR COMMANDS .HP .B path [ .I N ] .br Lists all paths with devices/project identifiers or set the current path to the .IR N th list entry (the current path is used by many of the commands described here, it identifies the filesystem toward which a command is directed). The path list can come from several places \- the command line, the mount table, and the .I /etc/projects file. .HP .B report [ .B \-gpu ] [ .B \-bir ] [ .B \-ahntlLNU ] [ .B \-f .I file ] .br Report filesystem quota information. This reports all quota usage for a filesystem, for the specified quota type .RB ( u / g / p and/or .BR b locks/ i nodes/ r ealtime). It reports blocks in 1KB units by default. The .B \-h option reports in a "human-readable" format similar to the .BR df (1) command. The .B \-f option outputs the report to .I file instead of stdout. The .B \-a option reports on all filesystems. By default, outputs the name of the user/group/project. If no name is defined for a given ID, outputs the numeric ID instead. The .B \-n option outputs the numeric ID instead of the name. The .B \-L and .B \-U options specify lower and upper ID bounds to report on. If upper/lower bounds are specified, then by default only the IDs will be displayed in output; with the .B \-l option, a lookup will be performed to translate these IDs to names. The .B \-N option reports information without the header line. The .B \-t option performs a terse report. .HP .B state [ .B \-gpu ] [ .B \-av ] [ .B \-f .I file ] .br Report overall quota state information. This reports on the state of quota accounting, quota enforcement, and the number of extents being used by quota metadata within the filesystem. The .B \-f option outputs state information to .I file instead of stdout. The .B \-a option reports state on all filesystems and not just the current path. .HP .B limit [ .BR \-g " | " \-p " | " \-u ] .BI bsoft= N | .BI bhard= N | .BI isoft= N | .BI ihard= N | .BI rtbsoft= N | .BI rtbhard= N .B \-d | .I id | .I name .br Set quota block limits (bhard/bsoft), inode count limits (ihard/isoft) and/or realtime block limits (rtbhard/rtbsoft). The .B \-d option (defaults) can be used to set the default value that will be used, otherwise a specific .BR u ser/ g roup/ p roject .I name or numeric .IR id entifier must be specified. .HP .B timer [ .BR \-g " | " \-p " | " \-u ] [ .B \-bir ] .I value .br Allows the quota enforcement timeout (i.e. the amount of time allowed to pass before the soft limits are enforced as the hard limits) to be modified. The current timeout setting can be displayed using the .B state command. The value argument is a number of seconds, but units of \&'minutes', 'hours', 'days', and 'weeks' are also understood (as are their abbreviations 'm', 'h', 'd', and 'w'). .HP .B warn [ .BR \-g " | " \-p " | " \-u ] [ .B \-bir ] .I value .B -d | .I id | .I name .br Allows the quota warnings limit (i.e. the number of times a warning will be send to someone over quota) to be viewed and modified. The .B \-d option (defaults) can be used to set the default time that will be used, otherwise a specific .BR u ser/ g roup/ p roject .I name or numeric .IR id entifier must be specified. .B NOTE: this feature is not currently implemented. .TP .BR enable " [ " \-gpu " ] [ " \-v " ]" Switches on quota enforcement for the filesystem identified by the current path. This requires the filesystem to have been mounted with quota enabled, and for accounting to be currently active. The .B \-v option (verbose) displays the state after the operation has completed. .TP .BR disable " [ " \-gpu " ] [ " \-v " ]" Disables quota enforcement, while leaving quota accounting active. The .B \-v option (verbose) displays the state after the operation has completed. .TP .BR off " [ " \-gpu " ] [ " \-v " ]" Permanently switches quota off for the filesystem identified by the current path. Quota can only be switched back on subsequently by unmounting and then mounting again. .TP .BR remove " [ " \-gpu " ] [ " \-v " ]" Remove any space allocated to quota metadata from the filesystem identified by the current path. Quota must not be enabled on the filesystem, else this operation will report an error. .HP .B dump [ .BR \-g " | " \-p " | " \-u ] [ .B \-f .I file ] .br Dump out quota limit information for backup utilities, either to standard output (default) or to a .IR file . This is only the limits, not the usage information, of course. .HP .B restore [ .BR \-g " | " \-p " | " \-u ] [ .B \-f .I file ] .br Restore quota limits from a backup .IR file . The file must be in the format produced by the .B dump command. .HP .B quot [ .BR \-g " | " \-p " | " \-u ] [ .B \-bir ] [ .B \-acnv ] [ .B \-f .I file ] .br Summarize filesystem ownership, by user, group or project. This command uses a special XFS "bulkstat" interface to quickly scan an entire filesystem and report usage information. This command can be used even when filesystem quota are not enabled, as it is a full-filesystem scan (it may also take a long time...). The .B \-a option displays information on all filesystems. The .B \-c option displays a histogram instead of a report. The .B \-n option displays numeric IDs rather than names. The .B \-v option displays verbose information. The .B \-f option send the output to .I file instead of stdout. .HP .B project [ .B \-cCs [ .B \-d .I depth ] [ .B \-p .I path ] .I id | .I name ] .br The .BR \-c , .BR \-C , and .B \-s options allow the directory tree quota mechanism to be maintained. .BR \-d allows to limit recursion level when processing project directories and .BR \-p allows to specify project paths at command line ( instead of .I /etc/projects ). All options are discussed in detail below. .SH DIRECTORY TREE QUOTA The project quota mechanism in XFS can be used to implement a form of directory tree quota, where a specified directory and all of the files and subdirectories below it (i.e. a tree) can be restricted to using a subset of the available space in the filesystem. .PP A managed tree must be setup initially using the .B \-s option to the .B project command. The specified project name or identifier is matched to one or more trees defined in .IR /etc/projects , and these trees are then recursively descended to mark the affected inodes as being part of that tree. This process sets an inode flag and the project identifier on every file in the affected tree. Once this has been done, new files created in the tree will automatically be accounted to the tree based on their project identifier. An attempt to create a hard link to a file in the tree will only succeed if the project identifier matches the project identifier for the tree. The .B xfs_io utility can be used to set the project ID for an arbitrary file, but this can only be done by a privileged user. .PP A previously setup tree can be cleared from project quota control through use of the .B project \-C option, which will recursively descend the tree, clearing the affected inodes from project quota control. .PP Finally, the .B project \-c option can be used to check whether a tree is setup, it reports nothing if the tree is correct, otherwise it reports the paths of inodes which do not have the project ID of the rest of the tree, or if the inode flag is not set. .PP Option .B \-d can be used to limit recursion level (\-1 is infinite, 0 is top level only, 1 is first level ... ). Option .B \-p adds possibility to specify project paths in command line without a need for .I /etc/projects to exist. Note that if projects file exists then it is also used. .SH EXAMPLES Enabling quota enforcement on an XFS filesystem (restrict a user to a set amount of space). .nf .sp .in +5 # mount \-o uquota /dev/xvm/home /home # xfs_quota \-x \-c 'limit bsoft=500m bhard=550m tanya' /home # xfs_quota \-x \-c report /home .in -5 .fi .PP Enabling project quota on an XFS filesystem (restrict files in log file directories to only using 1 gigabyte of space). .nf .sp .in +5 # mount \-o prjquota /dev/xvm/var /var # echo 42:/var/log >> /etc/projects # echo logfiles:42 >> /etc/projid # xfs_quota \-x \-c 'project \-s logfiles' /var # xfs_quota \-x \-c 'limit \-p bhard=1g logfiles' /var .in -5 .fi .PP Same as above without a need for configuration files. .nf .sp .in +5 # rm \-f /etc/projects /etc/projid # mount \-o prjquota /dev/xvm/var /var # xfs_quota \-x \-c 'project \-s \-p /var/log 42' /var # xfs_quota \-x \-c 'limit \-p bhard=1g 42' /var .in -5 .fi .SH CAVEATS XFS implements delayed allocation (aka. allocate-on-flush) and this has implications for the quota subsystem. Since quota accounting can only be done when blocks are actually allocated, it is possible to issue (buffered) writes into a file and not see the usage immediately updated. Only when the data is actually written out, either via one of the kernels flushing mechanisms, or via a manual .BR sync (2), will the usage reported reflect what has actually been written. .PP In addition, the XFS allocation mechanism will always reserve the maximum amount of space required before proceeding with an allocation. If insufficient space for this reservation is available, due to the block quota limit being reached for example, this may result in the allocation failing even though there is sufficient space. Quota enforcement can thus sometimes happen in situations where the user is under quota and the end result of some operation would still have left the user under quota had the operation been allowed to run its course. This additional overhead is typically in the range of tens of blocks. .PP Both of these properties are unavoidable side effects of the way XFS operates, so should be kept in mind when assigning block limits. .SH BUGS Quota support for filesystems with realtime subvolumes is not yet implemented, nor is the quota warning mechanism (the Linux .BR warnquota (8) tool can be used to provide similar functionality on that platform). .SH FILES .PD 0 .TP 20 .I /etc/projects Mapping of numeric project identifiers to directories trees. .TP .I /etc/projid Mapping of numeric project identifiers to project names. .PD .SH IRIX SEE ALSO .BR quotaon (1M), .BR xfs (4). .SH LINUX SEE ALSO .BR warnquota (8), .BR xfs (5). .SH SEE ALSO .BR df (1), .BR mount (1), .BR sync (2), .BR projid (5), .BR projects (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_repair.80000644000000000000000000003654313063067171016356 0ustar .TH xfs_repair 8 .SH NAME xfs_repair \- repair an XFS filesystem .SH SYNOPSIS .B xfs_repair [ .B \-dfLnPv ] [ .B \-m .I maxmem ] [ .BI \-c " subopt" = value ] [ .B \-o .I subopt\c [\c .B =\c .IR value ] ] [ .B \-t .I interval ] [ .B \-l .I logdev ] [ .B \-r .I rtdev ] .I device .br .B xfs_repair \-V .SH DESCRIPTION .B xfs_repair repairs corrupt or damaged XFS filesystems (see .BR xfs (5)). The filesystem is specified using the .I device argument which should be the device name of the disk partition or volume containing the filesystem. If given the name of a block device, .B xfs_repair will attempt to find the raw device associated with the specified block device and will use the raw device instead. .PP Regardless, the filesystem to be repaired must be unmounted, otherwise, the resulting filesystem may be inconsistent or corrupt. .SH OPTIONS .TP .B \-f Specifies that the filesystem image to be processed is stored in a regular file at .I device (see the .B mkfs.xfs \-d .I file option). This might happen if an image copy of a filesystem has been copied or written into an ordinary file. This option implies that any external log or realtime section is also in an ordinary file. .TP .B \-L Force Log Zeroing. Forces .B xfs_repair to zero the log even if it is dirty (contains metadata changes). When using this option the filesystem will likely appear to be corrupt, and can cause the loss of user files and/or data. .TP .BI \-l " logdev" Specifies the device special file where the filesystem's external log resides. Only for those filesystems which use an external log. See the .B mkfs.xfs \-l option, and refer to .BR xfs (5) for a detailed description of the XFS log. .TP .BI \-r " rtdev" Specifies the device special file where the filesystem's realtime section resides. Only for those filesystems which use a realtime section. See the .B mkfs.xfs \-r option, and refer to .BR xfs (5) for a detailed description of the XFS realtime section. .TP .B \-n No modify mode. Specifies that .B xfs_repair should not modify the filesystem but should only scan the filesystem and indicate what repairs would have been made. .TP .B \-P Disable prefetching of inode and directory blocks. Use this option if you find .B xfs_repair gets stuck and stops proceeding. Interrupting a stuck .B xfs_repair is safe. .TP .BI \-m " maxmem" Specifies the approximate maximum amount of memory, in megabytes, to use for .BR xfs_repair . .B xfs_repair has its own internal block cache which will scale out up to the lesser of the process's virtual address limit or about 75% of the system's physical RAM. This option overrides these limits. .IP .B NOTE: These memory limits are only approximate and may use more than the specified limit. .TP .BI \-c " subopt" = value Change filesystem parameters. Refer to .BR xfs_admin (8) for information on changing filesystem parameters. .HP .B \-o .I subopt\c [\c .B =\c .IR value ] .br Override what the program might conclude about the filesystem if left to its own devices. .IP The .IR subopt ions supported are: .RS 1.0i .TP .BI bhash= bhashsize overrides the default buffer cache hash size. The total number of buffer cache entries are limited to 8 times this amount. The default size is set to use up the remainder of 75% of the system's physical RAM size. .TP .BI ag_stride= ags_per_concat_unit This creates additional processing threads to parallel process AGs that span multiple concat units. This can significantly reduce repair times on concat based filesystems. .TP .BI force_geometry Check the filesystem even if geometry information could not be validated. Geometry information can not be validated if only a single allocation group exists and thus we do not have a backup superblock available, or if there are two allocation groups and the two superblocks do not agree on the filesystem geometry. Only use this option if you validated the geometry yourself and know what you are doing. If In doubt run in no modify mode first. .RE .TP .B \-t " interval" Modify reporting interval, specified in seconds. During long runs .B xfs_repair outputs its progress every 15 minutes. Reporting is only activated when ag_stride is enabled. .TP .B \-v Verbose output. May be specified multiple times to increase verbosity. .TP .B \-d Repair dangerously. Allow .B xfs_repair to repair an XFS filesystem mounted read only. This is typically done on a root filesystem from single user mode, immediately followed by a reboot. .TP .B \-V Prints the version number and exits. .SS Checks Performed Inconsistencies corrected include the following: .IP 1. Inode and inode blockmap (addressing) checks: bad magic number in inode, bad magic numbers in inode blockmap blocks, extents out of order, incorrect number of records in inode blockmap blocks, blocks claimed that are not in a legal data area of the filesystem, blocks that are claimed by more than one inode. .IP 2. Inode allocation map checks: bad magic number in inode map blocks, inode state as indicated by map (free or in-use) inconsistent with state indicated by the inode, inodes referenced by the filesystem that do not appear in the inode allocation map, inode allocation map referencing blocks that do not appear to contain inodes. .IP 3. Size checks: number of blocks claimed by inode inconsistent with inode size, directory size not block aligned, inode size not consistent with inode format. .IP 4. Directory checks: bad magic numbers in directory blocks, incorrect number of entries in a directory block, bad freespace information in a directory leaf block, entry pointing to an unallocated (free) or out of range inode, overlapping entries, missing or incorrect dot and dotdot entries, entries out of hashvalue order, incorrect internal directory pointers, directory type not consistent with inode format and size. .IP 5. Pathname checks: files or directories not referenced by a pathname starting from the filesystem root, illegal pathname components. .IP 6. Link count checks: link counts that do not agree with the number of directory references to the inode. .IP 7. Freemap checks: blocks claimed free by the freemap but also claimed by an inode, blocks unclaimed by any inode but not appearing in the freemap. .IP 8. Super Block checks: total free block and/or free i-node count incorrect, filesystem geometry inconsistent, secondary and primary superblocks contradictory. .PP Orphaned files and directories (allocated, in-use but unreferenced) are reconnected by placing them in the .I lost+found directory. The name assigned is the inode number. .SS Disk Errors .B xfs_repair aborts on most disk I/O errors. Therefore, if you are trying to repair a filesystem that was damaged due to a disk drive failure, steps should be taken to ensure that all blocks in the filesystem are readable and writable before attempting to use .B xfs_repair to repair the filesystem. A possible method is using .BR dd (8) to copy the data onto a good disk. .SS lost+found The directory .I lost+found does not have to already exist in the filesystem being repaired. If the directory does not exist, it is automatically created if required. If it already exists, it will be checked for consistency and if valid will be used for additional orphaned files. Invalid .I lost+found directories are removed and recreated. Existing files in a valid .I lost+found are not removed or renamed. .SS Corrupted Superblocks XFS has both primary and secondary superblocks. .B xfs_repair uses information in the primary superblock to automatically find and validate the primary superblock against the secondary superblocks before proceeding. Should the primary be too corrupted to be useful in locating the secondary superblocks, the program scans the filesystem until it finds and validates some secondary superblocks. At that point, it generates a primary superblock. .SS Quotas If quotas are in use, it is possible that .B xfs_repair will clear some or all of the filesystem quota information. If so, the program issues a warning just before it terminates. If all quota information is lost, quotas are disabled and the program issues a warning to that effect. .PP Note that .B xfs_repair does not check the validity of quota limits. It is recommended that you check the quota limit information manually after .BR xfs_repair . Also, space usage information is automatically regenerated the next time the filesystem is mounted with quotas turned on, so the next quota mount of the filesystem may take some time. .SH DIAGNOSTICS .B xfs_repair issues informative messages as it proceeds indicating what it has found that is abnormal or any corrective action that it has taken. Most of the messages are completely understandable only to those who are knowledgeable about the structure of the filesystem. Some of the more common messages are explained here. Note that the language of the messages is slightly different if .B xfs_repair is run in no-modify mode because the program is not changing anything on disk. No-modify mode indicates what it would do to repair the filesystem if run without the no-modify flag. .PP .B disconnected inode .IB ino , .B moving to lost+found .IP An inode numbered .I ino was not connected to the filesystem directory tree and was reconnected to the .I lost+found directory. The inode is assigned the name of its inode number .RI ( ino ). If a .I lost+found directory does not exist, it is automatically created. .PP .B disconnected dir inode .IB ino , .B moving to lost+found .IP As above only the inode is a directory inode. If a directory inode is attached to .IR lost+found , all of its children (if any) stay attached to the directory and therefore get automatically reconnected when the directory is reconnected. .PP .B imap claims in-use inode .I ino .B is free, correcting imap .IP The inode allocation map thinks that inode .I ino is free whereas examination of the inode indicates that the inode may be in use (although it may be disconnected). The program updates the inode allocation map. .PP .B imap claims free inode .I ino .B is in use, correcting imap .IP The inode allocation map thinks that inode .I ino is in use whereas examination of the inode indicates that the inode is not in use and therefore is free. The program updates the inode allocation map. .PP .B resetting inode .I ino .B nlinks from .I x .B to .I y .IP The program detected a mismatch between the number of valid directory entries referencing inode .I ino and the number of references recorded in the inode and corrected the the number in the inode. .PP .I fork-type .B fork in ino .I ino .B claims used block .I bno .IP Inode .I ino claims a block .I bno that is used (claimed) by either another inode or the filesystem itself for metadata storage. The .I fork-type is either .B data or .B attr indicating whether the problem lies in the portion of the inode that tracks regular data or the portion of the inode that stores XFS attributes. If the inode is a real-time (rt) inode, the message says so. Any inode that claims blocks used by the filesystem is deleted. If two or more inodes claim the same block, they are both deleted. .PP .I fork-type .B fork in ino .I ino .B claims dup extent ... .IP Inode .I ino claims a block in an extent known to be claimed more than once. The offset in the inode, start and length of the extent is given. The message is slightly different if the inode is a real-time (rt) inode and the extent is therefore a real-time (rt) extent. .PP .B inode .I ino .B \- bad extent ... .IP An extent record in the blockmap of inode .I ino claims blocks that are out of the legal range of the filesystem. The message supplies the start, end, and file offset of the extent. The message is slightly different if the extent is a real-time (rt) extent. .PP .B bad .I fork-type .B fork in inode .I ino .IP There was something structurally wrong or inconsistent with the data structures that map offsets to filesystem blocks. .PP .B cleared inode .I ino .IP There was something wrong with the inode that was uncorrectable so the program freed the inode. This usually happens because the inode claims blocks that are used by something else or the inode itself is badly corrupted. Typically, this message is preceded by one or more messages indicating why the inode needed to be cleared. .PP .B bad attribute fork in inode .IR ino , .B clearing attr fork .IP There was something wrong with the portion of the inode that stores XFS attributes (the attribute fork) so the program reset the attribute fork. As a result of this, all attributes on that inode are lost. .PP .B correcting nextents for inode .IR ino , .B was .I x .B \- counted .I y .IP The program found that the number of extents used to store the data in the inode is wrong and corrected the number. The message refers to nextents if the count is wrong on the number of extents used to store attribute information. .PP .B entry .I name .B in dir .I dir_ino .B not consistent with .. value .BI ( xxxx ) .B in dir ino .IB ino , .B junking entry .I name .B in directory inode .I dir_ino .IP The entry .I name in directory inode .I dir_ino references a directory inode .IR ino . However, the ..\& entry in directory .I ino does not point back to directory .IR dir_ino , so the program deletes the entry .I name in directory inode .IR dir_ino . If the directory inode .I ino winds up becoming a disconnected inode as a result of this, it is moved to .I lost+found later. .PP .B entry .I name .B in dir .I dir_ino .B references already connected dir ino .IB ino , .B junking entry .I name .B in directory inode .I dir_ino .IP The entry .I name in directory inode .I dir_ino points to a directory inode .I ino that is known to be a child of another directory. Therefore, the entry is invalid and is deleted. This message refers to an entry in a small directory. If this were a large directory, the last phrase would read "will clear entry". .PP .B entry references free inode .I ino .B in directory .IB dir_ino , .B will clear entry .IP An entry in directory inode .I dir_ino references an inode .I ino that is known to be free. The entry is therefore invalid and is deleted. This message refers to a large directory. If the directory were small, the message would read "junking entry ...". .SH EXIT STATUS .B xfs_repair \-n (no modify node) will return a status of 1 if filesystem corruption was detected and 0 if no filesystem corruption was detected. .B xfs_repair run without the \-n option will always return a status code of 0. .SH BUGS The filesystem to be checked and repaired must have been unmounted cleanly using normal system administration procedures (the .BR umount (8) command or system shutdown), not as a result of a crash or system reset. If the filesystem has not been unmounted cleanly, mount it and unmount it cleanly before running .BR xfs_repair . .PP .B xfs_repair does not do a thorough job on XFS extended attributes. The structure of the attribute fork will be consistent, but only the contents of attribute forks that will fit into an inode are checked. This limitation will be fixed in the future. .PP The no-modify mode .RB ( \-n option) is not completely accurate. It does not catch inconsistencies in the freespace and inode maps, particularly lost blocks or subtly corrupted maps (trees). .PP The no-modify mode can generate repeated warnings about the same problems because it cannot fix the problems as they are encountered. .PP If a filesystem fails to be repaired, a metadump image can be generated with .BR xfs_metadump (8) and be sent to an XFS maintainer to be analysed and .B xfs_repair fixed and/or improved. .SH SEE ALSO .BR dd (1), .BR mkfs.xfs (8), .BR umount (8), .BR xfs_admin (8), .BR xfs_metadump (8), .BR xfs (5). xfsprogs-4.9.0+nmu1ubuntu2/man/man8/xfs_rtcp.80000644000000000000000000000230713063067171016033 0ustar .TH xfs_rtcp 8 .SH NAME xfs_rtcp \- XFS realtime copy command .SH SYNOPSIS .B xfs_rtcp [ .B \-e .I extsize ] [ .B -p ] .IR source " ... " target .br .B xfs_rtcp \-V .SH DESCRIPTION .B xfs_rtcp copies a file to the realtime partition on an XFS filesystem. If there is more than one .I source and .IR target , the final argument (the .IR target ) must be a directory which already exists. .SH OPTIONS .TP .BI \-e " extsize" Sets the extent size of the destination realtime file. .TP .B \-p Use if the size of the source file is not an even multiple of the block size of the destination filesystem. When .B \-p is specified .B xfs_rtcp will pad the destination file to a size which is an even multiple of the filesystem block size. This is necessary since the realtime file is created using direct I/O and the minimum I/O is the filesystem block size. .TP .B \-V Prints the version number and exits. .SH SEE ALSO .BR xfs (5), .BR mkfs.xfs (8), .BR mount (8). .SH CAVEATS Currently, realtime partitions are not supported under the Linux version of XFS, and use of a realtime partition .B WILL CAUSE CORRUPTION on the data partition. As such, this command is made available for curious .B DEVELOPERS ONLY at this point in time. xfsprogs-4.9.0+nmu1ubuntu2/mdrestore/0000755000000000000000000000000013063067174014501 5ustar xfsprogs-4.9.0+nmu1ubuntu2/mdrestore/Makefile0000644000000000000000000000071313063067173016141 0ustar # # Copyright (c) 2007 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_mdrestore CFILES = xfs_mdrestore.c LLDLIBS = $(LIBXFS) $(LIBRT) $(LIBPTHREAD) $(LIBUUID) LTDEPENDENCIES = $(LIBXFS) LLDFLAGS = -static default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/mdrestore/xfs_mdrestore.c0000644000000000000000000001560013063067173017532 0ustar /* * Copyright (c) 2007 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "xfs_metadump.h" char *progname; int show_progress = 0; int progress_since_warning = 0; static void fatal(const char *msg, ...) { va_list args; va_start(args, msg); fprintf(stderr, "%s: ", progname); vfprintf(stderr, msg, args); exit(1); } static void print_progress(const char *fmt, ...) { char buf[60]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); buf[sizeof(buf)-1] = '\0'; printf("\r%-59s", buf); fflush(stdout); progress_since_warning = 1; } static void perform_restore( FILE *src_f, int dst_fd, int is_target_file) { xfs_metablock_t *metablock; /* header + index + blocks */ __be64 *block_index; char *block_buffer; int block_size; int max_indices; int cur_index; int mb_count; xfs_metablock_t tmb; xfs_sb_t sb; __int64_t bytes_read; /* * read in first blocks (superblock 0), set "inprogress" flag for it, * read in the rest of the file, and if complete, clear SB 0's * "inprogress flag" */ if (fread(&tmb, sizeof(tmb), 1, src_f) != 1) fatal("error reading from file: %s\n", strerror(errno)); if (be32_to_cpu(tmb.mb_magic) != XFS_MD_MAGIC) fatal("specified file is not a metadata dump\n"); block_size = 1 << tmb.mb_blocklog; max_indices = (block_size - sizeof(xfs_metablock_t)) / sizeof(__be64); metablock = (xfs_metablock_t *)calloc(max_indices + 1, block_size); if (metablock == NULL) fatal("memory allocation failure\n"); mb_count = be16_to_cpu(tmb.mb_count); if (mb_count == 0 || mb_count > max_indices) fatal("bad block count: %u\n", mb_count); block_index = (__be64 *)((char *)metablock + sizeof(xfs_metablock_t)); block_buffer = (char *)metablock + block_size; if (fread(block_index, block_size - sizeof(tmb), 1, src_f) != 1) fatal("error reading from file: %s\n", strerror(errno)); if (block_index[0] != 0) fatal("first block is not the primary superblock\n"); if (fread(block_buffer, mb_count << tmb.mb_blocklog, 1, src_f) != 1) fatal("error reading from file: %s\n", strerror(errno)); libxfs_sb_from_disk(&sb, (xfs_dsb_t *)block_buffer); if (sb.sb_magicnum != XFS_SB_MAGIC) fatal("bad magic number for primary superblock\n"); /* * Normally the upper bound would be simply XFS_MAX_SECTORSIZE * but the metadump format has a maximum number of BBSIZE blocks * it can store in a single metablock. */ if (sb.sb_sectsize < XFS_MIN_SECTORSIZE || sb.sb_sectsize > XFS_MAX_SECTORSIZE || sb.sb_sectsize > max_indices * block_size) fatal("bad sector size %u in metadump image\n", sb.sb_sectsize); ((xfs_dsb_t*)block_buffer)->sb_inprogress = 1; if (is_target_file) { /* ensure regular files are correctly sized */ if (ftruncate(dst_fd, sb.sb_dblocks * sb.sb_blocksize)) fatal("cannot set filesystem image size: %s\n", strerror(errno)); } else { /* ensure device is sufficiently large enough */ char *lb[XFS_MAX_SECTORSIZE] = { NULL }; off64_t off; off = sb.sb_dblocks * sb.sb_blocksize - sizeof(lb); if (pwrite(dst_fd, lb, sizeof(lb), off) < 0) fatal("failed to write last block, is target too " "small? (error: %s)\n", strerror(errno)); } bytes_read = 0; for (;;) { if (show_progress && (bytes_read & ((1 << 20) - 1)) == 0) print_progress("%lld MB read", bytes_read >> 20); for (cur_index = 0; cur_index < mb_count; cur_index++) { if (pwrite(dst_fd, &block_buffer[cur_index << tmb.mb_blocklog], block_size, be64_to_cpu(block_index[cur_index]) << BBSHIFT) < 0) fatal("error writing block %llu: %s\n", be64_to_cpu(block_index[cur_index]) << BBSHIFT, strerror(errno)); } if (mb_count < max_indices) break; if (fread(metablock, block_size, 1, src_f) != 1) fatal("error reading from file: %s\n", strerror(errno)); mb_count = be16_to_cpu(metablock->mb_count); if (mb_count == 0) break; if (mb_count > max_indices) fatal("bad block count: %u\n", mb_count); if (fread(block_buffer, mb_count << tmb.mb_blocklog, 1, src_f) != 1) fatal("error reading from file: %s\n", strerror(errno)); bytes_read += block_size + (mb_count << tmb.mb_blocklog); } if (progress_since_warning) putchar('\n'); memset(block_buffer, 0, sb.sb_sectsize); sb.sb_inprogress = 0; libxfs_sb_to_disk((xfs_dsb_t *)block_buffer, &sb); if (xfs_sb_version_hascrc(&sb)) { xfs_update_cksum(block_buffer, sb.sb_sectsize, offsetof(struct xfs_sb, sb_crc)); } if (pwrite(dst_fd, block_buffer, sb.sb_sectsize, 0) < 0) fatal("error writing primary superblock: %s\n", strerror(errno)); free(metablock); } static void usage(void) { fprintf(stderr, "Usage: %s [-V] [-g] source target\n", progname); exit(1); } extern int platform_check_ismounted(char *, char *, struct stat *, int); int main( int argc, char **argv) { FILE *src_f; int dst_fd; int c; int open_flags; struct stat statbuf; int is_target_file; progname = basename(argv[0]); while ((c = getopt(argc, argv, "gV")) != EOF) { switch (c) { case 'g': show_progress = 1; break; case 'V': printf("%s version %s\n", progname, VERSION); exit(0); default: usage(); } } if (argc - optind != 2) usage(); /* open source */ if (strcmp(argv[optind], "-") == 0) { src_f = stdin; if (isatty(fileno(stdin))) fatal("cannot read from a terminal\n"); } else { src_f = fopen(argv[optind], "rb"); if (src_f == NULL) fatal("cannot open source dump file\n"); } optind++; /* check and open target */ open_flags = O_RDWR; is_target_file = 0; if (stat(argv[optind], &statbuf) < 0) { /* ok, assume it's a file and create it */ open_flags |= O_CREAT; is_target_file = 1; } else if (S_ISREG(statbuf.st_mode)) { open_flags |= O_TRUNC; is_target_file = 1; } else { /* * check to make sure a filesystem isn't mounted on the device */ if (platform_check_ismounted(argv[optind], NULL, &statbuf, 0)) fatal("a filesystem is mounted on target device \"%s\"," " cannot restore to a mounted filesystem.\n", argv[optind]); } dst_fd = open(argv[optind], open_flags, 0644); if (dst_fd < 0) fatal("couldn't open target \"%s\"\n", argv[optind]); perform_restore(src_f, dst_fd, is_target_file); close(dst_fd); if (src_f != stdin) fclose(src_f); return 0; } xfsprogs-4.9.0+nmu1ubuntu2/mkfs/0000755000000000000000000000000013063067174013435 5ustar xfsprogs-4.9.0+nmu1ubuntu2/mkfs/Makefile0000644000000000000000000000103613063067170015071 0ustar # # Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = mkfs.xfs HFILES = CFILES = maxtrres.c proto.c xfs_mkfs.c LLDLIBS += $(LIBXFS) $(LIBXCMD) $(LIBRT) $(LIBPTHREAD) $(LIBBLKID) $(LIBUUID) LTDEPENDENCIES += $(LIBXFS) $(LIBXCMD) LLDFLAGS = -static-libtool-libs default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/mkfs/maxtrres.c0000644000000000000000000000476713063067170015460 0ustar /* * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * maxtrres.c * * Compute the maximum transaction reservation for a legal combination * of sector size, block size, inode size, directory version, and * directory block size. */ #include "libxfs.h" #include "xfs_multidisk.h" int max_trans_res( unsigned long agsize, int crcs_enabled, int dirversion, int sectorlog, int blocklog, int inodelog, int dirblocklog, int logversion, int log_sunit, int finobt, int rmapbt, int reflink) { xfs_sb_t *sbp; xfs_mount_t mount; int maxfsb; memset(&mount, 0, sizeof(mount)); sbp = &mount.m_sb; sbp->sb_magicnum = XFS_SB_MAGIC; sbp->sb_sectlog = sectorlog; sbp->sb_sectsize = 1 << sbp->sb_sectlog; sbp->sb_blocklog = blocklog; sbp->sb_blocksize = 1 << blocklog; sbp->sb_agblocks = agsize; sbp->sb_inodelog = inodelog; sbp->sb_inopblog = blocklog - inodelog; sbp->sb_inodesize = 1 << inodelog; sbp->sb_inopblock = 1 << (blocklog - inodelog); sbp->sb_dirblklog = dirblocklog - blocklog; if (log_sunit > 0) { log_sunit <<= blocklog; logversion = 2; } else log_sunit = 1; sbp->sb_logsunit = log_sunit; sbp->sb_versionnum = (crcs_enabled ? XFS_SB_VERSION_5 : XFS_SB_VERSION_4) | (dirversion == 2 ? XFS_SB_VERSION_DIRV2BIT : 0) | (logversion > 1 ? XFS_SB_VERSION_LOGV2BIT : 0) | XFS_DFL_SB_VERSION_BITS; if (finobt) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_FINOBT; if (rmapbt) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT; if (reflink) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK; libxfs_mount(&mount, sbp, 0,0,0,0); maxfsb = libxfs_log_calc_minimum_size(&mount); libxfs_umount(&mount); #if 0 printf("#define\tMAXTRRES_S%d_B%d_I%d_D%d_V%d_LSU%d\t%d\n", sectorlog, blocklog, inodelog, dirblocklog, dirversion, log_sunit, maxfsb); #endif return maxfsb; } xfsprogs-4.9.0+nmu1ubuntu2/mkfs/proto.c0000644000000000000000000004363113063067170014747 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #include "xfs_multidisk.h" /* * Prototypes for internal functions. */ static char *getstr(char **pp); static void fail(char *msg, int i); static struct xfs_trans * getres(struct xfs_mount *mp, uint blocks); static void rsvfile(xfs_mount_t *mp, xfs_inode_t *ip, long long len); static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, struct xfs_defer_ops *dfops, xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len); static char *newregfile(char **pp, int *len); static void rtinit(xfs_mount_t *mp); static long filesize(int fd); /* * Use this for block reservations needed for mkfs's conditions * (basically no fragmentation). */ #define MKFS_BLOCKRES_INODE \ ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1))) #define MKFS_BLOCKRES(rb) \ ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \ (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb))) static long long getnum( const char *str, unsigned int blksize, unsigned int sectsize, bool convert) { long long i; char *sp; if (convert) return cvtnum(blksize, sectsize, str); i = strtoll(str, &sp, 0); if (i == 0 && sp == str) return -1LL; if (*sp != '\0') return -1LL; /* trailing garbage */ return i; } char * setup_proto( char *fname) { char *buf = NULL; static char dflt[] = "d--755 0 0 $"; int fd; long size; if (!fname) return dflt; if ((fd = open(fname, O_RDONLY)) < 0 || (size = filesize(fd)) < 0) { fprintf(stderr, _("%s: failed to open %s: %s\n"), progname, fname, strerror(errno)); goto out_fail; } buf = malloc(size + 1); if (read(fd, buf, size) < size) { fprintf(stderr, _("%s: read failed on %s: %s\n"), progname, fname, strerror(errno)); goto out_fail; } if (buf[size - 1] != '\n') { fprintf(stderr, _("%s: proto file %s premature EOF\n"), progname, fname); goto out_fail; } buf[size] = '\0'; /* * Skip past the stuff there for compatibility, a string and 2 numbers. */ (void)getstr(&buf); /* boot image name */ (void)getnum(getstr(&buf), 0, 0, false); /* block count */ (void)getnum(getstr(&buf), 0, 0, false); /* inode count */ close(fd); return buf; out_fail: if (fd >= 0) close(fd); free(buf); exit(1); } static void fail( char *msg, int i) { fprintf(stderr, "%s: %s [%d - %s]\n", progname, msg, i, strerror(i)); exit(1); } void res_failed( int i) { fail(_("cannot reserve space"), i); } static struct xfs_trans * getres( struct xfs_mount *mp, uint blocks) { struct xfs_trans *tp; int i; uint r; for (i = 0, r = MKFS_BLOCKRES(blocks); r >= blocks; r--) { struct xfs_trans_res tres = {0}; i = -libxfs_trans_alloc(mp, &tres, r, 0, 0, &tp); if (i == 0) return tp; } res_failed(i); /* NOTREACHED */ return NULL; } static char * getstr( char **pp) { char c; char *p; char *rval; p = *pp; while ((c = *p)) { switch (c) { case ' ': case '\t': case '\n': p++; continue; case ':': p++; while (*p++ != '\n') ; continue; default: rval = p; while (c != ' ' && c != '\t' && c != '\n' && c != '\0') c = *++p; *p++ = '\0'; *pp = p; return rval; } } if (c != '\0') { fprintf(stderr, _("%s: premature EOF in prototype file\n"), progname); exit(1); } return NULL; } static void rsvfile( xfs_mount_t *mp, xfs_inode_t *ip, long long llen) { int error; xfs_trans_t *tp; struct xfs_trans_res tres = {0}; error = -libxfs_alloc_file_space(ip, 0, llen, 1, 0); if (error) { fail(_("error reserving space for a file"), error); exit(1); } /* * update the inode timestamp, mode, and prealloc flag bits */ libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp); libxfs_trans_ijoin(tp, ip, 0); VFS_I(ip)->i_mode &= ~S_ISUID; /* * Note that we don't have to worry about mandatory * file locking being disabled here because we only * clear the S_ISGID bit if the Group execute bit is * on, but if it was on then mandatory locking wouldn't * have been enabled. */ if (VFS_I(ip)->i_mode & S_IXGRP) VFS_I(ip)->i_mode &= ~S_ISGID; libxfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); libxfs_trans_commit(tp); } static int newfile( xfs_trans_t *tp, xfs_inode_t *ip, struct xfs_defer_ops *dfops, xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len) { xfs_buf_t *bp; xfs_daddr_t d; int error; int flags; xfs_bmbt_irec_t map; xfs_mount_t *mp; xfs_extlen_t nb; int nmap; flags = 0; mp = ip->i_mount; if (dolocal && len <= XFS_IFORK_DSIZE(ip)) { libxfs_idata_realloc(ip, len, XFS_DATA_FORK); if (buf) memmove(ip->i_df.if_u1.if_data, buf, len); ip->i_d.di_size = len; ip->i_df.if_flags &= ~XFS_IFEXTENTS; ip->i_df.if_flags |= XFS_IFINLINE; ip->i_d.di_format = XFS_DINODE_FMT_LOCAL; flags = XFS_ILOG_DDATA; } else if (len > 0) { nb = XFS_B_TO_FSB(mp, len); nmap = 1; error = -libxfs_bmapi_write(tp, ip, 0, nb, 0, first, nb, &map, &nmap, dfops); if (error) { fail(_("error allocating space for a file"), error); } if (nmap != 1) { fprintf(stderr, _("%s: cannot allocate space for file\n"), progname); exit(1); } d = XFS_FSB_TO_DADDR(mp, map.br_startblock); bp = libxfs_trans_get_buf(logit ? tp : 0, mp->m_dev, d, nb << mp->m_blkbb_log, 0); memmove(XFS_BUF_PTR(bp), buf, len); if (len < XFS_BUF_COUNT(bp)) memset(XFS_BUF_PTR(bp) + len, 0, XFS_BUF_COUNT(bp) - len); if (logit) libxfs_trans_log_buf(tp, bp, 0, XFS_BUF_COUNT(bp) - 1); else libxfs_writebuf(bp, LIBXFS_EXIT_ON_FAILURE); } ip->i_d.di_size = len; return flags; } static char * newregfile( char **pp, int *len) { char *buf; int fd; char *fname; long size; fname = getstr(pp); if ((fd = open(fname, O_RDONLY)) < 0 || (size = filesize(fd)) < 0) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, fname, strerror(errno)); exit(1); } if ((*len = (int)size)) { buf = malloc(size); if (read(fd, buf, size) < size) { fprintf(stderr, _("%s: read failed on %s: %s\n"), progname, fname, strerror(errno)); exit(1); } } else buf = 0; close(fd); return buf; } static void newdirent( xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *pip, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, struct xfs_defer_ops *dfops) { int error; int rsv; rsv = XFS_DIRENTER_SPACE_RES(mp, name->len); error = -libxfs_dir_createname(tp, pip, name, inum, first, dfops, rsv); if (error) fail(_("directory createname error"), error); } static void newdirectory( xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *dp, xfs_inode_t *pdp) { int error; error = -libxfs_dir_init(tp, dp, pdp); if (error) fail(_("directory create error"), error); } static void parseproto( xfs_mount_t *mp, xfs_inode_t *pip, struct fsxattr *fsxp, char **pp, char *name) { #define IF_REGULAR 0 #define IF_RESERVED 1 #define IF_BLOCK 2 #define IF_CHAR 3 #define IF_DIRECTORY 4 #define IF_SYMLINK 5 #define IF_FIFO 6 char *buf; int error; xfs_fsblock_t first; int flags; struct xfs_defer_ops dfops; int fmt; int i; xfs_inode_t *ip; int len; long long llen; int majdev; int mindev; int mode; char *mstr; xfs_trans_t *tp; int val; int isroot = 0; cred_t creds; char *value; struct xfs_name xname; memset(&creds, 0, sizeof(creds)); mstr = getstr(pp); switch (mstr[0]) { case '-': fmt = IF_REGULAR; break; case 'r': fmt = IF_RESERVED; break; case 'b': fmt = IF_BLOCK; break; case 'c': fmt = IF_CHAR; break; case 'd': fmt = IF_DIRECTORY; break; case 'l': fmt = IF_SYMLINK; break; case 'p': fmt = IF_FIFO; break; default: fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } mode = 0; switch (mstr[1]) { case '-': break; case 'u': mode |= S_ISUID; break; default: fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } switch (mstr[2]) { case '-': break; case 'g': mode |= S_ISGID; break; default: fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } val = 0; for (i = 3; i < 6; i++) { if (mstr[i] < '0' || mstr[i] > '7') { fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } val = val * 8 + mstr[i] - '0'; } mode |= val; creds.cr_uid = (int)getnum(getstr(pp), 0, 0, false); creds.cr_gid = (int)getnum(getstr(pp), 0, 0, false); xname.name = (unsigned char *)name; xname.len = name ? strlen(name) : 0; xname.type = 0; flags = XFS_ILOG_CORE; libxfs_defer_init(&dfops, &first); switch (fmt) { case IF_REGULAR: buf = newregfile(pp, &len); tp = getres(mp, XFS_B_TO_FSB(mp, len)); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); flags |= newfile(tp, ip, &dfops, &first, 0, 0, buf, len); if (buf) free(buf); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_REG_FILE; newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); break; case IF_RESERVED: /* pre-allocated space only */ value = getstr(pp); llen = getnum(value, mp->m_sb.sb_blocksize, mp->m_sb.sb_sectsize, true); if (llen < 0) { fprintf(stderr, _("%s: Bad value %s for proto file %s\n"), progname, value, name); exit(1); } tp = getres(mp, XFS_B_TO_FSB(mp, llen)); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode pre-allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_REG_FILE; newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); libxfs_trans_log_inode(tp, ip, flags); error = -libxfs_defer_finish(&tp, &dfops, ip); if (error) fail(_("Pre-allocated file creation failed"), error); libxfs_trans_commit(tp); rsvfile(mp, ip, llen); IRELE(ip); return; case IF_BLOCK: tp = getres(mp, 0); majdev = getnum(getstr(pp), 0, 0, false); mindev = getnum(getstr(pp), 0, 0, false); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFBLK, 1, IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); if (error) { fail(_("Inode allocation failed"), error); } libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_BLKDEV; newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); flags |= XFS_ILOG_DEV; break; case IF_CHAR: tp = getres(mp, 0); majdev = getnum(getstr(pp), 0, 0, false); mindev = getnum(getstr(pp), 0, 0, false); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFCHR, 1, IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_CHRDEV; newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); flags |= XFS_ILOG_DEV; break; case IF_FIFO: tp = getres(mp, 0); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFIFO, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_FIFO; newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); break; case IF_SYMLINK: buf = getstr(pp); len = (int)strlen(buf); tp = getres(mp, XFS_B_TO_FSB(mp, len)); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFLNK, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_SYMLINK; newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); break; case IF_DIRECTORY: tp = getres(mp, 0); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFDIR, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); inc_nlink(VFS_I(ip)); /* account for . */ if (!pip) { pip = ip; mp->m_sb.sb_rootino = ip->i_ino; libxfs_log_sb(tp); isroot = 1; } else { libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_DIR; newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); inc_nlink(VFS_I(pip)); libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); } newdirectory(mp, tp, ip, pip); libxfs_trans_log_inode(tp, ip, flags); error = -libxfs_defer_finish(&tp, &dfops, ip); if (error) fail(_("Directory creation failed"), error); libxfs_trans_commit(tp); /* * RT initialization. Do this here to ensure that * the RT inodes get placed after the root inode. */ if (isroot) rtinit(mp); tp = NULL; for (;;) { name = getstr(pp); if (!name) break; if (strcmp(name, "$") == 0) break; parseproto(mp, ip, fsxp, pp, name); } IRELE(ip); return; default: ASSERT(0); fail(_("Unknown format"), EINVAL); } libxfs_trans_log_inode(tp, ip, flags); error = -libxfs_defer_finish(&tp, &dfops, ip); if (error) { fail(_("Error encountered creating file from prototype file"), error); } libxfs_trans_commit(tp); IRELE(ip); } void parse_proto( xfs_mount_t *mp, struct fsxattr *fsx, char **pp) { parseproto(mp, NULL, fsx, pp, NULL); } /* * Allocate the realtime bitmap and summary inodes, and fill in data if any. */ static void rtinit( xfs_mount_t *mp) { xfs_fileoff_t bno; xfs_fileoff_t ebno; xfs_bmbt_irec_t *ep; int error; xfs_fsblock_t first; struct xfs_defer_ops dfops; int i; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; xfs_extlen_t nsumblocks; int nmap; xfs_inode_t *rbmip; xfs_inode_t *rsumip; xfs_trans_t *tp; struct cred creds; struct fsxattr fsxattrs; struct xfs_trans_res tres = {0}; /* * First, allocate the inodes. */ i = -libxfs_trans_alloc(mp, &tres, MKFS_BLOCKRES_INODE, 0, 0, &tp); if (i) res_failed(i); memset(&creds, 0, sizeof(creds)); memset(&fsxattrs, 0, sizeof(fsxattrs)); error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0, &creds, &fsxattrs, &rbmip); if (error) { fail(_("Realtime bitmap inode allocation failed"), error); } /* * Do our thing with rbmip before allocating rsumip, * because the next call to ialloc() may * commit the transaction in which rbmip was allocated. */ mp->m_sb.sb_rbmino = rbmip->i_ino; rbmip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize; rbmip->i_d.di_flags = XFS_DIFLAG_NEWRTBM; *(__uint64_t *)&VFS_I(rbmip)->i_atime = 0; libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE); libxfs_log_sb(tp); mp->m_rbmip = rbmip; error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0, &creds, &fsxattrs, &rsumip); if (error) { fail(_("Realtime summary inode allocation failed"), error); } mp->m_sb.sb_rsumino = rsumip->i_ino; rsumip->i_d.di_size = mp->m_rsumsize; libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE); libxfs_log_sb(tp); libxfs_trans_commit(tp); mp->m_rsumip = rsumip; /* * Next, give the bitmap file some zero-filled blocks. */ i = -libxfs_trans_alloc(mp, &tres, mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), 0, 0, &tp); if (i) res_failed(i); libxfs_trans_ijoin(tp, rbmip, 0); bno = 0; libxfs_defer_init(&dfops, &first); while (bno < mp->m_sb.sb_rbmblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, rbmip, bno, (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno), 0, &first, mp->m_sb.sb_rbmblocks, map, &nmap, &dfops); if (error) { fail(_("Allocation of the realtime bitmap failed"), error); } for (i = 0, ep = map; i < nmap; i++, ep++) { libxfs_device_zero(mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, ep->br_startblock), XFS_FSB_TO_BB(mp, ep->br_blockcount)); bno += ep->br_blockcount; } } error = -libxfs_defer_finish(&tp, &dfops, rbmip); if (error) { fail(_("Completion of the realtime bitmap failed"), error); } libxfs_trans_commit(tp); /* * Give the summary file some zero-filled blocks. */ nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; i = -libxfs_trans_alloc(mp, &tres, nsumblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), 0, 0, &tp); if (i) res_failed(i); libxfs_trans_ijoin(tp, rsumip, 0); bno = 0; libxfs_defer_init(&dfops, &first); while (bno < nsumblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, rsumip, bno, (xfs_extlen_t)(nsumblocks - bno), 0, &first, nsumblocks, map, &nmap, &dfops); if (error) { fail(_("Allocation of the realtime summary failed"), error); } for (i = 0, ep = map; i < nmap; i++, ep++) { libxfs_device_zero(mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, ep->br_startblock), XFS_FSB_TO_BB(mp, ep->br_blockcount)); bno += ep->br_blockcount; } } error = -libxfs_defer_finish(&tp, &dfops, rsumip); if (error) { fail(_("Completion of the realtime summary failed"), error); } libxfs_trans_commit(tp); /* * Free the whole area using transactions. * Do one transaction per bitmap block. */ for (bno = 0; bno < mp->m_sb.sb_rextents; bno = ebno) { i = -libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp); if (i) res_failed(i); libxfs_trans_ijoin(tp, rbmip, 0); libxfs_defer_init(&dfops, &first); ebno = XFS_RTMIN(mp->m_sb.sb_rextents, bno + NBBY * mp->m_sb.sb_blocksize); error = -libxfs_rtfree_extent(tp, bno, (xfs_extlen_t)(ebno-bno)); if (error) { fail(_("Error initializing the realtime space"), error); } error = -libxfs_defer_finish(&tp, &dfops, rbmip); if (error) { fail(_("Error completing the realtime space"), error); } libxfs_trans_commit(tp); } } static long filesize( int fd) { struct stat stb; if (fstat(fd, &stb) < 0) return -1; return (long)stb.st_size; } xfsprogs-4.9.0+nmu1ubuntu2/mkfs/xfs_mkfs.c0000644000000000000000000026347413063067170015435 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include #ifdef ENABLE_BLKID # include #endif /* ENABLE_BLKID */ #include "xfs_multidisk.h" #include "libxcmd.h" /* * Prototypes for internal functions. */ static void conflict(char opt, char *tab[], int oldidx, int newidx); static void illegal(const char *value, const char *opt); static __attribute__((noreturn)) void usage (void); static __attribute__((noreturn)) void reqval(char opt, char *tab[], int idx); static void respec(char opt, char *tab[], int idx); static void unknown(char opt, char *s); static int ispow2(unsigned int i); /* * The configured block and sector sizes are defined as global variables so * that they don't need to be passed to functions that require them. */ unsigned int blocksize; unsigned int sectorsize; #define MAX_SUBOPTS 16 #define SUBOPT_NEEDS_VAL (-1LL) #define MAX_CONFLICTS 8 #define LAST_CONFLICT (-1) /* * Table for parsing mkfs parameters. * * Description of the structure members follows: * * name MANDATORY * Name is a single char, e.g., for '-d file', name is 'd'. * * subopts MANDATORY * Subopts is a list of strings naming suboptions. In the example above, * it would contain "file". The last entry of this list has to be NULL. * * subopt_params MANDATORY * This is a list of structs tied with subopts. For each entry in subopts, * a corresponding entry has to be defined: * * subopt_params struct: * index MANDATORY * This number, starting from zero, denotes which item in subopt_params * it is. The index has to be the same as is the order in subopts list, * so we can access the right item both in subopt_param and subopts. * * seen INTERNAL * Do not set this flag when definning a subopt. It is used to remeber that * this subopt was already seen, for example for conflicts detection. * * str_seen INTERNAL * Do not set. It is used internally for respecification, when some options * has to be parsed twice - at first as a string, then later as a number. * * convert OPTIONAL * A flag signalling whether the user-given value can use suffixes. * If you want to allow the use of user-friendly values like 13k, 42G, * set it to true. * * is_power_2 OPTIONAL * An optional flag for subopts where the given value has to be a power * of two. * * conflicts MANDATORY * If your subopt is in a conflict with some other option, specify it. * Accepts the .index values of the conflicting subopts and the last * member of this list has to be LAST_CONFLICT. * * minval, maxval OPTIONAL * These options are used for automatic range check and they have to be * always used together in pair. If you don't want to limit the max value, * use something like UINT_MAX. If no value is given, then you must either * supply your own validation, or refuse any value in the 'case * X_SOMETHING' block. If you forget to define the min and max value, but * call a standard function for validating user's value, it will cause an * error message notifying you about this issue. * * (Said in another way, you can't have minval and maxval both equal * to zero. But if one value is different: minval=0 and maxval=1, * then it is OK.) * * defaultval MANDATORY * The value used if user specifies the subopt, but no value. * If the subopt accepts some values (-d file=[1|0]), then this * sets what is used with simple specifying the subopt (-d file). * A special SUBOPT_NEEDS_VAL can be used to require a user-given * value in any case. */ struct opt_params { const char name; const char *subopts[MAX_SUBOPTS]; struct subopt_param { int index; bool seen; bool str_seen; bool convert; bool is_power_2; int conflicts[MAX_CONFLICTS]; long long minval; long long maxval; long long defaultval; } subopt_params[MAX_SUBOPTS]; }; struct opt_params bopts = { .name = 'b', .subopts = { #define B_LOG 0 "log", #define B_SIZE 1 "size", NULL }, .subopt_params = { { .index = B_LOG, .conflicts = { B_SIZE, LAST_CONFLICT }, .minval = XFS_MIN_BLOCKSIZE_LOG, .maxval = XFS_MAX_BLOCKSIZE_LOG, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = B_SIZE, .convert = true, .is_power_2 = true, .conflicts = { B_LOG, LAST_CONFLICT }, .minval = XFS_MIN_BLOCKSIZE, .maxval = XFS_MAX_BLOCKSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, }, }; struct opt_params dopts = { .name = 'd', .subopts = { #define D_AGCOUNT 0 "agcount", #define D_FILE 1 "file", #define D_NAME 2 "name", #define D_SIZE 3 "size", #define D_SUNIT 4 "sunit", #define D_SWIDTH 5 "swidth", #define D_AGSIZE 6 "agsize", #define D_SU 7 "su", #define D_SW 8 "sw", #define D_SECTLOG 9 "sectlog", #define D_SECTSIZE 10 "sectsize", #define D_NOALIGN 11 "noalign", #define D_RTINHERIT 12 "rtinherit", #define D_PROJINHERIT 13 "projinherit", #define D_EXTSZINHERIT 14 "extszinherit", NULL }, .subopt_params = { { .index = D_AGCOUNT, .conflicts = { D_AGSIZE, LAST_CONFLICT }, .minval = 1, .maxval = XFS_MAX_AGNUMBER, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_FILE, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = D_NAME, .conflicts = { LAST_CONFLICT }, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_SIZE, .conflicts = { LAST_CONFLICT }, .convert = true, .minval = XFS_AG_MIN_BYTES, .maxval = LLONG_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_SUNIT, .conflicts = { D_NOALIGN, D_SU, D_SW, LAST_CONFLICT }, .minval = 0, .maxval = UINT_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_SWIDTH, .conflicts = { D_NOALIGN, D_SU, D_SW, LAST_CONFLICT }, .minval = 0, .maxval = UINT_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_AGSIZE, .conflicts = { D_AGCOUNT, LAST_CONFLICT }, .convert = true, .minval = XFS_AG_MIN_BYTES, .maxval = XFS_AG_MAX_BYTES, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_SU, .conflicts = { D_NOALIGN, D_SUNIT, D_SWIDTH, LAST_CONFLICT }, .convert = true, .minval = 0, .maxval = UINT_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_SW, .conflicts = { D_NOALIGN, D_SUNIT, D_SWIDTH, LAST_CONFLICT }, .minval = 0, .maxval = UINT_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_SECTLOG, .conflicts = { D_SECTSIZE, LAST_CONFLICT }, .minval = XFS_MIN_SECTORSIZE_LOG, .maxval = XFS_MAX_SECTORSIZE_LOG, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_SECTSIZE, .conflicts = { D_SECTLOG, LAST_CONFLICT }, .convert = true, .is_power_2 = true, .minval = XFS_MIN_SECTORSIZE, .maxval = XFS_MAX_SECTORSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_NOALIGN, .conflicts = { D_SU, D_SW, D_SUNIT, D_SWIDTH, LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = D_RTINHERIT, .conflicts = { LAST_CONFLICT }, .minval = 1, .maxval = 1, .defaultval = 1, }, { .index = D_PROJINHERIT, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = UINT_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = D_EXTSZINHERIT, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = UINT_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, }, }; struct opt_params iopts = { .name = 'i', .subopts = { #define I_ALIGN 0 "align", #define I_LOG 1 "log", #define I_MAXPCT 2 "maxpct", #define I_PERBLOCK 3 "perblock", #define I_SIZE 4 "size", #define I_ATTR 5 "attr", #define I_PROJID32BIT 6 "projid32bit", #define I_SPINODES 7 "sparse", NULL }, .subopt_params = { { .index = I_ALIGN, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = I_LOG, .conflicts = { I_PERBLOCK, I_SIZE, LAST_CONFLICT }, .minval = XFS_DINODE_MIN_LOG, .maxval = XFS_DINODE_MAX_LOG, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = I_MAXPCT, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 100, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = I_PERBLOCK, .conflicts = { I_LOG, I_SIZE, LAST_CONFLICT }, .is_power_2 = true, .minval = XFS_MIN_INODE_PERBLOCK, .maxval = XFS_MAX_BLOCKSIZE / XFS_DINODE_MIN_SIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = I_SIZE, .conflicts = { I_PERBLOCK, I_LOG, LAST_CONFLICT }, .is_power_2 = true, .minval = XFS_DINODE_MIN_SIZE, .maxval = XFS_DINODE_MAX_SIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = I_ATTR, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 2, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = I_PROJID32BIT, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = I_SPINODES, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, }, }; struct opt_params lopts = { .name = 'l', .subopts = { #define L_AGNUM 0 "agnum", #define L_INTERNAL 1 "internal", #define L_SIZE 2 "size", #define L_VERSION 3 "version", #define L_SUNIT 4 "sunit", #define L_SU 5 "su", #define L_DEV 6 "logdev", #define L_SECTLOG 7 "sectlog", #define L_SECTSIZE 8 "sectsize", #define L_FILE 9 "file", #define L_NAME 10 "name", #define L_LAZYSBCNTR 11 "lazy-count", NULL }, .subopt_params = { { .index = L_AGNUM, .conflicts = { L_DEV, LAST_CONFLICT }, .minval = 0, .maxval = UINT_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_INTERNAL, .conflicts = { L_FILE, L_DEV, LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = L_SIZE, .conflicts = { LAST_CONFLICT }, .convert = true, .minval = 2 * 1024 * 1024LL, /* XXX: XFS_MIN_LOG_BYTES */ .maxval = XFS_MAX_LOG_BYTES, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_VERSION, .conflicts = { LAST_CONFLICT }, .minval = 1, .maxval = 2, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_SUNIT, .conflicts = { L_SU, LAST_CONFLICT }, .minval = 1, .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE), .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_SU, .conflicts = { L_SUNIT, LAST_CONFLICT }, .convert = true, .minval = BBTOB(1), .maxval = XLOG_MAX_RECORD_BSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_DEV, .conflicts = { L_AGNUM, L_INTERNAL, LAST_CONFLICT }, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_SECTLOG, .conflicts = { L_SECTSIZE, LAST_CONFLICT }, .minval = XFS_MIN_SECTORSIZE_LOG, .maxval = XFS_MAX_SECTORSIZE_LOG, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_SECTSIZE, .conflicts = { L_SECTLOG, LAST_CONFLICT }, .convert = true, .is_power_2 = true, .minval = XFS_MIN_SECTORSIZE, .maxval = XFS_MAX_SECTORSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_FILE, .conflicts = { L_INTERNAL, LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = L_NAME, .conflicts = { L_AGNUM, L_INTERNAL, LAST_CONFLICT }, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = L_LAZYSBCNTR, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, }, }; struct opt_params nopts = { .name = 'n', .subopts = { #define N_LOG 0 "log", #define N_SIZE 1 "size", #define N_VERSION 2 "version", #define N_FTYPE 3 "ftype", NULL, }, .subopt_params = { { .index = N_LOG, .conflicts = { N_SIZE, LAST_CONFLICT }, .minval = XFS_MIN_REC_DIRSIZE, .maxval = XFS_MAX_BLOCKSIZE_LOG, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = N_SIZE, .conflicts = { N_LOG, LAST_CONFLICT }, .convert = true, .is_power_2 = true, .minval = 1 << XFS_MIN_REC_DIRSIZE, .maxval = XFS_MAX_BLOCKSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = N_VERSION, .conflicts = { LAST_CONFLICT }, .minval = 2, .maxval = 2, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = N_FTYPE, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, }, }; struct opt_params ropts = { .name = 'r', .subopts = { #define R_EXTSIZE 0 "extsize", #define R_SIZE 1 "size", #define R_DEV 2 "rtdev", #define R_FILE 3 "file", #define R_NAME 4 "name", #define R_NOALIGN 5 "noalign", NULL }, .subopt_params = { { .index = R_EXTSIZE, .conflicts = { LAST_CONFLICT }, .convert = true, .minval = XFS_MIN_RTEXTSIZE, .maxval = XFS_MAX_RTEXTSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = R_SIZE, .conflicts = { LAST_CONFLICT }, .convert = true, .minval = 0, .maxval = LLONG_MAX, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = R_DEV, .conflicts = { LAST_CONFLICT }, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = R_FILE, .minval = 0, .maxval = 1, .defaultval = 1, .conflicts = { LAST_CONFLICT }, }, { .index = R_NAME, .conflicts = { LAST_CONFLICT }, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = R_NOALIGN, .minval = 0, .maxval = 1, .defaultval = 1, .conflicts = { LAST_CONFLICT }, }, }, }; struct opt_params sopts = { .name = 's', .subopts = { #define S_LOG 0 "log", #define S_SECTLOG 1 "sectlog", #define S_SIZE 2 "size", #define S_SECTSIZE 3 "sectsize", NULL }, .subopt_params = { { .index = S_LOG, .conflicts = { S_SIZE, S_SECTSIZE, LAST_CONFLICT }, .minval = XFS_MIN_SECTORSIZE_LOG, .maxval = XFS_MAX_SECTORSIZE_LOG, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = S_SECTLOG, .conflicts = { S_SIZE, S_SECTSIZE, LAST_CONFLICT }, .minval = XFS_MIN_SECTORSIZE_LOG, .maxval = XFS_MAX_SECTORSIZE_LOG, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = S_SIZE, .conflicts = { S_LOG, S_SECTLOG, LAST_CONFLICT }, .convert = true, .is_power_2 = true, .minval = XFS_MIN_SECTORSIZE, .maxval = XFS_MAX_SECTORSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = S_SECTSIZE, .conflicts = { S_LOG, S_SECTLOG, LAST_CONFLICT }, .convert = true, .is_power_2 = true, .minval = XFS_MIN_SECTORSIZE, .maxval = XFS_MAX_SECTORSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, }, }; struct opt_params mopts = { .name = 'm', .subopts = { #define M_CRC 0 "crc", #define M_FINOBT 1 "finobt", #define M_UUID 2 "uuid", #define M_RMAPBT 3 "rmapbt", #define M_REFLINK 4 "reflink", NULL }, .subopt_params = { { .index = M_CRC, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = M_FINOBT, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 1, }, { .index = M_UUID, .conflicts = { LAST_CONFLICT }, .defaultval = SUBOPT_NEEDS_VAL, }, { .index = M_RMAPBT, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 0, }, { .index = M_REFLINK, .conflicts = { LAST_CONFLICT }, .minval = 0, .maxval = 1, .defaultval = 0, }, }, }; #define TERABYTES(count, blog) ((__uint64_t)(count) << (40 - (blog))) #define GIGABYTES(count, blog) ((__uint64_t)(count) << (30 - (blog))) #define MEGABYTES(count, blog) ((__uint64_t)(count) << (20 - (blog))) /* * Use this macro before we have superblock and mount structure */ #define DTOBT(d) ((xfs_rfsblock_t)((d) >> (blocklog - BBSHIFT))) /* * Use this for block reservations needed for mkfs's conditions * (basically no fragmentation). */ #define MKFS_BLOCKRES_INODE \ ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1))) #define MKFS_BLOCKRES(rb) \ ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \ (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb))) /* amount (in bytes) we zero at the beginning and end of the device to * remove traces of other filesystems, raid superblocks, etc. */ #define WHACK_SIZE (128 * 1024) /* * Convert lsu to lsunit for 512 bytes blocks and check validity of the values. */ static void calc_stripe_factors( int dsu, int dsw, int dsectsz, int lsu, int lsectsz, int *dsunit, int *dswidth, int *lsunit) { /* Handle data sunit/swidth options */ if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) { fprintf(stderr, _("both data sunit and data swidth options " "must be specified\n")); usage(); } if (dsu || dsw) { if ((dsu && !dsw) || (!dsu && dsw)) { fprintf(stderr, _("both data su and data sw options " "must be specified\n")); usage(); } if (dsu % dsectsz) { fprintf(stderr, _("data su must be a multiple of the " "sector size (%d)\n"), dsectsz); usage(); } *dsunit = (int)BTOBBT(dsu); *dswidth = *dsunit * dsw; } if (*dsunit && (*dswidth % *dsunit != 0)) { fprintf(stderr, _("data stripe width (%d) must be a multiple of the " "data stripe unit (%d)\n"), *dswidth, *dsunit); usage(); } /* Handle log sunit options */ if (lsu) *lsunit = (int)BTOBBT(lsu); /* verify if lsu/lsunit is a multiple block size */ if (lsu % blocksize != 0) { fprintf(stderr, _("log stripe unit (%d) must be a multiple of the block size (%d)\n"), lsu, blocksize); exit(1); } if ((BBTOB(*lsunit) % blocksize != 0)) { fprintf(stderr, _("log stripe unit (%d) must be a multiple of the block size (%d)\n"), BBTOB(*lsunit), blocksize); exit(1); } } static void check_device_type( const char *name, int *isfile, bool no_size, bool no_name, int *create, bool force_overwrite, const char *optname) { struct stat statbuf; if (*isfile && (no_size || no_name)) { fprintf(stderr, _("if -%s file then -%s name and -%s size are required\n"), optname, optname, optname); usage(); } if (!name) { fprintf(stderr, _("No device name specified\n")); usage(); } if (stat(name, &statbuf)) { if (errno == ENOENT && *isfile) { if (create) *create = 1; return; } fprintf(stderr, _("Error accessing specified device %s: %s\n"), name, strerror(errno)); usage(); return; } if (!force_overwrite && check_overwrite(name)) { fprintf(stderr, _("%s: Use the -f option to force overwrite.\n"), progname); exit(1); } /* * We only want to completely truncate and recreate an existing file if * we were specifically told it was a file. Set the create flag only in * this case to trigger that behaviour. */ if (S_ISREG(statbuf.st_mode)) { if (!*isfile) *isfile = 1; else if (create) *create = 1; return; } if (S_ISBLK(statbuf.st_mode)) { if (*isfile) { fprintf(stderr, _("specified \"-%s file\" on a block device %s\n"), optname, name); usage(); } return; } fprintf(stderr, _("specified device %s not a file or block device\n"), name); usage(); } static void fixup_log_stripe_unit( int lsflag, int sunit, xfs_rfsblock_t *logblocks, int blocklog) { __uint64_t tmp_logblocks; /* * Make sure that the log size is a multiple of the stripe unit */ if ((*logblocks % sunit) != 0) { if (!lsflag) { tmp_logblocks = ((*logblocks + (sunit - 1)) / sunit) * sunit; /* * If the log is too large, round down * instead of round up */ if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) || ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) { tmp_logblocks = (*logblocks / sunit) * sunit; } *logblocks = tmp_logblocks; } else { fprintf(stderr, _("log size %lld is not a multiple " "of the log stripe unit %d\n"), (long long) *logblocks, sunit); usage(); } } } static xfs_fsblock_t fixup_internal_log_stripe( xfs_mount_t *mp, int lsflag, xfs_fsblock_t logstart, __uint64_t agsize, int sunit, xfs_rfsblock_t *logblocks, int blocklog, int *lalign) { if ((logstart % sunit) != 0) { logstart = ((logstart + (sunit - 1))/sunit) * sunit; *lalign = 1; } fixup_log_stripe_unit(lsflag, sunit, logblocks, blocklog); if (*logblocks > agsize - XFS_FSB_TO_AGBNO(mp, logstart)) { fprintf(stderr, _("Due to stripe alignment, the internal log size " "(%lld) is too large.\n"), (long long) *logblocks); fprintf(stderr, _("Must fit within an allocation group.\n")); usage(); } return logstart; } void validate_log_size(__uint64_t logblocks, int blocklog, int min_logblocks) { if (logblocks < min_logblocks) { fprintf(stderr, _("log size %lld blocks too small, minimum size is %d blocks\n"), (long long)logblocks, min_logblocks); usage(); } if (logblocks > XFS_MAX_LOG_BLOCKS) { fprintf(stderr, _("log size %lld blocks too large, maximum size is %lld blocks\n"), (long long)logblocks, XFS_MAX_LOG_BLOCKS); usage(); } if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) { fprintf(stderr, _("log size %lld bytes too large, maximum size is %lld bytes\n"), (long long)(logblocks << blocklog), XFS_MAX_LOG_BYTES); usage(); } } static int calc_default_imaxpct( int blocklog, __uint64_t dblocks) { /* * This returns the % of the disk space that is used for * inodes, it changes relatively to the FS size: * - over 50 TB, use 1%, * - 1TB - 50 TB, use 5%, * - under 1 TB, use XFS_DFL_IMAXIMUM_PCT (25%). */ if (dblocks < TERABYTES(1, blocklog)) { return XFS_DFL_IMAXIMUM_PCT; } else if (dblocks < TERABYTES(50, blocklog)) { return 5; } return 1; } static void validate_ag_geometry( int blocklog, __uint64_t dblocks, __uint64_t agsize, __uint64_t agcount) { if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) { fprintf(stderr, _("agsize (%lld blocks) too small, need at least %lld blocks\n"), (long long)agsize, (long long)XFS_AG_MIN_BLOCKS(blocklog)); usage(); } if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) { fprintf(stderr, _("agsize (%lld blocks) too big, maximum is %lld blocks\n"), (long long)agsize, (long long)XFS_AG_MAX_BLOCKS(blocklog)); usage(); } if (agsize > dblocks) { fprintf(stderr, _("agsize (%lld blocks) too big, data area is %lld blocks\n"), (long long)agsize, (long long)dblocks); usage(); } if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) { fprintf(stderr, _("too many allocation groups for size = %lld\n"), (long long)agsize); fprintf(stderr, _("need at most %lld allocation groups\n"), (long long)(dblocks / XFS_AG_MIN_BLOCKS(blocklog) + (dblocks % XFS_AG_MIN_BLOCKS(blocklog) != 0))); usage(); } if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) { fprintf(stderr, _("too few allocation groups for size = %lld\n"), (long long)agsize); fprintf(stderr, _("need at least %lld allocation groups\n"), (long long)(dblocks / XFS_AG_MAX_BLOCKS(blocklog) + (dblocks % XFS_AG_MAX_BLOCKS(blocklog) != 0))); usage(); } /* * If the last AG is too small, reduce the filesystem size * and drop the blocks. */ if ( dblocks % agsize != 0 && (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) { fprintf(stderr, _("last AG size %lld blocks too small, minimum size is %lld blocks\n"), (long long)(dblocks % agsize), (long long)XFS_AG_MIN_BLOCKS(blocklog)); usage(); } /* * If agcount is too large, make it smaller. */ if (agcount > XFS_MAX_AGNUMBER + 1) { fprintf(stderr, _("%lld allocation groups is too many, maximum is %lld\n"), (long long)agcount, (long long)XFS_MAX_AGNUMBER + 1); usage(); } } static void zero_old_xfs_structures( libxfs_init_t *xi, xfs_sb_t *new_sb) { void *buf; xfs_sb_t sb; __uint32_t bsize; int i; xfs_off_t off; /* * We open regular files with O_TRUNC|O_CREAT. Nothing to do here... */ if (xi->disfile && xi->dcreat) return; /* * read in existing filesystem superblock, use its geometry * settings and zero the existing secondary superblocks. */ buf = memalign(libxfs_device_alignment(), new_sb->sb_sectsize); if (!buf) { fprintf(stderr, _("error reading existing superblock -- failed to memalign buffer\n")); return; } memset(buf, 0, new_sb->sb_sectsize); /* * If we are creating an image file, it might be of zero length at this * point in time. Hence reading the existing superblock is going to * return zero bytes. It's not a failure we need to warn about in this * case. */ off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0); if (off != new_sb->sb_sectsize) { if (!xi->disfile) fprintf(stderr, _("error reading existing superblock: %s\n"), strerror(errno)); goto done; } libxfs_sb_from_disk(&sb, buf); /* * perform same basic superblock validation to make sure we * actually zero secondary blocks */ if (sb.sb_magicnum != XFS_SB_MAGIC || sb.sb_blocksize == 0) goto done; for (bsize = 1, i = 0; bsize < sb.sb_blocksize && i < sizeof(sb.sb_blocksize) * NBBY; i++) bsize <<= 1; if (i < XFS_MIN_BLOCKSIZE_LOG || i > XFS_MAX_BLOCKSIZE_LOG || i != sb.sb_blocklog) goto done; if (sb.sb_dblocks > ((__uint64_t)sb.sb_agcount * sb.sb_agblocks) || sb.sb_dblocks < ((__uint64_t)(sb.sb_agcount - 1) * sb.sb_agblocks + XFS_MIN_AG_BLOCKS)) goto done; /* * block size and basic geometry seems alright, zero the secondaries. */ memset(buf, 0, new_sb->sb_sectsize); off = 0; for (i = 1; i < sb.sb_agcount; i++) { off += sb.sb_agblocks; if (pwrite(xi->dfd, buf, new_sb->sb_sectsize, off << sb.sb_blocklog) == -1) break; } done: free(buf); } static void discard_blocks(dev_t dev, __uint64_t nsectors) { int fd; /* * We intentionally ignore errors from the discard ioctl. It is * not necessary for the mkfs functionality but just an optimization. */ fd = libxfs_device_to_fd(dev); if (fd > 0) platform_discard_blocks(fd, 0, nsectors << 9); } struct sb_feat_args { int log_version; int attr_version; int dir_version; int spinodes; int finobt; bool inode_align; bool nci; bool lazy_sb_counters; bool projid16bit; bool crcs_enabled; bool dirftype; bool parent_pointers; bool rmapbt; bool reflink; }; static void sb_set_features( struct xfs_sb *sbp, struct sb_feat_args *fp, int sectsize, int lsectsize, int dsunit) { sbp->sb_versionnum = XFS_DFL_SB_VERSION_BITS; if (fp->crcs_enabled) sbp->sb_versionnum |= XFS_SB_VERSION_5; else sbp->sb_versionnum |= XFS_SB_VERSION_4; if (fp->inode_align) sbp->sb_versionnum |= XFS_SB_VERSION_ALIGNBIT; if (dsunit) sbp->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT; if (fp->log_version == 2) sbp->sb_versionnum |= XFS_SB_VERSION_LOGV2BIT; if (fp->attr_version == 1) sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; if (sectsize > BBSIZE || lsectsize > BBSIZE) sbp->sb_versionnum |= XFS_SB_VERSION_SECTORBIT; if (fp->nci) sbp->sb_versionnum |= XFS_SB_VERSION_BORGBIT; sbp->sb_features2 = 0; if (fp->lazy_sb_counters) sbp->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT; if (!fp->projid16bit) sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; if (fp->parent_pointers) sbp->sb_features2 |= XFS_SB_VERSION2_PARENTBIT; if (fp->crcs_enabled) sbp->sb_features2 |= XFS_SB_VERSION2_CRCBIT; if (fp->attr_version == 2) sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT; /* v5 superblocks have their own feature bit for dirftype */ if (fp->dirftype && !fp->crcs_enabled) sbp->sb_features2 |= XFS_SB_VERSION2_FTYPE; /* update whether extended features are in use */ if (sbp->sb_features2 != 0) sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; /* * Due to a structure alignment issue, sb_features2 ended up in one * of two locations, the second "incorrect" location represented by * the sb_bad_features2 field. To avoid older kernels mounting * filesystems they shouldn't, set both field to the same value. */ sbp->sb_bad_features2 = sbp->sb_features2; if (!fp->crcs_enabled) return; /* default features for v5 filesystems */ sbp->sb_features_compat = 0; sbp->sb_features_ro_compat = 0; sbp->sb_features_incompat = XFS_SB_FEAT_INCOMPAT_FTYPE; sbp->sb_features_log_incompat = 0; if (fp->finobt) sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT; if (fp->rmapbt) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT; if (fp->reflink) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK; /* * Sparse inode chunk support has two main inode alignment requirements. * First, sparse chunk alignment must match the cluster size. Second, * full chunk alignment must match the inode chunk size. * * Copy the already calculated/scaled inoalignmt to spino_align and * update the former to the full inode chunk size. */ if (fp->spinodes) { sbp->sb_spino_align = sbp->sb_inoalignmt; sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK * sbp->sb_inodesize >> sbp->sb_blocklog; sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES; } } static __attribute__((noreturn)) void illegal_option( const char *value, struct opt_params *opts, int index, const char *reason) { fprintf(stderr, _("Illegal value %s for -%c %s option. %s\n"), value, opts->name, opts->subopts[index], reason ? reason : ""); usage(); } /* * Check for conflicts and option respecification. */ static void check_opt( struct opt_params *opts, int index, bool str_seen) { struct subopt_param *sp = &opts->subopt_params[index]; int i; if (sp->index != index) { fprintf(stderr, ("Developer screwed up option parsing (%d/%d)! Please report!\n"), sp->index, index); reqval(opts->name, (char **)opts->subopts, index); } /* * Check for respecification of the option. This is more complex than it * seems because some options are parsed twice - once as a string during * input parsing, then later the string is passed to getnum for * conversion into a number and bounds checking. Hence the two variables * used to track the different uses based on the @str parameter passed * to us. */ if (!str_seen) { if (sp->seen) respec(opts->name, (char **)opts->subopts, index); sp->seen = true; } else { if (sp->str_seen) respec(opts->name, (char **)opts->subopts, index); sp->str_seen = true; } /* check for conflicts with the option */ for (i = 0; i < MAX_CONFLICTS; i++) { int conflict_opt = sp->conflicts[i]; if (conflict_opt == LAST_CONFLICT) break; if (opts->subopt_params[conflict_opt].seen || opts->subopt_params[conflict_opt].str_seen) conflict(opts->name, (char **)opts->subopts, conflict_opt, index); } } static long long getnum( const char *str, struct opt_params *opts, int index) { struct subopt_param *sp = &opts->subopt_params[index]; long long c; check_opt(opts, index, false); /* empty strings might just return a default value */ if (!str || *str == '\0') { if (sp->defaultval == SUBOPT_NEEDS_VAL) reqval(opts->name, (char **)opts->subopts, index); return sp->defaultval; } if (sp->minval == 0 && sp->maxval == 0) { fprintf(stderr, _("Option -%c %s has undefined minval/maxval." "Can't verify value range. This is a bug.\n"), opts->name, opts->subopts[index]); exit(1); } /* * Some values are pure numbers, others can have suffixes that define * the units of the number. Those get passed to cvtnum(), otherwise we * convert it ourselves to guarantee there is no trailing garbage in the * number. */ if (sp->convert) c = cvtnum(blocksize, sectorsize, str); else { char *str_end; c = strtoll(str, &str_end, 0); if (c == 0 && str_end == str) illegal_option(str, opts, index, NULL); if (*str_end != '\0') illegal_option(str, opts, index, NULL); } /* Validity check the result. */ if (c < sp->minval) illegal_option(str, opts, index, _("value is too small")); else if (c > sp->maxval) illegal_option(str, opts, index, _("value is too large")); if (sp->is_power_2 && !ispow2(c)) illegal_option(str, opts, index, _("value must be a power of 2")); return c; } /* * Option is a string - do all the option table work, and check there * is actually an option string. Otherwise we don't do anything with the string * here - validation will be done later when the string is converted to a value * or used as a file/device path. */ static char * getstr( char *str, struct opt_params *opts, int index) { check_opt(opts, index, true); /* empty strings for string options are not valid */ if (!str || *str == '\0') reqval(opts->name, (char **)opts->subopts, index); return str; } int main( int argc, char **argv) { __uint64_t agcount; xfs_agf_t *agf; xfs_agi_t *agi; xfs_agnumber_t agno; __uint64_t agsize; xfs_alloc_rec_t *arec; struct xfs_btree_block *block; int blflag; int blocklog; int bsflag; int bsize; xfs_buf_t *buf; int c; int daflag; int dasize; xfs_rfsblock_t dblocks; char *dfile; int dirblocklog; int dirblocksize; char *dsize; int dsu; int dsw; int dsunit; int dswidth; int force_overwrite; struct fsxattr fsx; int ilflag; int imaxpct; int imflag; int inodelog; int inopblock; int ipflag; int isflag; int isize; char *label = NULL; int laflag; int lalign; int ldflag; int liflag; xfs_agnumber_t logagno; xfs_rfsblock_t logblocks; char *logfile; int loginternal; char *logsize; xfs_fsblock_t logstart; int lvflag; int lsflag; int lsuflag; int lsunitflag; int lsectorlog; int lsectorsize; int lslflag; int lssflag; int lsu; int lsunit; int min_logblocks; xfs_mount_t *mp; xfs_mount_t mbuf; xfs_extlen_t nbmblocks; int nlflag; int nodsflag; int norsflag; xfs_alloc_rec_t *nrec; int nsflag; int nvflag; int Nflag; int discard = 1; char *p; char *protofile; char *protostring; int qflag; xfs_rfsblock_t rtblocks; xfs_extlen_t rtextblocks; xfs_rtblock_t rtextents; char *rtextsize; char *rtfile; char *rtsize; xfs_sb_t *sbp; int sectorlog; __uint64_t sector_mask; int slflag; int ssflag; __uint64_t tmp_agsize; uuid_t uuid; int worst_freelist; libxfs_init_t xi; struct fs_topology ft; struct sb_feat_args sb_feat = { .finobt = 1, .spinodes = 0, .log_version = 2, .attr_version = 2, .dir_version = XFS_DFL_DIR_VERSION, .inode_align = XFS_IFLAG_ALIGN, .nci = false, .lazy_sb_counters = true, .projid16bit = false, .crcs_enabled = true, .dirftype = true, .parent_pointers = false, .rmapbt = false, .reflink = false, }; platform_uuid_generate(&uuid); progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0; blocklog = blocksize = 0; sectorlog = lsectorlog = 0; sectorsize = lsectorsize = 0; agsize = daflag = dasize = dblocks = 0; ilflag = imflag = ipflag = isflag = 0; liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0; loginternal = 1; logagno = logblocks = rtblocks = rtextblocks = 0; Nflag = nlflag = nsflag = nvflag = 0; dirblocklog = dirblocksize = 0; qflag = 0; imaxpct = inodelog = inopblock = isize = 0; dfile = logfile = rtfile = NULL; dsize = logsize = rtsize = rtextsize = protofile = NULL; dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0; nodsflag = norsflag = 0; force_overwrite = 0; worst_freelist = 0; memset(&fsx, 0, sizeof(fsx)); memset(&xi, 0, sizeof(xi)); xi.isdirect = LIBXFS_DIRECT; xi.isreadonly = LIBXFS_EXCLUSIVELY; while ((c = getopt(argc, argv, "b:d:i:l:L:m:n:KNp:qr:s:CfV")) != EOF) { switch (c) { case 'C': case 'f': force_overwrite = 1; break; case 'b': p = optarg; while (*p != '\0') { char **subopts = (char **)bopts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case B_LOG: blocklog = getnum(value, &bopts, B_LOG); blocksize = 1 << blocklog; blflag = 1; break; case B_SIZE: blocksize = getnum(value, &bopts, B_SIZE); blocklog = libxfs_highbit32(blocksize); bsflag = 1; break; default: unknown('b', value); } } break; case 'd': p = optarg; while (*p != '\0') { char **subopts = (char **)dopts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case D_AGCOUNT: agcount = getnum(value, &dopts, D_AGCOUNT); daflag = 1; break; case D_AGSIZE: agsize = getnum(value, &dopts, D_AGSIZE); dasize = 1; break; case D_FILE: xi.disfile = getnum(value, &dopts, D_FILE); break; case D_NAME: xi.dname = getstr(value, &dopts, D_NAME); break; case D_SIZE: dsize = getstr(value, &dopts, D_SIZE); break; case D_SUNIT: dsunit = getnum(value, &dopts, D_SUNIT); break; case D_SWIDTH: dswidth = getnum(value, &dopts, D_SWIDTH); break; case D_SU: dsu = getnum(value, &dopts, D_SU); break; case D_SW: dsw = getnum(value, &dopts, D_SW); break; case D_NOALIGN: nodsflag = getnum(value, &dopts, D_NOALIGN); break; case D_SECTLOG: sectorlog = getnum(value, &dopts, D_SECTLOG); sectorsize = 1 << sectorlog; slflag = 1; break; case D_SECTSIZE: sectorsize = getnum(value, &dopts, D_SECTSIZE); sectorlog = libxfs_highbit32(sectorsize); ssflag = 1; break; case D_RTINHERIT: c = getnum(value, &dopts, D_RTINHERIT); if (c) fsx.fsx_xflags |= XFS_DIFLAG_RTINHERIT; break; case D_PROJINHERIT: fsx.fsx_projid = getnum(value, &dopts, D_PROJINHERIT); fsx.fsx_xflags |= XFS_DIFLAG_PROJINHERIT; break; case D_EXTSZINHERIT: fsx.fsx_extsize = getnum(value, &dopts, D_EXTSZINHERIT); fsx.fsx_xflags |= XFS_DIFLAG_EXTSZINHERIT; break; default: unknown('d', value); } } break; case 'i': p = optarg; while (*p != '\0') { char **subopts = (char **)iopts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case I_ALIGN: sb_feat.inode_align = getnum(value, &iopts, I_ALIGN); break; case I_LOG: inodelog = getnum(value, &iopts, I_LOG); isize = 1 << inodelog; ilflag = 1; break; case I_MAXPCT: imaxpct = getnum(value, &iopts, I_MAXPCT); imflag = 1; break; case I_PERBLOCK: inopblock = getnum(value, &iopts, I_PERBLOCK); ipflag = 1; break; case I_SIZE: isize = getnum(value, &iopts, I_SIZE); inodelog = libxfs_highbit32(isize); isflag = 1; break; case I_ATTR: sb_feat.attr_version = getnum(value, &iopts, I_ATTR); break; case I_PROJID32BIT: sb_feat.projid16bit = !getnum(value, &iopts, I_PROJID32BIT); break; case I_SPINODES: sb_feat.spinodes = getnum(value, &iopts, I_SPINODES); break; default: unknown('i', value); } } break; case 'l': p = optarg; while (*p != '\0') { char **subopts = (char **)lopts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case L_AGNUM: logagno = getnum(value, &lopts, L_AGNUM); laflag = 1; break; case L_FILE: xi.lisfile = getnum(value, &lopts, L_FILE); break; case L_INTERNAL: loginternal = getnum(value, &lopts, L_INTERNAL); liflag = 1; break; case L_SU: lsu = getnum(value, &lopts, L_SU); lsuflag = 1; break; case L_SUNIT: lsunit = getnum(value, &lopts, L_SUNIT); lsunitflag = 1; break; case L_NAME: case L_DEV: logfile = getstr(value, &lopts, L_NAME); xi.logname = logfile; ldflag = 1; loginternal = 0; break; case L_VERSION: sb_feat.log_version = getnum(value, &lopts, L_VERSION); lvflag = 1; break; case L_SIZE: logsize = getstr(value, &lopts, L_SIZE); break; case L_SECTLOG: lsectorlog = getnum(value, &lopts, L_SECTLOG); lsectorsize = 1 << lsectorlog; lslflag = 1; break; case L_SECTSIZE: lsectorsize = getnum(value, &lopts, L_SECTSIZE); lsectorlog = libxfs_highbit32(lsectorsize); lssflag = 1; break; case L_LAZYSBCNTR: sb_feat.lazy_sb_counters = getnum(value, &lopts, L_LAZYSBCNTR); break; default: unknown('l', value); } } break; case 'L': if (strlen(optarg) > sizeof(sbp->sb_fname)) illegal(optarg, "L"); label = optarg; break; case 'm': p = optarg; while (*p != '\0') { char **subopts = (char **)mopts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case M_CRC: sb_feat.crcs_enabled = getnum(value, &mopts, M_CRC); if (sb_feat.crcs_enabled) sb_feat.dirftype = true; break; case M_FINOBT: sb_feat.finobt = getnum( value, &mopts, M_FINOBT); break; case M_UUID: if (!value || *value == '\0') reqval('m', subopts, M_UUID); if (platform_uuid_parse(value, &uuid)) illegal(optarg, "m uuid"); break; case M_RMAPBT: sb_feat.rmapbt = getnum( value, &mopts, M_RMAPBT); break; case M_REFLINK: sb_feat.reflink = getnum( value, &mopts, M_REFLINK); break; default: unknown('m', value); } } break; case 'n': p = optarg; while (*p != '\0') { char **subopts = (char **)nopts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case N_LOG: dirblocklog = getnum(value, &nopts, N_LOG); dirblocksize = 1 << dirblocklog; nlflag = 1; break; case N_SIZE: dirblocksize = getnum(value, &nopts, N_SIZE); dirblocklog = libxfs_highbit32(dirblocksize); nsflag = 1; break; case N_VERSION: value = getstr(value, &nopts, N_VERSION); if (!strcasecmp(value, "ci")) { /* ASCII CI mode */ sb_feat.nci = true; } else { sb_feat.dir_version = getnum(value, &nopts, N_VERSION); } nvflag = 1; break; case N_FTYPE: sb_feat.dirftype = getnum(value, &nopts, N_FTYPE); break; default: unknown('n', value); } } break; case 'N': Nflag = 1; break; case 'K': discard = 0; break; case 'p': if (protofile) respec('p', NULL, 0); protofile = optarg; break; case 'q': qflag = 1; break; case 'r': p = optarg; while (*p != '\0') { char **subopts = (char **)ropts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case R_EXTSIZE: rtextsize = getstr(value, &ropts, R_EXTSIZE); break; case R_FILE: xi.risfile = getnum(value, &ropts, R_FILE); break; case R_NAME: case R_DEV: xi.rtname = getstr(value, &ropts, R_NAME); break; case R_SIZE: rtsize = getstr(value, &ropts, R_SIZE); break; case R_NOALIGN: norsflag = getnum(value, &ropts, R_NOALIGN); break; default: unknown('r', value); } } break; case 's': p = optarg; while (*p != '\0') { char **subopts = (char **)sopts.subopts; char *value; switch (getsubopt(&p, subopts, &value)) { case S_LOG: case S_SECTLOG: if (lssflag) conflict('s', subopts, S_SECTSIZE, S_SECTLOG); sectorlog = getnum(value, &sopts, S_SECTLOG); lsectorlog = sectorlog; sectorsize = 1 << sectorlog; lsectorsize = sectorsize; lslflag = slflag = 1; break; case S_SIZE: case S_SECTSIZE: if (lslflag) conflict('s', subopts, S_SECTLOG, S_SECTSIZE); sectorsize = getnum(value, &sopts, S_SECTSIZE); lsectorsize = sectorsize; sectorlog = libxfs_highbit32(sectorsize); lsectorlog = sectorlog; lssflag = ssflag = 1; break; default: unknown('s', value); } } break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); case '?': unknown(optopt, ""); } } if (argc - optind > 1) { fprintf(stderr, _("extra arguments\n")); usage(); } else if (argc - optind == 1) { dfile = xi.volname = getstr(argv[optind], &dopts, D_NAME); } else dfile = xi.dname; /* * Blocksize and sectorsize first, other things depend on them * For RAID4/5/6 we want to align sector size and block size, * so we need to start with the device geometry extraction too. */ if (!blflag && !bsflag) { blocklog = XFS_DFL_BLOCKSIZE_LOG; blocksize = 1 << XFS_DFL_BLOCKSIZE_LOG; } if (blocksize < XFS_MIN_BLOCKSIZE || blocksize > XFS_MAX_BLOCKSIZE) { fprintf(stderr, _("illegal block size %d\n"), blocksize); usage(); } if (sb_feat.crcs_enabled && blocksize < XFS_MIN_CRC_BLOCKSIZE) { fprintf(stderr, _("Minimum block size for CRC enabled filesystems is %d bytes.\n"), XFS_MIN_CRC_BLOCKSIZE); usage(); } if (sb_feat.crcs_enabled && !sb_feat.dirftype) { fprintf(stderr, _("cannot disable ftype with crcs enabled\n")); usage(); } if (!slflag && !ssflag) { sectorlog = XFS_MIN_SECTORSIZE_LOG; sectorsize = XFS_MIN_SECTORSIZE; } if (!lslflag && !lssflag) { lsectorlog = sectorlog; lsectorsize = sectorsize; } /* * Before anything else, verify that we are correctly operating on * files or block devices and set the control parameters correctly. * Explicitly disable direct IO for image files so we don't error out on * sector size mismatches between the new filesystem and the underlying * host filesystem. */ check_device_type(dfile, &xi.disfile, !dsize, !dfile, Nflag ? NULL : &xi.dcreat, force_overwrite, "d"); if (!loginternal) check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname, Nflag ? NULL : &xi.lcreat, force_overwrite, "l"); if (xi.rtname) check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname, Nflag ? NULL : &xi.rcreat, force_overwrite, "r"); if (xi.disfile || xi.lisfile || xi.risfile) xi.isdirect = 0; memset(&ft, 0, sizeof(ft)); get_topology(&xi, &ft, force_overwrite); if (!ssflag) { /* * Unless specified manually on the command line use the * advertised sector size of the device. We use the physical * sector size unless the requested block size is smaller * than that, then we can use logical, but warn about the * inefficiency. */ /* Older kernels may not have physical/logical distinction */ if (!ft.psectorsize) ft.psectorsize = ft.lsectorsize; sectorsize = ft.psectorsize ? ft.psectorsize : XFS_MIN_SECTORSIZE; if ((blocksize < sectorsize) && (blocksize >= ft.lsectorsize)) { fprintf(stderr, _("specified blocksize %d is less than device physical sector size %d\n"), blocksize, ft.psectorsize); fprintf(stderr, _("switching to logical sector size %d\n"), ft.lsectorsize); sectorsize = ft.lsectorsize ? ft.lsectorsize : XFS_MIN_SECTORSIZE; } } if (!ssflag) { sectorlog = libxfs_highbit32(sectorsize); if (loginternal) { lsectorsize = sectorsize; lsectorlog = sectorlog; } } if (sectorsize < XFS_MIN_SECTORSIZE || sectorsize > XFS_MAX_SECTORSIZE || sectorsize > blocksize) { if (ssflag) fprintf(stderr, _("illegal sector size %d\n"), sectorsize); else fprintf(stderr, _("block size %d cannot be smaller than logical sector size %d\n"), blocksize, ft.lsectorsize); usage(); } if (sectorsize < ft.lsectorsize) { fprintf(stderr, _("illegal sector size %d; hw sector is %d\n"), sectorsize, ft.lsectorsize); usage(); } if (lsectorsize < XFS_MIN_SECTORSIZE || lsectorsize > XFS_MAX_SECTORSIZE || lsectorsize > blocksize) { fprintf(stderr, _("illegal log sector size %d\n"), lsectorsize); usage(); } else if (lsectorsize > XFS_MIN_SECTORSIZE && !lsu && !lsunit) { lsu = blocksize; sb_feat.log_version = 2; } /* * Now we have blocks and sector sizes set up, check parameters that are * no longer optional for CRC enabled filesystems. Catch them up front * here before doing anything else. */ if (sb_feat.crcs_enabled) { /* minimum inode size is 512 bytes, ipflag checked later */ if ((isflag || ilflag) && inodelog < XFS_DINODE_DFL_CRC_LOG) { fprintf(stderr, _("Minimum inode size for CRCs is %d bytes\n"), 1 << XFS_DINODE_DFL_CRC_LOG); usage(); } /* inodes always aligned */ if (!sb_feat.inode_align) { fprintf(stderr, _("Inodes always aligned for CRC enabled filesytems\n")); usage(); } /* lazy sb counters always on */ if (!sb_feat.lazy_sb_counters) { fprintf(stderr, _("Lazy superblock counted always enabled for CRC enabled filesytems\n")); usage(); } /* version 2 logs always on */ if (sb_feat.log_version != 2) { fprintf(stderr, _("V2 logs always enabled for CRC enabled filesytems\n")); usage(); } /* attr2 always on */ if (sb_feat.attr_version != 2) { fprintf(stderr, _("V2 attribute format always enabled on CRC enabled filesytems\n")); usage(); } /* 32 bit project quota always on */ /* attr2 always on */ if (sb_feat.projid16bit) { fprintf(stderr, _("32 bit Project IDs always enabled on CRC enabled filesytems\n")); usage(); } } else { /* * The kernel doesn't currently support crc=0,finobt=1 * filesystems. If crcs are not enabled and the user has not * explicitly turned finobt on, then silently turn it off to * avoid an unnecessary warning. * If the user explicitly tried to use crc=0,finobt=1, * then issue an error. * The same is also for sparse inodes. */ if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) { fprintf(stderr, _("finobt not supported without CRC support\n")); usage(); } sb_feat.finobt = 0; if (sb_feat.spinodes) { fprintf(stderr, _("sparse inodes not supported without CRC support\n")); usage(); } sb_feat.spinodes = 0; if (sb_feat.rmapbt) { fprintf(stderr, _("rmapbt not supported without CRC support\n")); usage(); } sb_feat.rmapbt = false; if (sb_feat.reflink) { fprintf(stderr, _("reflink not supported without CRC support\n")); usage(); } sb_feat.reflink = false; } if (sb_feat.rmapbt && xi.rtname) { fprintf(stderr, _("rmapbt not supported with realtime devices\n")); usage(); sb_feat.rmapbt = false; } if (nsflag || nlflag) { if (dirblocksize < blocksize || dirblocksize > XFS_MAX_BLOCKSIZE) { fprintf(stderr, _("illegal directory block size %d\n"), dirblocksize); usage(); } } else { if (blocksize < (1 << XFS_MIN_REC_DIRSIZE)) dirblocklog = XFS_MIN_REC_DIRSIZE; else dirblocklog = blocklog; dirblocksize = 1 << dirblocklog; } if (dsize) { __uint64_t dbytes; dbytes = getnum(dsize, &dopts, D_SIZE); if (dbytes % XFS_MIN_BLOCKSIZE) { fprintf(stderr, _("illegal data length %lld, not a multiple of %d\n"), (long long)dbytes, XFS_MIN_BLOCKSIZE); usage(); } dblocks = (xfs_rfsblock_t)(dbytes >> blocklog); if (dbytes % blocksize) fprintf(stderr, _("warning: " "data length %lld not a multiple of %d, truncated to %lld\n"), (long long)dbytes, blocksize, (long long)(dblocks << blocklog)); } if (ipflag) { inodelog = blocklog - libxfs_highbit32(inopblock); isize = 1 << inodelog; } else if (!ilflag && !isflag) { inodelog = sb_feat.crcs_enabled ? XFS_DINODE_DFL_CRC_LOG : XFS_DINODE_DFL_LOG; isize = 1 << inodelog; } if (sb_feat.crcs_enabled && inodelog < XFS_DINODE_DFL_CRC_LOG) { fprintf(stderr, _("Minimum inode size for CRCs is %d bytes\n"), 1 << XFS_DINODE_DFL_CRC_LOG); usage(); } if (logsize) { __uint64_t logbytes; logbytes = getnum(logsize, &lopts, L_SIZE); if (logbytes % XFS_MIN_BLOCKSIZE) { fprintf(stderr, _("illegal log length %lld, not a multiple of %d\n"), (long long)logbytes, XFS_MIN_BLOCKSIZE); usage(); } logblocks = (xfs_rfsblock_t)(logbytes >> blocklog); if (logbytes % blocksize) fprintf(stderr, _("warning: log length %lld not a multiple of %d, truncated to %lld\n"), (long long)logbytes, blocksize, (long long)(logblocks << blocklog)); } if (rtsize) { __uint64_t rtbytes; rtbytes = getnum(rtsize, &ropts, R_SIZE); if (rtbytes % XFS_MIN_BLOCKSIZE) { fprintf(stderr, _("illegal rt length %lld, not a multiple of %d\n"), (long long)rtbytes, XFS_MIN_BLOCKSIZE); usage(); } rtblocks = (xfs_rfsblock_t)(rtbytes >> blocklog); if (rtbytes % blocksize) fprintf(stderr, _("warning: rt length %lld not a multiple of %d, truncated to %lld\n"), (long long)rtbytes, blocksize, (long long)(rtblocks << blocklog)); } /* * If specified, check rt extent size against its constraints. */ if (rtextsize) { __uint64_t rtextbytes; rtextbytes = getnum(rtextsize, &ropts, R_EXTSIZE); if (rtextbytes % blocksize) { fprintf(stderr, _("illegal rt extent size %lld, not a multiple of %d\n"), (long long)rtextbytes, blocksize); usage(); } rtextblocks = (xfs_extlen_t)(rtextbytes >> blocklog); } else { /* * If realtime extsize has not been specified by the user, * and the underlying volume is striped, then set rtextblocks * to the stripe width. */ __uint64_t rswidth; __uint64_t rtextbytes; if (!norsflag && !xi.risfile && !(!rtsize && xi.disfile)) rswidth = ft.rtswidth; else rswidth = 0; /* check that rswidth is a multiple of fs blocksize */ if (!norsflag && rswidth && !(BBTOB(rswidth) % blocksize)) { rswidth = DTOBT(rswidth); rtextbytes = rswidth << blocklog; if (XFS_MIN_RTEXTSIZE <= rtextbytes && (rtextbytes <= XFS_MAX_RTEXTSIZE)) { rtextblocks = rswidth; } } if (!rtextblocks) { rtextblocks = (blocksize < XFS_MIN_RTEXTSIZE) ? XFS_MIN_RTEXTSIZE >> blocklog : 1; } } ASSERT(rtextblocks); /* * Check some argument sizes against mins, maxes. */ if (isize > blocksize / XFS_MIN_INODE_PERBLOCK || isize < XFS_DINODE_MIN_SIZE || isize > XFS_DINODE_MAX_SIZE) { int maxsz; fprintf(stderr, _("illegal inode size %d\n"), isize); maxsz = MIN(blocksize / XFS_MIN_INODE_PERBLOCK, XFS_DINODE_MAX_SIZE); if (XFS_DINODE_MIN_SIZE == maxsz) fprintf(stderr, _("allowable inode size with %d byte blocks is %d\n"), blocksize, XFS_DINODE_MIN_SIZE); else fprintf(stderr, _("allowable inode size with %d byte blocks is between %d and %d\n"), blocksize, XFS_DINODE_MIN_SIZE, maxsz); exit(1); } /* if lsu or lsunit was specified, automatically use v2 logs */ if ((lsu || lsunit) && sb_feat.log_version == 1) { fprintf(stderr, _("log stripe unit specified, using v2 logs\n")); sb_feat.log_version = 2; } calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize, &dsunit, &dswidth, &lsunit); xi.setblksize = sectorsize; /* * Initialize. This will open the log and rt devices as well. */ if (!libxfs_init(&xi)) usage(); if (!xi.ddev) { fprintf(stderr, _("no device name given in argument list\n")); usage(); } /* * Ok, Linux only has a 1024-byte resolution on device _size_, * and the sizes below are in basic 512-byte blocks, * so if we have (size % 2), on any partition, we can't get * to the last 512 bytes. The same issue exists for larger * sector sizes - we cannot write past the last sector. * * So, we reduce the size (in basic blocks) to a perfect * multiple of the sector size, or 1024, whichever is larger. */ sector_mask = (__uint64_t)-1 << (MAX(sectorlog, 10) - BBSHIFT); xi.dsize &= sector_mask; xi.rtsize &= sector_mask; xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT); /* don't do discards on print-only runs or on files */ if (discard && !Nflag) { if (!xi.disfile) discard_blocks(xi.ddev, xi.dsize); if (xi.rtdev && !xi.risfile) discard_blocks(xi.rtdev, xi.rtsize); if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile) discard_blocks(xi.logdev, xi.logBBsize); } if (!liflag && !ldflag) loginternal = xi.logdev == 0; if (xi.logname) logfile = xi.logname; else if (loginternal) logfile = _("internal log"); else if (xi.volname && xi.logdev) logfile = _("volume log"); else if (!ldflag) { fprintf(stderr, _("no log subvolume or internal log\n")); usage(); } if (xi.rtname) rtfile = xi.rtname; else if (xi.volname && xi.rtdev) rtfile = _("volume rt"); else if (!xi.rtdev) rtfile = _("none"); if (dsize && xi.dsize > 0 && dblocks > DTOBT(xi.dsize)) { fprintf(stderr, _("size %s specified for data subvolume is too large, " "maximum is %lld blocks\n"), dsize, (long long)DTOBT(xi.dsize)); usage(); } else if (!dsize && xi.dsize > 0) dblocks = DTOBT(xi.dsize); else if (!dsize) { fprintf(stderr, _("can't get size of data subvolume\n")); usage(); } if (dblocks < XFS_MIN_DATA_BLOCKS) { fprintf(stderr, _("size %lld of data subvolume is too small, minimum %d blocks\n"), (long long)dblocks, XFS_MIN_DATA_BLOCKS); usage(); } if (loginternal && xi.logdev) { fprintf(stderr, _("can't have both external and internal logs\n")); usage(); } else if (loginternal && sectorsize != lsectorsize) { fprintf(stderr, _("data and log sector sizes must be equal for internal logs\n")); usage(); } if (xi.dbsize > sectorsize) { fprintf(stderr, _( "Warning: the data subvolume sector size %u is less than the sector size \n\ reported by the device (%u).\n"), sectorsize, xi.dbsize); } if (!loginternal && xi.lbsize > lsectorsize) { fprintf(stderr, _( "Warning: the log subvolume sector size %u is less than the sector size\n\ reported by the device (%u).\n"), lsectorsize, xi.lbsize); } if (rtsize && xi.rtsize > 0 && xi.rtbsize > sectorsize) { fprintf(stderr, _( "Warning: the realtime subvolume sector size %u is less than the sector size\n\ reported by the device (%u).\n"), sectorsize, xi.rtbsize); } if (rtsize && xi.rtsize > 0 && rtblocks > DTOBT(xi.rtsize)) { fprintf(stderr, _("size %s specified for rt subvolume is too large, " "maximum is %lld blocks\n"), rtsize, (long long)DTOBT(xi.rtsize)); usage(); } else if (!rtsize && xi.rtsize > 0) rtblocks = DTOBT(xi.rtsize); else if (rtsize && !xi.rtdev) { fprintf(stderr, _("size specified for non-existent rt subvolume\n")); usage(); } if (xi.rtdev) { rtextents = rtblocks / rtextblocks; nbmblocks = (xfs_extlen_t)howmany(rtextents, NBBY * blocksize); } else { rtextents = rtblocks = 0; nbmblocks = 0; } if (!nodsflag) { if (dsunit) { if (ft.dsunit && ft.dsunit != dsunit) { fprintf(stderr, _("%s: Specified data stripe unit %d " "is not the same as the volume stripe " "unit %d\n"), progname, dsunit, ft.dsunit); } if (ft.dswidth && ft.dswidth != dswidth) { fprintf(stderr, _("%s: Specified data stripe width %d " "is not the same as the volume stripe " "width %d\n"), progname, dswidth, ft.dswidth); } } else { dsunit = ft.dsunit; dswidth = ft.dswidth; nodsflag = 1; } } /* else dsunit & dswidth can't be set if nodsflag is set */ if (dasize) { /* User-specified AG size */ /* * Check specified agsize is a multiple of blocksize. */ if (agsize % blocksize) { fprintf(stderr, _("agsize (%lld) not a multiple of fs blk size (%d)\n"), (long long)agsize, blocksize); usage(); } agsize /= blocksize; agcount = dblocks / agsize + (dblocks % agsize != 0); } else if (daflag) { /* User-specified AG count */ agsize = dblocks / agcount + (dblocks % agcount != 0); } else { calc_default_ag_geometry(blocklog, dblocks, dsunit | dswidth, &agsize, &agcount); } /* * If dsunit is a multiple of fs blocksize, then check that is a * multiple of the agsize too */ if (dsunit && !(BBTOB(dsunit) % blocksize) && dswidth && !(BBTOB(dswidth) % blocksize)) { /* convert from 512 byte blocks to fs blocksize */ dsunit = DTOBT(dsunit); dswidth = DTOBT(dswidth); /* * agsize is not a multiple of dsunit */ if ((agsize % dsunit) != 0) { /* * Round up to stripe unit boundary. Also make sure * that agsize is still larger than * XFS_AG_MIN_BLOCKS(blocklog) */ tmp_agsize = ((agsize + (dsunit - 1))/ dsunit) * dsunit; /* * Round down to stripe unit boundary if rounding up * created an AG size that is larger than the AG max. */ if (tmp_agsize > XFS_AG_MAX_BLOCKS(blocklog)) tmp_agsize = ((agsize) / dsunit) * dsunit; if ((tmp_agsize >= XFS_AG_MIN_BLOCKS(blocklog)) && (tmp_agsize <= XFS_AG_MAX_BLOCKS(blocklog))) { agsize = tmp_agsize; if (!daflag) agcount = dblocks/agsize + (dblocks % agsize != 0); if (dasize) fprintf(stderr, _("agsize rounded to %lld, swidth = %d\n"), (long long)agsize, dswidth); } else { if (nodsflag) { dsunit = dswidth = 0; } else { /* * agsize is out of bounds, this will * print nice details & exit. */ validate_ag_geometry(blocklog, dblocks, agsize, agcount); exit(1); } } } if (dswidth && ((agsize % dswidth) == 0) && (agcount > 1)) { /* This is a non-optimal configuration because all AGs * start on the same disk in the stripe. Changing * the AG size by one sunit will guarantee that this * does not happen. */ tmp_agsize = agsize - dsunit; if (tmp_agsize < XFS_AG_MIN_BLOCKS(blocklog)) { tmp_agsize = agsize + dsunit; if (dblocks < agsize) { /* oh well, nothing to do */ tmp_agsize = agsize; } } if (daflag || dasize) { fprintf(stderr, _( "Warning: AG size is a multiple of stripe width. This can cause performance\n\ problems by aligning all AGs on the same disk. To avoid this, run mkfs with\n\ an AG size that is one stripe unit smaller, for example %llu.\n"), (unsigned long long)tmp_agsize); } else { agsize = tmp_agsize; agcount = dblocks/agsize + (dblocks % agsize != 0); /* * If the last AG is too small, reduce the * filesystem size and drop the blocks. */ if ( dblocks % agsize != 0 && (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) { dblocks = (xfs_rfsblock_t)((agcount - 1) * agsize); agcount--; ASSERT(agcount != 0); } } } } else { if (nodsflag) dsunit = dswidth = 0; else { fprintf(stderr, _("%s: Stripe unit(%d) or stripe width(%d) is " "not a multiple of the block size(%d)\n"), progname, BBTOB(dsunit), BBTOB(dswidth), blocksize); exit(1); } } /* * If the last AG is too small, reduce the filesystem size * and drop the blocks. */ if ( dblocks % agsize != 0 && (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) { ASSERT(!daflag); dblocks = (xfs_rfsblock_t)((agcount - 1) * agsize); agcount--; ASSERT(agcount != 0); } validate_ag_geometry(blocklog, dblocks, agsize, agcount); if (!imflag) imaxpct = calc_default_imaxpct(blocklog, dblocks); /* * check that log sunit is modulo fsblksize or default it to dsunit. */ if (lsunit) { /* convert from 512 byte blocks to fs blocks */ lsunit = DTOBT(lsunit); } else if (sb_feat.log_version == 2 && loginternal && dsunit) { /* lsunit and dsunit now in fs blocks */ lsunit = dsunit; } if (sb_feat.log_version == 2 && (lsunit * blocksize) > 256 * 1024) { /* Warn only if specified on commandline */ if (lsuflag || lsunitflag) { fprintf(stderr, _("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"), (lsunit * blocksize)); fprintf(stderr, _("log stripe unit adjusted to 32KiB\n")); } lsunit = (32 * 1024) >> blocklog; } min_logblocks = max_trans_res(agsize, sb_feat.crcs_enabled, sb_feat.dir_version, sectorlog, blocklog, inodelog, dirblocklog, sb_feat.log_version, lsunit, sb_feat.finobt, sb_feat.rmapbt, sb_feat.reflink); ASSERT(min_logblocks); min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks); if (!logsize && dblocks >= (1024*1024*1024) >> blocklog) min_logblocks = MAX(min_logblocks, XFS_MIN_LOG_BYTES>>blocklog); if (logsize && xi.logBBsize > 0 && logblocks > DTOBT(xi.logBBsize)) { fprintf(stderr, _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), logsize, (long long)DTOBT(xi.logBBsize)); usage(); } else if (!logsize && xi.logBBsize > 0) { logblocks = DTOBT(xi.logBBsize); } else if (logsize && !xi.logdev && !loginternal) { fprintf(stderr, _("size specified for non-existent log subvolume\n")); usage(); } else if (loginternal && logsize && logblocks >= dblocks) { fprintf(stderr, _("size %lld too large for internal log\n"), (long long)logblocks); usage(); } else if (!loginternal && !xi.logdev) { logblocks = 0; } else if (loginternal && !logsize) { if (dblocks < GIGABYTES(1, blocklog)) { /* tiny filesystems get minimum sized logs. */ logblocks = min_logblocks; } else if (dblocks < GIGABYTES(16, blocklog)) { /* * For small filesystems, we want to use the * XFS_MIN_LOG_BYTES for filesystems smaller than 16G if * at all possible, ramping up to 128MB at 256GB. */ logblocks = MIN(XFS_MIN_LOG_BYTES >> blocklog, min_logblocks * XFS_DFL_LOG_FACTOR); } else { /* * With a 2GB max log size, default to maximum size * at 4TB. This keeps the same ratio from the older * max log size of 128M at 256GB fs size. IOWs, * the ratio of fs size to log size is 2048:1. */ logblocks = (dblocks << blocklog) / 2048; logblocks = logblocks >> blocklog; } /* Ensure the chosen size meets minimum log size requirements */ logblocks = MAX(min_logblocks, logblocks); /* make sure the log fits wholly within an AG */ if (logblocks >= agsize) logblocks = min_logblocks; /* and now clamp the size to the maximum supported size */ logblocks = MIN(logblocks, XFS_MAX_LOG_BLOCKS); if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) logblocks = XFS_MAX_LOG_BYTES >> blocklog; } validate_log_size(logblocks, blocklog, min_logblocks); protostring = setup_proto(protofile); bsize = 1 << (blocklog - BBSHIFT); mp = &mbuf; sbp = &mp->m_sb; memset(mp, 0, sizeof(xfs_mount_t)); sbp->sb_blocklog = (__uint8_t)blocklog; sbp->sb_sectlog = (__uint8_t)sectorlog; sbp->sb_agblklog = (__uint8_t)libxfs_log2_roundup((unsigned int)agsize); sbp->sb_agblocks = (xfs_agblock_t)agsize; mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT; mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; /* * sb_versionnum, finobt and rmapbt flags must be set before we use * libxfs_prealloc_blocks(). */ sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit); if (loginternal) { /* * Readjust the log size to fit within an AG if it was sized * automatically. */ if (!logsize) { logblocks = MIN(logblocks, libxfs_alloc_ag_max_usable(mp)); /* revalidate the log size is valid if we changed it */ validate_log_size(logblocks, blocklog, min_logblocks); } if (logblocks > agsize - libxfs_prealloc_blocks(mp)) { fprintf(stderr, _("internal log size %lld too large, must fit in allocation group\n"), (long long)logblocks); usage(); } if (laflag) { if (logagno >= agcount) { fprintf(stderr, _("log ag number %d too large, must be less than %lld\n"), logagno, (long long)agcount); usage(); } } else logagno = (xfs_agnumber_t)(agcount / 2); logstart = XFS_AGB_TO_FSB(mp, logagno, libxfs_prealloc_blocks(mp)); /* * Align the logstart at stripe unit boundary. */ if (lsunit) { logstart = fixup_internal_log_stripe(mp, lsflag, logstart, agsize, lsunit, &logblocks, blocklog, &lalign); } else if (dsunit) { logstart = fixup_internal_log_stripe(mp, lsflag, logstart, agsize, dsunit, &logblocks, blocklog, &lalign); } } else { logstart = 0; if (lsunit) fixup_log_stripe_unit(lsflag, lsunit, &logblocks, blocklog); } validate_log_size(logblocks, blocklog, min_logblocks); if (!qflag || Nflag) { printf(_( "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"), dfile, isize, (long long)agcount, (long long)agsize, "", sectorsize, sb_feat.attr_version, !sb_feat.projid16bit, "", sb_feat.crcs_enabled, sb_feat.finobt, sb_feat.spinodes, sb_feat.rmapbt, sb_feat.reflink, "", blocksize, (long long)dblocks, imaxpct, "", dsunit, dswidth, sb_feat.dir_version, dirblocksize, sb_feat.nci, sb_feat.dirftype, logfile, 1 << blocklog, (long long)logblocks, sb_feat.log_version, "", lsectorsize, lsunit, sb_feat.lazy_sb_counters, rtfile, rtextblocks << blocklog, (long long)rtblocks, (long long)rtextents); if (Nflag) exit(0); } if (label) strncpy(sbp->sb_fname, label, sizeof(sbp->sb_fname)); sbp->sb_magicnum = XFS_SB_MAGIC; sbp->sb_blocksize = blocksize; sbp->sb_dblocks = dblocks; sbp->sb_rblocks = rtblocks; sbp->sb_rextents = rtextents; platform_uuid_copy(&sbp->sb_uuid, &uuid); /* Only in memory; libxfs expects this as if read from disk */ platform_uuid_copy(&sbp->sb_meta_uuid, &uuid); sbp->sb_logstart = logstart; sbp->sb_rootino = sbp->sb_rbmino = sbp->sb_rsumino = NULLFSINO; sbp->sb_rextsize = rtextblocks; sbp->sb_agcount = (xfs_agnumber_t)agcount; sbp->sb_rbmblocks = nbmblocks; sbp->sb_logblocks = (xfs_extlen_t)logblocks; sbp->sb_sectsize = (__uint16_t)sectorsize; sbp->sb_inodesize = (__uint16_t)isize; sbp->sb_inopblock = (__uint16_t)(blocksize / isize); sbp->sb_sectlog = (__uint8_t)sectorlog; sbp->sb_inodelog = (__uint8_t)inodelog; sbp->sb_inopblog = (__uint8_t)(blocklog - inodelog); sbp->sb_rextslog = (__uint8_t)(rtextents ? libxfs_highbit32((unsigned int)rtextents) : 0); sbp->sb_inprogress = 1; /* mkfs is in progress */ sbp->sb_imax_pct = imaxpct; sbp->sb_icount = 0; sbp->sb_ifree = 0; sbp->sb_fdblocks = dblocks - agcount * libxfs_prealloc_blocks(mp) - (loginternal ? logblocks : 0); sbp->sb_frextents = 0; /* will do a free later */ sbp->sb_uquotino = sbp->sb_gquotino = sbp->sb_pquotino = 0; sbp->sb_qflags = 0; sbp->sb_unit = dsunit; sbp->sb_width = dswidth; sbp->sb_dirblklog = dirblocklog - blocklog; if (sb_feat.log_version == 2) { /* This is stored in bytes */ lsunit = (lsunit == 0) ? 1 : XFS_FSB_TO_B(mp, lsunit); sbp->sb_logsunit = lsunit; } else sbp->sb_logsunit = 0; if (sb_feat.inode_align) { int cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; if (sb_feat.crcs_enabled) cluster_size *= isize / XFS_DINODE_MIN_SIZE; sbp->sb_inoalignmt = cluster_size >> blocklog; sb_feat.inode_align = sbp->sb_inoalignmt != 0; } else sbp->sb_inoalignmt = 0; if (lsectorsize != BBSIZE || sectorsize != BBSIZE) { sbp->sb_logsectlog = (__uint8_t)lsectorlog; sbp->sb_logsectsize = (__uint16_t)lsectorsize; } else { sbp->sb_logsectlog = 0; sbp->sb_logsectsize = 0; } sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit); if (force_overwrite) zero_old_xfs_structures(&xi, sbp); /* * Zero out the beginning of the device, to obliterate any old * filesystem signatures out there. This should take care of * swap (somewhere around the page size), jfs (32k), * ext[2,3] and reiserfs (64k) - and hopefully all else. */ libxfs_buftarg_init(mp, xi.ddev, xi.logdev, xi.rtdev); buf = libxfs_getbuf(mp->m_ddev_targp, 0, BTOBB(WHACK_SIZE)); memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); libxfs_purgebuf(buf); /* OK, now write the superblock */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_SB_DADDR, XFS_FSS_TO_BB(mp, 1)); buf->b_ops = &xfs_sb_buf_ops; memset(XFS_BUF_PTR(buf), 0, sectorsize); libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); libxfs_purgebuf(buf); /* * If the data area is a file, then grow it out to its final size * if needed so that the reads for the end of the device in the mount * code will succeed. */ if (xi.disfile && xi.dsize * xi.dbsize < dblocks * blocksize) { if (ftruncate(xi.dfd, dblocks * blocksize) < 0) { fprintf(stderr, _("%s: Growing the data section failed\n"), progname); exit(1); } } /* * Zero out the end of the device, to obliterate any * old MD RAID (or other) metadata at the end of the device. * (MD sb is ~64k from the end, take out a wider swath to be sure) */ if (!xi.disfile) { buf = libxfs_getbuf(mp->m_ddev_targp, (xi.dsize - BTOBB(WHACK_SIZE)), BTOBB(WHACK_SIZE)); memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); libxfs_purgebuf(buf); } /* * Zero the log.... */ libxfs_log_clear(mp->m_logdev_targp, NULL, XFS_FSB_TO_DADDR(mp, logstart), (xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks), &sbp->sb_uuid, sb_feat.log_version, lsunit, XLOG_FMT, XLOG_INIT_CYCLE, false); mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0); if (mp == NULL) { fprintf(stderr, _("%s: filesystem failed to initialize\n"), progname); exit(1); } /* * XXX: this code is effectively shared with the kernel growfs code. * These initialisations should be pulled into libxfs to keep the * kernel/userspace header initialisation code the same. */ for (agno = 0; agno < agcount; agno++) { struct xfs_agfl *agfl; int bucket; struct xfs_perag *pag = libxfs_perag_get(mp, agno); /* * Superblock. */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1)); buf->b_ops = &xfs_sb_buf_ops; memset(XFS_BUF_PTR(buf), 0, sectorsize); libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * AG header block: freespace */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1)); buf->b_ops = &xfs_agf_buf_ops; agf = XFS_BUF_TO_AGF(buf); memset(agf, 0, sectorsize); if (agno == agcount - 1) agsize = dblocks - (xfs_rfsblock_t)(agno * agsize); agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); agf->agf_seqno = cpu_to_be32(agno); agf->agf_length = cpu_to_be32(agsize); agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp)); agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp)); agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1); agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1); pag->pagf_levels[XFS_BTNUM_BNOi] = 1; pag->pagf_levels[XFS_BTNUM_CNTi] = 1; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { agf->agf_roots[XFS_BTNUM_RMAPi] = cpu_to_be32(XFS_RMAP_BLOCK(mp)); agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1); agf->agf_rmap_blocks = cpu_to_be32(1); } if (xfs_sb_version_hasreflink(&mp->m_sb)) { agf->agf_refcount_root = cpu_to_be32( libxfs_refc_block(mp)); agf->agf_refcount_level = cpu_to_be32(1); agf->agf_refcount_blocks = cpu_to_be32(1); } agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); agf->agf_flcount = 0; nbmblocks = (xfs_extlen_t)(agsize - libxfs_prealloc_blocks(mp)); agf->agf_freeblks = cpu_to_be32(nbmblocks); agf->agf_longest = cpu_to_be32(nbmblocks); if (xfs_sb_version_hascrc(&mp->m_sb)) platform_uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_uuid); if (loginternal && agno == logagno) { be32_add_cpu(&agf->agf_freeblks, -logblocks); agf->agf_longest = cpu_to_be32(agsize - XFS_FSB_TO_AGBNO(mp, logstart) - logblocks); } if (libxfs_alloc_min_freelist(mp, pag) > worst_freelist) worst_freelist = libxfs_alloc_min_freelist(mp, pag); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * AG freelist header block */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1)); buf->b_ops = &xfs_agfl_buf_ops; agfl = XFS_BUF_TO_AGFL(buf); /* setting to 0xff results in initialisation to NULLAGBLOCK */ memset(agfl, 0xff, sectorsize); if (xfs_sb_version_hascrc(&mp->m_sb)) { agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC); agfl->agfl_seqno = cpu_to_be32(agno); platform_uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid); for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++) agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK); } libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * AG header block: inodes */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1)); agi = XFS_BUF_TO_AGI(buf); buf->b_ops = &xfs_agi_buf_ops; memset(agi, 0, sectorsize); agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); agi->agi_seqno = cpu_to_be32(agno); agi->agi_length = cpu_to_be32((xfs_agblock_t)agsize); agi->agi_count = 0; agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp)); agi->agi_level = cpu_to_be32(1); if (sb_feat.finobt) { agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp)); agi->agi_free_level = cpu_to_be32(1); } agi->agi_freecount = 0; agi->agi_newino = cpu_to_be32(NULLAGINO); agi->agi_dirino = cpu_to_be32(NULLAGINO); if (xfs_sb_version_hascrc(&mp->m_sb)) platform_uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid); for (c = 0; c < XFS_AGI_UNLINKED_BUCKETS; c++) agi->agi_unlinked[c] = cpu_to_be32(NULLAGINO); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * BNO btree root block */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), bsize); buf->b_ops = &xfs_allocbt_buf_ops; block = XFS_BUF_TO_BLOCK(buf); memset(block, 0, blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, buf, XFS_ABTB_CRC_MAGIC, 0, 1, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, buf, XFS_ABTB_MAGIC, 0, 1, agno, 0); arec = XFS_ALLOC_REC_ADDR(mp, block, 1); arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp)); if (loginternal && agno == logagno) { if (lalign) { /* * Have to insert two records * Insert pad record for stripe align of log */ arec->ar_blockcount = cpu_to_be32( XFS_FSB_TO_AGBNO(mp, logstart) - be32_to_cpu(arec->ar_startblock)); nrec = arec + 1; /* * Insert record at start of internal log */ nrec->ar_startblock = cpu_to_be32( be32_to_cpu(arec->ar_startblock) + be32_to_cpu(arec->ar_blockcount)); arec = nrec; be16_add_cpu(&block->bb_numrecs, 1); } /* * Change record start to after the internal log */ be32_add_cpu(&arec->ar_startblock, logblocks); } /* * Calculate the record block count and check for the case where * the log might have consumed all available space in the AG. If * so, reset the record count to 0 to avoid exposure of an invalid * record start block. */ arec->ar_blockcount = cpu_to_be32(agsize - be32_to_cpu(arec->ar_startblock)); if (!arec->ar_blockcount) block->bb_numrecs = 0; libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * CNT btree root block */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), bsize); buf->b_ops = &xfs_allocbt_buf_ops; block = XFS_BUF_TO_BLOCK(buf); memset(block, 0, blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, buf, XFS_ABTC_CRC_MAGIC, 0, 1, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, buf, XFS_ABTC_MAGIC, 0, 1, agno, 0); arec = XFS_ALLOC_REC_ADDR(mp, block, 1); arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp)); if (loginternal && agno == logagno) { if (lalign) { arec->ar_blockcount = cpu_to_be32( XFS_FSB_TO_AGBNO(mp, logstart) - be32_to_cpu(arec->ar_startblock)); nrec = arec + 1; nrec->ar_startblock = cpu_to_be32( be32_to_cpu(arec->ar_startblock) + be32_to_cpu(arec->ar_blockcount)); arec = nrec; be16_add_cpu(&block->bb_numrecs, 1); } be32_add_cpu(&arec->ar_startblock, logblocks); } /* * Calculate the record block count and check for the case where * the log might have consumed all available space in the AG. If * so, reset the record count to 0 to avoid exposure of an invalid * record start block. */ arec->ar_blockcount = cpu_to_be32(agsize - be32_to_cpu(arec->ar_startblock)); if (!arec->ar_blockcount) block->bb_numrecs = 0; libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * refcount btree root block */ if (xfs_sb_version_hasreflink(&mp->m_sb)) { buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AGB_TO_DADDR(mp, agno, libxfs_refc_block(mp)), bsize); buf->b_ops = &xfs_refcountbt_buf_ops; block = XFS_BUF_TO_BLOCK(buf); memset(block, 0, blocksize); libxfs_btree_init_block(mp, buf, XFS_REFC_CRC_MAGIC, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); } /* * INO btree root block */ buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), bsize); buf->b_ops = &xfs_inobt_buf_ops; block = XFS_BUF_TO_BLOCK(buf); memset(block, 0, blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, buf, XFS_IBT_CRC_MAGIC, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, buf, XFS_IBT_MAGIC, 0, 0, agno, 0); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * Free INO btree root block */ if (sb_feat.finobt) { buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)), bsize); buf->b_ops = &xfs_inobt_buf_ops; block = XFS_BUF_TO_BLOCK(buf); memset(block, 0, blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, buf, XFS_FIBT_CRC_MAGIC, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, buf, XFS_FIBT_MAGIC, 0, 0, agno, 0); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); } /* RMAP btree root block */ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { struct xfs_rmap_rec *rrec; buf = libxfs_getbuf(mp->m_ddev_targp, XFS_AGB_TO_DADDR(mp, agno, XFS_RMAP_BLOCK(mp)), bsize); buf->b_ops = &xfs_rmapbt_buf_ops; block = XFS_BUF_TO_BLOCK(buf); memset(block, 0, blocksize); libxfs_btree_init_block(mp, buf, XFS_RMAP_CRC_MAGIC, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); /* * mark the AG header regions as static metadata * The BNO btree block is the first block after the * headers, so it's location defines the size of region * the static metadata consumes. */ rrec = XFS_RMAP_REC_ADDR(block, 1); rrec->rm_startblock = 0; rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp)); rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS); rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); /* account freespace btree root blocks */ rrec = XFS_RMAP_REC_ADDR(block, 2); rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp)); rrec->rm_blockcount = cpu_to_be32(2); rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); /* account inode btree root blocks */ rrec = XFS_RMAP_REC_ADDR(block, 3); rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp)); rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) - XFS_IBT_BLOCK(mp)); rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT); rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); /* account for rmap btree root */ rrec = XFS_RMAP_REC_ADDR(block, 4); rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp)); rrec->rm_blockcount = cpu_to_be32(1); rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); /* account for refcount btree root */ if (xfs_sb_version_hasreflink(&mp->m_sb)) { rrec = XFS_RMAP_REC_ADDR(block, 5); rrec->rm_startblock = cpu_to_be32( libxfs_refc_block(mp)); rrec->rm_blockcount = cpu_to_be32(1); rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC); rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); } /* account for the log space */ if (loginternal && agno == logagno) { rrec = XFS_RMAP_REC_ADDR(block, be16_to_cpu(block->bb_numrecs) + 1); rrec->rm_startblock = cpu_to_be32( XFS_FSB_TO_AGBNO(mp, logstart)); rrec->rm_blockcount = cpu_to_be32(logblocks); rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_LOG); rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); } libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); } libxfs_perag_put(pag); } /* * Touch last block, make fs the right size if it's a file. */ buf = libxfs_getbuf(mp->m_ddev_targp, (xfs_daddr_t)XFS_FSB_TO_BB(mp, dblocks - 1LL), bsize); memset(XFS_BUF_PTR(buf), 0, blocksize); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * Make sure we can write the last block in the realtime area. */ if (mp->m_rtdev_targp->dev && rtblocks > 0) { buf = libxfs_getbuf(mp->m_rtdev_targp, XFS_FSB_TO_BB(mp, rtblocks - 1LL), bsize); memset(XFS_BUF_PTR(buf), 0, blocksize); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); } /* * BNO, CNT free block list */ for (agno = 0; agno < agcount; agno++) { xfs_alloc_arg_t args; xfs_trans_t *tp; struct xfs_trans_res tres = {0}; c = libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp); if (c) res_failed(c); memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = mp; args.agno = agno; args.alignment = 1; args.pag = libxfs_perag_get(mp,agno); libxfs_alloc_fix_freelist(&args, 0); libxfs_perag_put(args.pag); libxfs_trans_commit(tp); } /* * Allocate the root inode and anything else in the proto file. */ parse_proto(mp, &fsx, &protostring); /* * Protect ourselves against possible stupidity */ if (XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino) != 0) { fprintf(stderr, _("%s: root inode created in AG %u, not AG 0\n"), progname, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino)); exit(1); } /* * Write out multiple secondary superblocks with rootinode field set */ if (mp->m_sb.sb_agcount > 1) { /* * the last superblock */ buf = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, mp->m_sb.sb_agcount-1, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), LIBXFS_EXIT_ON_FAILURE, &xfs_sb_buf_ops); XFS_BUF_TO_SBP(buf)->sb_rootino = cpu_to_be64( mp->m_sb.sb_rootino); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* * and one in the middle for luck */ if (mp->m_sb.sb_agcount > 2) { buf = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, (mp->m_sb.sb_agcount-1)/2, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), LIBXFS_EXIT_ON_FAILURE, &xfs_sb_buf_ops); XFS_BUF_TO_SBP(buf)->sb_rootino = cpu_to_be64( mp->m_sb.sb_rootino); libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); } } /* * Dump all inodes and buffers before marking us all done. * Need to drop references to inodes we still hold, first. */ libxfs_rtmount_destroy(mp); libxfs_bcache_purge(); /* * Mark the filesystem ok. */ buf = libxfs_getsb(mp, LIBXFS_EXIT_ON_FAILURE); (XFS_BUF_TO_SBP(buf))->sb_inprogress = 0; libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); libxfs_umount(mp); if (xi.rtdev) libxfs_device_close(xi.rtdev); if (xi.logdev && xi.logdev != xi.ddev) libxfs_device_close(xi.logdev); libxfs_device_close(xi.ddev); return 0; } static void conflict( char opt, char *tab[], int oldidx, int newidx) { fprintf(stderr, _("Cannot specify both -%c %s and -%c %s\n"), opt, tab[oldidx], opt, tab[newidx]); usage(); } static void illegal( const char *value, const char *opt) { fprintf(stderr, _("Illegal value %s for -%s option\n"), value, opt); usage(); } static int ispow2( unsigned int i) { return (i & (i - 1)) == 0; } static void __attribute__((noreturn)) reqval( char opt, char *tab[], int idx) { fprintf(stderr, _("-%c %s option requires a value\n"), opt, tab[idx]); usage(); } static void respec( char opt, char *tab[], int idx) { fprintf(stderr, "-%c ", opt); if (tab) fprintf(stderr, "%s ", tab[idx]); fprintf(stderr, _("option respecified\n")); usage(); } static void unknown( char opt, char *s) { fprintf(stderr, _("unknown option -%c %s\n"), opt, s); usage(); } long long cvtnum( unsigned int blksize, unsigned int sectsize, const char *s) { long long i; char *sp; int c; i = strtoll(s, &sp, 0); if (i == 0 && sp == s) return -1LL; if (*sp == '\0') return i; if (sp[1] != '\0') return -1LL; if (*sp == 'b') { if (!blksize) { fprintf(stderr, _("Blocksize must be provided prior to using 'b' suffix.\n")); usage(); } else { return i * blksize; } } if (*sp == 's') { if (!sectsize) { fprintf(stderr, _("Sectorsize must be specified prior to using 's' suffix.\n")); usage(); } else { return i * sectsize; } } c = tolower(*sp); switch (c) { case 'e': i *= 1024LL; /* fall through */ case 'p': i *= 1024LL; /* fall through */ case 't': i *= 1024LL; /* fall through */ case 'g': i *= 1024LL; /* fall through */ case 'm': i *= 1024LL; /* fall through */ case 'k': return i * 1024LL; default: break; } return -1LL; } static void __attribute__((noreturn)) usage( void ) { fprintf(stderr, _("Usage: %s\n\ /* blocksize */ [-b log=n|size=num]\n\ /* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\ /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\ (sunit=value,swidth=value|su=num,sw=num|noalign),\n\ sectlog=n|sectsize=num\n\ /* force overwrite */ [-f]\n\ /* inode size */ [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\ projid32bit=0|1,sparse=0|1]\n\ /* no discard */ [-K]\n\ /* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\ sunit=value|su=num,sectlog=n|sectsize=num,\n\ lazy-count=0|1]\n\ /* label */ [-L label (maximum 12 characters)]\n\ /* naming */ [-n log=n|size=num,version=2|ci,ftype=0|1]\n\ /* no-op info only */ [-N]\n\ /* prototype file */ [-p fname]\n\ /* quiet */ [-q]\n\ /* realtime subvol */ [-r extsize=num,size=num,rtdev=xxx]\n\ /* sectorsize */ [-s log=n|size=num]\n\ /* version */ [-V]\n\ devicename\n\ is required unless -d name=xxx is given.\n\ is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n\ xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n\ is xxx (512 byte blocks).\n"), progname); exit(1); } xfsprogs-4.9.0+nmu1ubuntu2/po/0000755000000000000000000000000013063067174013113 5ustar xfsprogs-4.9.0+nmu1ubuntu2/po/Makefile0000644000000000000000000000110513063067172014546 0ustar # # Copyright (c) 2001-2003 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs POTHEAD = $(PKG_NAME).pot # If the user has requested a specific set of translations, only build those. SUPPORTED_LINGUAS = $(patsubst %.po,%,$(wildcard *.po)) LINGUAS ?= $(SUPPORTED_LINGUAS) LINGUAS := $(filter $(SUPPORTED_LINGUAS),$(LINGUAS)) LSRCFILES = $(LINGUAS:%=%.po) LDIRT = $(POTHEAD) XGETTEXTFILES = $(LOCALIZED_FILES) default: $(POTHEAD) $(LINGUAS:%=%.mo) include $(BUILDRULES) install: default $(INSTALL_LINGUAS) install-dev install-lib: xfsprogs-4.9.0+nmu1ubuntu2/po/de.po0000644000000000000000000177074013063067174014063 0ustar # Translation of xfsprogs to German # Copyright (C) Chris Leick , 2009. # This file is distributed under the same license as the xfsprogs package. # Chris Leick , 2009. # msgid "" msgstr "" "Project-Id-Version: xfsprogs 3.0.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-01-08 07:15+1100\n" "PO-Revision-Date: 2009-10-21 21:08+0100\n" "Last-Translator: Chris Leick \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: .././copy/xfs_copy.c:115 #, c-format msgid "Check logfile \"%s\" for more details\n" msgstr "Prüfen Sie die Protokolldatei »%s«, um mehr Details zu erhalten\n" #: .././copy/xfs_copy.c:121 #, c-format msgid "%s: could not write to logfile \"%s\".\n" msgstr "%s: Es konnte nicht in die Protokolldatei »%s« geschrieben werden.\n" #: .././copy/xfs_copy.c:124 #, c-format msgid "Aborting XFS copy -- logfile error -- reason: %s\n" msgstr "Kopieren von XFS wird abgebrochen -- Protokollfehler -- Grund: %s\n" #: .././copy/xfs_copy.c:139 .././copy/xfs_copy.c:292 .././copy/xfs_copy.c:605 #: .././copy/xfs_copy.c:612 msgid "Aborting XFS copy - reason" msgstr "Kopieren von XFS wird abgebrochen - Grund" #: .././copy/xfs_copy.c:159 msgid "THE FOLLOWING COPIES FAILED TO COMPLETE\n" msgstr "DAS VERVOLLSTÄNDIGEN DER FOLGENDEN KOPIEN SCHEITERTE\n" #: .././copy/xfs_copy.c:163 msgid "write error" msgstr "Schreibfehler" #: .././copy/xfs_copy.c:165 msgid "lseek error" msgstr "lseek-Fehler" #: .././copy/xfs_copy.c:166 #, c-format msgid " at offset %lld\n" msgstr " bei Versatz %lld\n" #: .././copy/xfs_copy.c:170 #, c-format msgid "All copies completed.\n" msgstr "Alle Kopien vervollständigt.\n" #: .././copy/xfs_copy.c:173 #, c-format msgid "See \"%s\" for more details.\n" msgstr "Lesen Sie »%s«, um mehr Details zu erhalten.\n" #: .././copy/xfs_copy.c:261 #, c-format msgid "%s: write error on target %d \"%s\" at offset %lld\n" msgstr "%s: Schreibfehler auf Ziel %d »%s« bei Versatz %lld\n" #: .././copy/xfs_copy.c:266 #, c-format msgid "%s: lseek error on target %d \"%s\" at offset %lld\n" msgstr "%s: lseek-Fehler auf Ziel %d »%s« bei Versatz %lld\n" #: .././copy/xfs_copy.c:272 #, c-format msgid "Aborting target %d - reason" msgstr "Ziel %d wird abgebrochen - Grund" #: .././copy/xfs_copy.c:276 msgid "Aborting XFS copy - no more targets.\n" msgstr "Kopieren von XFS wird abgebrochen - keine Ziele mehr.\n" #: .././copy/xfs_copy.c:287 #, c-format msgid "%s: thread %d died unexpectedly, target \"%s\" incomplete\n" msgstr "%s: Thread %d unerwartet beendet, Ziel »%s« unvollständig\n" #: .././copy/xfs_copy.c:289 #, c-format msgid "%s: offset was probably %lld\n" msgstr "%s: Versatz war vermutlich %lld\n" #: .././copy/xfs_copy.c:300 #, c-format msgid "%s: Unknown child died (should never happen!)\n" msgstr "%s: Unbekannter Kindprozess beendet (sollte nie vorkommen!)\n" #: .././copy/xfs_copy.c:310 #, fuzzy, c-format msgid "Usage: %s [-bdV] [-L logfile] source target [target ...]\n" msgstr "Aufruf: %s [-bd] [-L Protokolldatei] Quelle Ziel [Ziel ...]\n" #: .././copy/xfs_copy.c:393 #, c-format msgid "%s: lseek failure at offset %lld\n" msgstr "%s: lseek-Fehlschlag bei Versatz %lld\n" #: .././copy/xfs_copy.c:408 #, c-format msgid "assert error: buf->length = %d, buf->size = %d\n" msgstr "bestätigter Fehler: buf->length = %d, buf->size = %d\n" #: .././copy/xfs_copy.c:414 #, c-format msgid "%s: read failure at offset %lld\n" msgstr "%s: Lese-Fehlschlag bei Versatz %lld\n" #: .././copy/xfs_copy.c:444 msgid "ag header buffer invalid!\n" msgstr "" #: .././copy/xfs_copy.c:585 .././db/init.c:96 .././estimate/xfs_estimate.c:144 #: .././fsr/xfs_fsr.c:295 .././growfs/xfs_growfs.c:190 .././io/init.c:199 #: .././logprint/logprint.c:206 .././mkfs/xfs_mkfs.c:1925 #: .././quota/init.c:181 .././repair/xfs_repair.c:322 .././rtcp/xfs_rtcp.c:55 #, c-format msgid "%s version %s\n" msgstr "%s Version %s\n" #: .././copy/xfs_copy.c:603 #, c-format msgid "%s: couldn't open log file \"%s\"\n" msgstr "%s: Protokolldatei »%s« kann nicht geöffnet werden.\n" #: .././copy/xfs_copy.c:610 #, c-format msgid "%s: couldn't set up logfile stream\n" msgstr "%s: Protokoll-Datenstrom konnte nicht erzeugt werden\n" #: .././copy/xfs_copy.c:622 msgid "Couldn't allocate target array\n" msgstr "Ziel-Array konnte nicht bereitgestellt werden.\n" #: .././copy/xfs_copy.c:641 #, c-format msgid "%s: couldn't open source \"%s\"\n" msgstr "%s: Konnte Quelle »%s« nicht öffnen.\n" #: .././copy/xfs_copy.c:647 #, c-format msgid "%s: couldn't stat source \"%s\"\n" msgstr "%s: kann Quellenstatus »%s« nicht abfragen.\n" #: .././copy/xfs_copy.c:657 #, c-format msgid "%s: Cannot set direct I/O flag on \"%s\".\n" msgstr "%s: Direkte I/O-Markierung auf »%s« kann nicht gesetzt werden.\n" #: .././copy/xfs_copy.c:662 #, c-format msgid "%s: xfsctl on file \"%s\" failed.\n" msgstr "%s: xfsctl auf Datei »%s« fehlgeschlagen.\n" #: .././copy/xfs_copy.c:685 #, c-format msgid "%s: Warning -- a filesystem is mounted on the source device.\n" msgstr "%s: Warnung -- ein Dateisystem ist auf dem Quellgerät eingehängt.\n" #: .././copy/xfs_copy.c:688 msgid "\t\tGenerated copies may be corrupt unless the source is\n" msgstr "" "\t\tGenerierte Kopien könnten fehlerhaft sein, sofern die Quelle nicht\n" #: .././copy/xfs_copy.c:690 msgid "\t\tunmounted or mounted read-only. Copy proceeding...\n" msgstr "" "\t\tabgehängt oder nur mit Lesezugriff eingehängt ist.\n" "\t\tKopieren durchführen ...\n" #: .././copy/xfs_copy.c:707 #, c-format msgid "" "%s: couldn't initialize XFS library\n" "%s: Aborting.\n" msgstr "" "%s: XFS-Bibliothek konnte nicht initialisiert werden.\n" "%s: Abbruch.\n" #: .././copy/xfs_copy.c:731 #, c-format msgid "" "%s: %s filesystem failed to initialize\n" "%s: Aborting.\n" msgstr "" "%s: %s-Dateisystem konnte nicht initialisiert werden.\n" "%s: Abbruch.\n" #: .././copy/xfs_copy.c:735 #, c-format msgid "" "%s %s filesystem failed to initialize\n" "%s: Aborting.\n" msgstr "" "%s: %s-Dateisystem konnte nicht initialisiert werden.\n" "%s: Abbruch.\n" #: .././copy/xfs_copy.c:739 #, c-format msgid "" "%s: %s has an external log.\n" "%s: Aborting.\n" msgstr "" "%s: %s hat ein externes Protokoll.\n" "%s: Abbruch.\n" #: .././copy/xfs_copy.c:743 #, c-format msgid "" "%s: %s has a real-time section.\n" "%s: Aborting.\n" msgstr "" "%s: %s hat einen Echtzeit-Bereich.\n" "%s: Abbruch.\n" #: .././copy/xfs_copy.c:762 msgid "" "Error: source filesystem log is dirty. Mount the filesystem to replay the\n" "log, unmount and retry xfs_copy.\n" msgstr "" #: .././copy/xfs_copy.c:767 msgid "" "Error: could not determine the log head or tail of the source filesystem.\n" "Mount the filesystem to replay the log or run xfs_repair.\n" msgstr "" #: .././copy/xfs_copy.c:783 msgid "" "Error: filesystem block size is smaller than the disk sectorsize.\n" "Aborting XFS copy now.\n" msgstr "" "Fehler: Die Blockgröße des Dateisystems ist kleiner als die Sektorgröße\n" "der Platte. XFS-Kopieren wird nun abgebrochen.\n" #: .././copy/xfs_copy.c:800 #, c-format msgid "Creating file %s\n" msgstr "Datei %s wird erzeugt.\n" #: .././copy/xfs_copy.c:818 #, c-format msgid "" "%s: a filesystem is mounted on target device \"%s\".\n" "%s cannot copy to mounted filesystems. Aborting\n" msgstr "" "%s: Ein Dateisystem ist auf dem Zielgerät »%s« eingehängt.\n" "%s kann nicht auf eingehängte Dateisysteme schreiben. Abbruch\n" #: .././copy/xfs_copy.c:829 #, c-format msgid "%s: couldn't open target \"%s\"\n" msgstr "%s: Ziel »%s« kann nicht geöffnet werden.\n" #: .././copy/xfs_copy.c:839 #, c-format msgid "%s: cannot grow data section.\n" msgstr "%s: Datenbereich kann nicht vergrößert werden.\n" #: .././copy/xfs_copy.c:847 #, c-format msgid "%s: xfsctl on \"%s\" failed.\n" msgstr "%s: xfsctl auf »%s« fehlgeschlagen.\n" #: .././copy/xfs_copy.c:866 #, c-format msgid "%s: failed to write last block\n" msgstr "%s: Letzter Block konnte nicht geschrieben werden.\n" #: .././copy/xfs_copy.c:868 #, c-format msgid "\tIs target \"%s\" too small?\n" msgstr "\tIst das Ziel »%s« zu klein?\n" #: .././copy/xfs_copy.c:878 msgid "Couldn't initialize global thread mask\n" msgstr "Globale Thread-Maske kann nicht initialisiert werden\n" #: .././copy/xfs_copy.c:885 msgid "Error initializing wbuf 0\n" msgstr "Fehler beim Initialisieren von wbuf 0\n" #: .././copy/xfs_copy.c:893 msgid "Error initializing btree buf 1\n" msgstr "Fehler beim Initialisieren von btree buf 1\n" #: .././copy/xfs_copy.c:898 msgid "Error creating first semaphore.\n" msgstr "Fehler beim Erstellen des ersten Semaphor.\n" #: .././copy/xfs_copy.c:913 msgid "Couldn't malloc space for thread args\n" msgstr "" "Für die Thread-Argumente konnte kein Speicherplatz bereit\n" "gestellt werden.\n" #: .././copy/xfs_copy.c:925 #, c-format msgid "Error creating thread mutex %d\n" msgstr "Fehler beim Erzeugen des Thread-Mutex %d\n" #: .././copy/xfs_copy.c:942 #, c-format msgid "Error creating thread for target %d\n" msgstr "Fehler beim Erzeugen des Threads für Ziel %d\n" #: .././copy/xfs_copy.c:996 #, c-format msgid "Error: current level %d >= btree levels %d\n" msgstr "" #: .././copy/xfs_copy.c:1015 #, c-format msgid "Bad btree magic 0x%x\n" msgstr "" #: .././copy/xfs_copy.c:1042 msgid "WARNING: source filesystem inconsistent.\n" msgstr "WARNUNG: Quell-Dateisystem ist nicht konsistent.\n" #: .././copy/xfs_copy.c:1044 msgid " A leaf btree rec isn't a leaf. Aborting now.\n" msgstr " Ein Blatt »btree rec« ist kein Blatt. Es wird nun abgebrochen.\n" #: .././db/addr.c:35 msgid "[field-expression]" msgstr "[Feldausdruck]" #: .././db/addr.c:36 msgid "set current address" msgstr "derzeitige Adresse setzen" #: .././db/addr.c:42 msgid "" "\n" " 'addr' uses the given field to set the filesystem address and type\n" "\n" " Examples:\n" "\n" " sb\n" " a rootino - set the type to inode and set position to the root inode\n" " a u.bmx[0].startblock (for inode with blockmap)\n" "\n" msgstr "" "\n" " »addr« benutzt das gegebene Feld, um die Dateisystemadresse und den Typ\n" " zu setzen\n" "\n" " Beispiele:\n" "\n" " sb\n" " ein Wurzel-ino - setzt den Typ auf Inode und setzt die Position auf den\n" " Wurzel-Inode\n" " ein u.bmx[0].startblock (für Inode mit blockmap)\n" "\n" #: .././db/addr.c:72 .././db/attrset.c:86 .././db/attrset.c:189 #: .././db/crc.c:76 .././db/print.c:74 .././db/type.c:208 .././db/write.c:110 msgid "no current type\n" msgstr "kein aktueller Typ\n" #: .././db/addr.c:82 #, c-format msgid "no fields for type %s\n" msgstr "keine Felder für Typ %s\n" #: .././db/addr.c:94 msgid "array not allowed for addr command\n" msgstr "Array nicht für addr-Befehl erlaubt\n" #: .././db/addr.c:103 #, c-format msgid "no next type for field %s\n" msgstr "kein nächster Typ für Feld %s\n" #: .././db/addr.c:110 #, c-format msgid "no addr function for field %s (type %s)\n" msgstr "keine addr-Funktion für Feld %s (Typ %s)\n" #: .././db/agf.c:35 .././db/agfl.c:36 .././db/agi.c:35 .././db/sb.c:44 msgid "[agno]" msgstr "[agno]" #: .././db/agf.c:36 msgid "set address to agf header" msgstr "Adresse auf agf-Kopfzeilen setzen" #: .././db/agf.c:100 msgid "" "\n" " set allocation group free block list\n" "\n" " Example:\n" "\n" " agf 2 - move location to AGF in 2nd filesystem allocation group\n" "\n" " Located in the second sector of each allocation group, the AGF\n" " contains the root of two different freespace btrees:\n" " The 'cnt' btree keeps track freespace indexed on section size.\n" " The 'bno' btree tracks sections of freespace indexed on block number.\n" msgstr "" "\n" " Liste freier Blöcke der Zuordnungsgruppe setzen\n" "\n" " Beispiel:\n" "\n" " agf 2 - Ort auf AGF in 2.Dateisystemzuordnungsgruppe setzen.\n" "\n" " Im zweiten Abschnitt jeder Zuordnungsgruppe gelegen, enthält das AGF die\n" " Wurzel zweier unterschiedlicher freespace btrees:\n" " Der »cnt«-btree folgt Abschnitten von freespace, indiziert auf\n" " Blocknummer.\n" #: .././db/agf.c:125 .././db/agfl.c:106 .././db/agi.c:94 .././db/sb.c:167 #, c-format msgid "bad allocation group number %s\n" msgstr "falsche Zuteilungsgruppennummer %s\n" #: .././db/agfl.c:37 msgid "set address to agfl block" msgstr "Adresse auf agfl Block setzen" #: .././db/agfl.c:79 msgid "" "\n" " set allocation group freelist\n" "\n" " Example:\n" "\n" " agfl 5\n" " Located in the fourth sector of each allocation group,\n" " the agfl freelist for internal btree space allocation is maintained\n" " for each allocation group. This acts as a reserved pool of space\n" " separate from the general filesystem freespace (not used for user data).\n" "\n" msgstr "" "\n" " Zuteilungsgruppen-freelist setzen\n" "\n" " Beispiel:\n" "\n" " agfl 5\n" " Die agfl freelist, die sich für interne btree-Speicherzuteilung im\n" " vierten Abschnitt jeder Zuteilungsgruppe befindet, wird für jede\n" " Zuteilungsgruppe verwaltet. Dies agiert als ein reservierter Speicherpool\n" " getrennt vom allgemeinen Dateisystem-freespace (nicht für Benutzerdaten\n" " benutzt).\n" "\n" #: .././db/agi.c:36 msgid "set address to agi header" msgstr "Adressen auf agi-Kopfzeilen setzen" #: .././db/agi.c:69 msgid "" "\n" " set allocation group inode btree\n" "\n" " Example:\n" "\n" " agi 3 (set location to 3rd allocation group inode btree and type to 'agi')\n" "\n" " Located in the 3rd 512 byte block of each allocation group,\n" " the agi inode btree tracks all used/free inodes in the allocation group.\n" " Inodes are allocated in 16k 'chunks', each btree entry tracks a 'chunk'.\n" "\n" msgstr "" "\n" " Zuteilungsgruppen-Inode btree setzen\n" "\n" " Beispiel:\n" "\n" " agi 3 (setzt Ort auf 3. Zuteilungsgruppen-Inode btree und Typ auf »agi«)\n" "\n" " Der im dritten 512-Byte-Block von jeder Zuteilungsruppe gelegene\n" " agi-Inode btree spürt alle benutzten/freien Inodes in der\n" " Zuteilungsgruppe auf. Inodes sind in 16k-»chunks« zugeteilt, jeder\n" " btree-Eintrag folgt einem »chunk«.\n" "\n" #: .././db/attr.c:556 #, fuzzy msgid "Unknown attribute buffer type!\n" msgstr "Attributsdaten für Datei\n" #: .././db/attr.c:568 msgid "Writing unknown attribute buffer type!\n" msgstr "" #: .././db/attrset.c:38 msgid "[-r|-s|-p|-u] [-n] [-R|-C] [-v n] name" msgstr "[-r|-s|-p|-u] [-n] [-R|-C] [-v n] Name" #: .././db/attrset.c:39 msgid "set the named attribute on the current inode" msgstr "das Namens-Attribut des aktuellen Inodes setzen" #: .././db/attrset.c:42 msgid "[-r|-s|-p|-u] [-n] name" msgstr "[-r|-s|-p|-u] [-n] Name" #: .././db/attrset.c:43 msgid "remove the named attribute from the current inode" msgstr "das genannte Attribut aus dem aktuellen Inode entfernen" #: .././db/attrset.c:49 msgid "" "\n" " The 'attr_set' and 'attr_remove' commands provide interfaces for debugging\n" " the extended attribute allocation and removal code.\n" " Both commands require an attribute name to be specified, and the attr_set\n" " command allows an optional value length (-v) to be provided as well.\n" " There are 4 namespace flags:\n" " -r -- 'root'\n" " -u -- 'user'\t\t(default)\n" " -s -- 'secure'\n" "\n" " For attr_set, these options further define the type of set operation:\n" " -C -- 'create' - create attribute, fail if it already exists\n" " -R -- 'replace' - replace attribute, fail if it does not exist\n" " The backward compatibility mode 'noattr2' can be emulated (-n) also.\n" "\n" msgstr "" "\n" " Die »attr_set«- und xattr_remove«-Befehle stellen Schittstellen für die\n" " Fehlersuche in der erweiterten Attributszuteilung und Code-Entfernung\n" " zur Verfügung. Beide Befehle benötigen zur Angabe einen Attributs-Namen\n" " und der attr_set-Befehl erlaubt außerdem die Angabe einer optionalen\n" " Wertlänge (-v).\n" " Es gibt vier Namensraumkennzeichen:\n" " -r -- 'root'\n" " -u -- 'user'\t\t(Vorgabe)\n" " -s -- 'secure'\n" "\n" " Für attr-set definieren diese Optionen weiterhin den Typ der\n" " Einstelloperation:\n" " -C -- »createy - erzeugt Attribut, scheitert, wenn es bereits besteht\n" " -R -- »replace« - ersetzt Attribut, scheitert, wenn es nicht besteht\n" " Außerdem kann der Rückwärtskompatibilitätsmodus »noattr2« (-n) emuliert\n" " werden.\n" #: .././db/attrset.c:90 .././db/attrset.c:193 msgid "current type is not inode\n" msgstr "aktueller Typ ist nicht Inode\n" #: .././db/attrset.c:125 #, c-format msgid "bad attr_set valuelen %s\n" msgstr "falsche attr_set valuelen %s\n" #: .././db/attrset.c:131 msgid "bad option for attr_set command\n" msgstr "falsche Option für attr_set-Befehl\n" #: .././db/attrset.c:137 msgid "too few options for attr_set (no name given)\n" msgstr "zu wenige Optionen für attr_set (kein Name angegeben)\n" #: .././db/attrset.c:146 #, c-format msgid "cannot allocate buffer (%d)\n" msgstr "Puffer (%d) kann nicht zugeteilt werden\n" #: .././db/attrset.c:155 .././db/attrset.c:230 #, c-format msgid "failed to iget inode %llu\n" msgstr "iget von Inode %llu fehlgeschlagen\n" #: .././db/attrset.c:162 #, c-format msgid "failed to set attr %s on inode %llu\n" msgstr "attr %s auf Inode %llu zu setzen ist fehlgeschlagen\n" #: .././db/attrset.c:217 msgid "bad option for attr_remove command\n" msgstr "falsche Option für attr_remove-Befehl\n" #: .././db/attrset.c:223 msgid "too few options for attr_remove (no name given)\n" msgstr "zu wenige Optionen für attr_remove (kein Name angegeben)\n" #: .././db/attrset.c:236 #, c-format msgid "failed to remove attr %s from inode %llu\n" msgstr "Entfernen von attr %s von Inode %llu fehlgeschlagen\n" #: .././db/block.c:43 .././db/block.c:49 msgid "filoff" msgstr "filoff" #: .././db/block.c:44 msgid "set address to file offset (attr fork)" msgstr "Adresse auf Dateiversatz setzen (attr fork)" #: .././db/block.c:46 msgid "[d]" msgstr "[d]" #: .././db/block.c:47 msgid "set address to daddr value" msgstr "Adresse auf daddr-Wert setzen" #: .././db/block.c:50 msgid "set address to file offset (data fork)" msgstr "Adresse auf Dateiversatz setzen (Daten-fork)" #: .././db/block.c:52 msgid "[fsb]" msgstr "[fsb]" #: .././db/block.c:53 msgid "set address to fsblock value" msgstr "Adresse auf fsblock-Wert setzen" #: .././db/block.c:59 msgid "" "\n" " Example:\n" "\n" " 'ablock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's attribute fork. The filesystem block size is specified in\n" " the superblock.\n" "\n" msgstr "" "\n" " Beispiel:\n" "\n" " »ablock 23« - setzt die Dateiposition auf den 23. Dateisystemblock im\n" " Attributs-Fork des Inodes. Die Dateisystemblockgröße ist im Superblock\n" " angegeben.\n" "\n" #: .././db/block.c:82 .././db/block.c:177 #, c-format msgid "bad block number %s\n" msgstr "falsche Blocknummer %s\n" #: .././db/block.c:90 msgid "no attribute data for file\n" msgstr "Attributsdaten für Datei\n" #: .././db/block.c:96 msgid "file attr block is unmapped\n" msgstr "attr-Block der Datei ist nicht abgebildet\n" #: .././db/block.c:119 msgid "" "\n" " Example:\n" "\n" " 'daddr 102' - sets position to the 102nd absolute disk block\n" " (512 byte block).\n" msgstr "" "\n" " Beispiel:\n" "\n" " »daddr 102« - setzt Position auf den 102. absoluten Plattenblock\n" " (512 Byte-Block).\n" #: .././db/block.c:135 #, c-format msgid "current daddr is %lld\n" msgstr "aktuelle daddr ist %lld\n" #: .././db/block.c:141 #, c-format msgid "bad daddr %s\n" msgstr "falsche daddr %s\n" #: .././db/block.c:153 msgid "" "\n" " Example:\n" "\n" " 'dblock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's data fork. The filesystem block size is specified in the\n" " superblock.\n" "\n" msgstr "" "\n" " Beispiel:\n" "\n" " »dblock 23« - setzt die Dateiposition auf den 23. Dateisystemblock im\n" " Daten-Fork des Inodes. Die Dateisystemblockgröße ist im Superblock\n" " angegeben.\n" "\n" #: .././db/block.c:185 msgid "no type for file data\n" msgstr "kein Typ für Dateidaten\n" #: .././db/block.c:192 msgid "file data block is unmapped\n" msgstr "Dateidatenblock ist nicht abgebildet\n" #: .././db/block.c:210 msgid "" "\n" " Example:\n" "\n" " 'fsblock 1023' - sets the file position to the 1023rd filesystem block.\n" " The filesystem block size is specified in the superblock and set during\n" " mkfs time. Offset is absolute (not AG relative).\n" "\n" msgstr "" "\n" " Beispiel:\n" "\n" " »fsblock 1023« - setzt die Dateiposition auf den 1023. Dateisystemblock.\n" " Die Dateisystemblockgröße ist im Superblock angegeben und wurde während \n" " der mkfs-Zeit gesetzt. Versatz ist absolut (nicht AG-relativ).\n" "\n" #: .././db/block.c:229 #, c-format msgid "current fsblock is %lld\n" msgstr "aktueller fsblock ist %lld\n" #: .././db/block.c:235 .././db/block.c:241 #, c-format msgid "bad fsblock %s\n" msgstr "falscher fsblock %s\n" #: .././db/bmap.c:39 msgid "[-ad] [block [len]]" msgstr "[-ad] [Block [len]]" #: .././db/bmap.c:40 msgid "show block map for current file" msgstr "Blockkarte für aktuelle Datei anzeigen" #: .././db/bmap.c:152 .././db/inode.c:424 msgid "no current inode\n" msgstr "kein aktueller Inode\n" #: .././db/bmap.c:165 msgid "bad option for bmap command\n" msgstr "falsche Option für bmap-Befehl\n" #: .././db/bmap.c:182 #, c-format msgid "bad block number for bmap %s\n" msgstr "falsche Blocknummer für bmap %s\n" #: .././db/bmap.c:190 #, c-format msgid "bad len for bmap %s\n" msgstr "falsche len für bmap %s\n" #: .././db/bmap.c:213 #, c-format msgid "%s offset %lld startblock %llu (%u/%u) count %llu flag %u\n" msgstr "%s Versatz %lld Startblock %llu (%u/%u) zählt %llu Flag %u\n" #: .././db/bmap.c:215 .././db/check.c:2224 .././db/check.c:2236 #: .././db/check.c:2263 .././repair/dinode.c:52 msgid "data" msgstr "Daten" #: .././db/bmap.c:215 .././db/check.c:2224 .././db/check.c:2236 #: .././db/check.c:2263 .././repair/dinode.c:53 msgid "attr" msgstr "attr" #: .././db/check.c:378 msgid "free block usage information" msgstr "Information über freie Blöcke" #: .././db/check.c:381 msgid "[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..." msgstr "[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..." #: .././db/check.c:382 msgid "get block usage and check consistency" msgstr "Blockbenutzung erhalten und Konsistenz prüfen" #: .././db/check.c:385 msgid "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ..." msgstr "" "[-n Anzahl] [-x Mindestlänge] [-y Maximallänge] [-s füllen] [-0123] [-t " "Typ] ..." #: .././db/check.c:386 msgid "trash randomly selected block(s)" msgstr "zufällig ausgewähle Blöcke wegwerfen" #: .././db/check.c:389 msgid "[-n] [-c blockcount]" msgstr "[-n] [-c Blockanzahl]" #: .././db/check.c:390 msgid "print usage for current block(s)" msgstr "Benutzung für aktuelle Blöcke ausgeben" #: .././db/check.c:393 msgid "[-s] [-i ino] ..." msgstr "[-s] [-i ino] ..." #: .././db/check.c:394 msgid "print inode-name pairs" msgstr "Inode-Namenspaare ausgeben" #: .././db/check.c:414 #, c-format msgid "-i %lld bad inode number\n" msgstr "-i %lld falsche Inode-Nummer\n" #: .././db/check.c:426 #, c-format msgid "inode %lld add link, now %u\n" msgstr "Inode %lld Verweis hinzufügen, nun %u\n" #: .././db/check.c:453 #, c-format msgid "inode %lld parent %lld\n" msgstr "Inode %lld Übergeordnet %lld\n" #: .././db/check.c:766 msgid "block usage information not allocated\n" msgstr "Blockbenutzungsinformationen nicht zugeteilt\n" #: .././db/check.c:804 msgid "already have block usage information\n" msgstr "Blockbenutzungsinformationen bereits erhalten\n" #: .././db/check.c:821 .././db/check.c:922 msgid "WARNING: this may be a newer XFS filesystem.\n" msgstr "WARNUNG: Dies könnte ein neueres XFS-Dateisystem sein\n" #: .././db/check.c:857 #, c-format msgid "sb_icount %lld, counted %lld\n" msgstr "sb_icount %lld, gezählt %lld\n" #: .././db/check.c:863 #, c-format msgid "sb_ifree %lld, counted %lld\n" msgstr "sb_ifree %lld, gezählt %lld\n" #: .././db/check.c:869 #, c-format msgid "sb_fdblocks %lld, counted %lld\n" msgstr "sb_fdblocks %lld, gezählt %lld\n" #: .././db/check.c:875 #, c-format msgid "sb_fdblocks %lld, aggregate AGF count %lld\n" msgstr "sb_fdblocks %lld, gesamte AGF-Anzahl %lld\n" #: .././db/check.c:881 #, c-format msgid "sb_frextents %lld, counted %lld\n" msgstr "sb_frextents %lld, gezählt %lld\n" #: .././db/check.c:888 #, c-format msgid "sb_features2 (0x%x) not same as sb_bad_features2 (0x%x)\n" msgstr "sb_features2 (0x%x) entspricht nicht sb_bad_features2 (0x%x)\n" #: .././db/check.c:897 #, c-format msgid "sb versionnum missing attr bit %x\n" msgstr "sb-Versionsnummer fehlt attr-Bit %x\n" #: .././db/check.c:904 #, c-format msgid "sb versionnum missing quota bit %x\n" msgstr "sb-Versionsnummer fehlt Quota-Bit %x\n" #: .././db/check.c:911 #, c-format msgid "sb versionnum extra align bit %x\n" msgstr "zusätzliches sb-Versionsnummerausrichtungs-Bit %x\n" #: .././db/check.c:950 msgid "zeroed" msgstr "auf Null gesetzt" #: .././db/check.c:950 msgid "set" msgstr "setze" #: .././db/check.c:950 msgid "flipped" msgstr "umgeblättert" #: .././db/check.c:950 msgid "randomized" msgstr "randomisiert" #: .././db/check.c:958 #, fuzzy, c-format msgid "zero-length block %u/%u buffer to trash??\n" msgstr "Block %u/%u wird auf %s gesetzt\n" #: .././db/check.c:977 #, c-format msgid "can't read block %u/%u for trashing\n" msgstr "Block %u/%u zum Wegwerfen kann nicht gelesen werden\n" #: .././db/check.c:1006 #, c-format msgid "blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n" msgstr "blocktrash: %u/%u %s Block %d Bit%s startet %d:%d %s\n" #: .././db/check.c:1085 #, c-format msgid "bad blocktrash count %s\n" msgstr "falsche blocktrash-Anzahl %s\n" #: .././db/check.c:1097 #, fuzzy, c-format msgid "bad blocktrash offset %s\n" msgstr "falsche blocktrash-Anzahl %s\n" #: .././db/check.c:1114 #, c-format msgid "bad blocktrash type %s\n" msgstr "falscher blocktrash-Typ %s\n" #: .././db/check.c:1123 #, c-format msgid "bad blocktrash min %s\n" msgstr "falsches blocktrash-Minimum %s\n" #: .././db/check.c:1131 #, c-format msgid "bad blocktrash max %s\n" msgstr "falsches blocktrash-Maximum %s\n" #: .././db/check.c:1139 msgid "bad option for blocktrash command\n" msgstr "falscher Option für blocktrash-Befehl\n" #: .././db/check.c:1144 .././db/check.c:1235 msgid "must run blockget first\n" msgstr "zuerst muss blockget ausgeführt werden\n" #: .././db/check.c:1148 #, fuzzy msgid "nothing on stack\n" msgstr "nichts zu schreiben\n" #: .././db/check.c:1152 msgid "bad min/max for blocktrash command\n" msgstr "falsches Minimum/Maximum für blocktrash-Befehl\n" #: .././db/check.c:1170 #, c-format msgid "blocktrash: seed %u\n" msgstr "blocktrash: %u füllen\n" #: .././db/check.c:1186 msgid "blocktrash: no matching blocks\n" msgstr "blocktrash: keine passenden Blöcke\n" #: .././db/check.c:1250 #, c-format msgid "bad blockuse count %s\n" msgstr "falsche blockuse-Anzahl %s\n" #: .././db/check.c:1256 .././db/check.c:1980 msgid "must run blockget -n first\n" msgstr "zuerst muss »blockget -n« ausgeführt werden\n" #: .././db/check.c:1262 msgid "bad option for blockuse command\n" msgstr "falsche Option für Befehl blockuse\n" #: .././db/check.c:1269 #, c-format msgid "block %llu (%u/%u) type %s" msgstr "Block %llu (%u/%u) Typ %s" #: .././db/check.c:1273 #, c-format msgid " inode %lld" msgstr "Inode %lld" #: .././db/check.c:1317 #, c-format msgid "block %u/%u expected type %s got %s\n" msgstr "Block %u/%u erwartete Typ %s bekam %s\n" #: .././db/check.c:1350 #, c-format msgid "blocks %u/%u..%u claimed by inode %lld\n" msgstr "Blöcke %u/%u..%u werden von Inode %lld beansprucht\n" #: .././db/check.c:1358 #, c-format msgid "block %u/%u claimed by inode %lld, previous inum %lld\n" msgstr "Block %u/%u von Inode %lld beansprucht, vorherige inum %lld\n" #: .././db/check.c:1387 #, c-format msgid "link count mismatch for inode %lld (name %s), nlink %d, counted %d\n" msgstr "" "keine Übereinstimmung bei Verweisanzahl für Inode %lld (Name %s), nlink %d, " "gezählt %d\n" #: .././db/check.c:1395 #, c-format msgid "disconnected inode %lld, nlink %d\n" msgstr "getrennter Inode %lld, nlink %d\n" #: .././db/check.c:1399 #, c-format msgid "allocated inode %lld has 0 link count\n" msgstr "zugeteilter Inode %lld hat Verweisanzahl 0\n" #: .././db/check.c:1409 #, c-format msgid "inode %lld name %s\n" msgstr "Inode %lld Name %s\n" #: .././db/check.c:1443 .././db/check.c:1458 #, c-format msgid "block %u/%u out of range\n" msgstr "Block %u/%u außerhalb des Bereichs\n" #: .././db/check.c:1446 .././db/check.c:1461 #, c-format msgid "blocks %u/%u..%u out of range\n" msgstr "Blöcke %u/%u..%u außerhalb des Bereichs\n" #: .././db/check.c:1484 #, c-format msgid "rtblock %llu expected type %s got %s\n" msgstr "rtblock %llu erwartete Typ %s bekam %s\n" #: .././db/check.c:1504 #, c-format msgid "rtblocks %llu..%llu claimed by inode %lld\n" msgstr "rtblocks %llu..%llu von Inode %lld beansprucht\n" #: .././db/check.c:1513 #, c-format msgid "rtblock %llu claimed by inode %lld, previous inum %lld\n" msgstr "rtblock %llu von Inode %lld beansprucht, vorheriger inum %lld\n" #: .././db/check.c:1531 #, c-format msgid "root inode %lld is missing\n" msgstr "Wurzel-Inode %lld fehlt\n" #: .././db/check.c:1536 #, c-format msgid "root inode %lld is not a directory\n" msgstr "Wurzel-Inode %lld ist kein Verzeichnis\n" #: .././db/check.c:1552 #, c-format msgid "rtblock %llu out of range\n" msgstr "rtblock %llu außerhalb des Bereichs\n" #: .././db/check.c:1596 #, c-format msgid "blocks %u/%u..%u claimed by block %u/%u\n" msgstr "Blöcke %u/%u..%u von Block %u/%u beansprucht\n" #: .././db/check.c:1610 #, c-format msgid "setting block %u/%u to %s\n" msgstr "Block %u/%u wird auf %s gesetzt\n" #: .././db/check.c:1633 #, c-format msgid "setting rtblock %llu to %s\n" msgstr "rtblock %llu wird auf %s gesetzt\n" #: .././db/check.c:1654 .././repair/rt.c:151 #, c-format msgid "rt summary mismatch, size %d block %llu, file: %d, computed: %d\n" msgstr "" "rt-Zusammenfassung stimmt nicht überein, Größe %d Block %llu, Datei: %d,\n" "berechnet: %d\n" #: .././db/check.c:1679 #, c-format msgid "block %u/%u type %s not expected\n" msgstr "Block %u/%u Typ %s nicht erwartet\n" #: .././db/check.c:1700 #, c-format msgid "rtblock %llu type %s not expected\n" msgstr "rtblock %llu Typ %s nicht erwartet\n" #: .././db/check.c:1737 #, c-format msgid "dir ino %lld missing leaf entry for %x/%x\n" msgstr "dir ino %lld fehlt der Blatteintrag für %x/%x\n" #: .././db/check.c:1856 #, c-format msgid "bad superblock magic number %x, giving up\n" msgstr "falsche Magische Nummer %x von Superblock, es wird aufgegeben\n" #: .././db/check.c:1910 msgid "bad option for blockget command\n" msgstr "falsche Option für blockget-Befehl\n" #: .././db/check.c:1997 #, c-format msgid "bad option -%c for ncheck command\n" msgstr "falsche Option -%c für ncheck-Befehl\n" #: .././db/check.c:2071 #, c-format msgid "block 0 for directory inode %lld is missing\n" msgstr "Block 0 für Verzeichnis-Inode %lld fehlt\n" #: .././db/check.c:2091 #, c-format msgid "can't read block 0 for directory inode %lld\n" msgstr "Block 0 für Verzeichnis-Inode %lld kann nicht gelesen werden\n" #: .././db/check.c:2137 #, c-format msgid "inode %lld extent [%lld,%lld,%lld,%d]\n" msgstr "Inode %lld Umfang [%lld,%lld,%lld,%d]\n" #: .././db/check.c:2140 #, c-format msgid "bmap rec out of order, inode %lld entry %d\n" msgstr "bmap rec außer Betrieb, Inode %lld Eintrag %d \n" #: .././db/check.c:2146 #, c-format msgid "inode %lld bad rt block number %lld, offset %lld\n" msgstr "Inode %lld falsche rt-Blocknummer %lld, Versatz %lld\n" #: .././db/check.c:2156 .././db/check.c:2162 #, c-format msgid "inode %lld bad block number %lld [%d,%d], offset %lld\n" msgstr "Inode %lld falsche Block-Nummer %lld [%d,%d], Versatz %lld\n" #: .././db/check.c:2180 .././db/check.c:2194 #, c-format msgid "inode %lld block %lld at offset %lld\n" msgstr "Inode %lld Block %lld bei Versatz %lld\n" #: .././db/check.c:2221 #, c-format msgid "level for ino %lld %s fork bmap root too large (%u)\n" msgstr "Stufe für ino %lld %s-Fork bmap-Wurzel zu groß (%u)\n" #: .././db/check.c:2233 #, c-format msgid "numrecs for ino %lld %s fork bmap root too large (%u)\n" msgstr "numrecs für ino %lld %s-Fork bmap-Wurzel zu groß (%u)\n" #: .././db/check.c:2260 #, c-format msgid "extent count for ino %lld %s fork too low (%d) for file format\n" msgstr "Umfanganzahl für ino %lld %s-Fork zu niedrig (%d) für Dateiformat\n" #: .././db/check.c:2312 .././db/check.c:3338 #, c-format msgid "bad directory data magic # %#x for dir ino %lld block %d\n" msgstr "falsche magische Verzeichnisdaten-# %#x für ino %lld Block %d\n" #: .././db/check.c:2330 #, c-format msgid "bad block directory tail for dir ino %lld\n" msgstr "falsches Verzeichnisblockende für dir ino %lld\n" #: .././db/check.c:2375 #, c-format msgid "dir %lld block %d bad free entry at %d\n" msgstr "dir %lld Block %d falscher freier Eintrag bei %d\n" #: .././db/check.c:2399 #, c-format msgid "dir %lld block %d zero length entry at %d\n" msgstr "dir %lld Block %d Eintrag der Länge Null bei %d\n" #: .././db/check.c:2408 #, c-format msgid "dir %lld block %d bad entry at %d\n" msgstr "dir %lld Block %d falscher Eintrag bei %d\n" #: .././db/check.c:2426 #, c-format msgid "dir %lld block %d entry %*.*s %lld\n" msgstr "dir %lld Block %d Eintrag %*.*s %lld\n" #: .././db/check.c:2433 #, c-format msgid "dir %lld block %d entry %*.*s bad inode number %lld\n" msgstr "dir %lld Block %d Eintrag %*.*s falsche Inode-Nummer %lld\n" #: .././db/check.c:2443 #, c-format msgid "multiple .. entries in dir %lld (%lld, %lld)\n" msgstr "mehrere .. Einträge in dir %lld (%lld, %lld)\n" #: .././db/check.c:2460 #, c-format msgid "dir %lld entry . inode number mismatch (%lld)\n" msgstr "dir %lld Eintrag . Inode-Nummer stimmt nicht überein (%lld)\n" #: .././db/check.c:2474 #, c-format msgid "dir %lld block %d bad count %u\n" msgstr "dir %lld Block %d falsche Anzahl %u\n" #: .././db/check.c:2485 .././db/check.c:3352 #, c-format msgid "dir %lld block %d extra leaf entry %x %x\n" msgstr "dir %lld Block %d zusätzlicher Blatteintrag %x %x\n" #: .././db/check.c:2497 #, c-format msgid "dir %lld block %d bad bestfree data\n" msgstr "dir %lld Block %d falsche bestfree-Daten\n" #: .././db/check.c:2505 #, c-format msgid "dir %lld block %d bad block tail count %d (stale %d)\n" msgstr "dir %lld Block %d falsche Blockgrößenanzahl %d (abgelaufen %d)\n" #: .././db/check.c:2515 #, c-format msgid "dir %lld block %d bad stale tail count %d\n" msgstr "dir %lld Block %d falsche Anzahl abgelaufener Blöcke %d\n" #: .././db/check.c:2521 #, c-format msgid "dir %lld block %d consecutive free entries\n" msgstr "dir %lld Block %d aufeinander folgende freie Einträge\n" #: .././db/check.c:2527 #, c-format msgid "dir %lld block %d entry/unused tag mismatch\n" msgstr "dir %lld Block %d Eintrag/nichtbenutzte Markierung passt nicht\n" #: .././db/check.c:2576 #, c-format msgid "no . entry for directory %lld\n" msgstr "kein .-Eintrag für Verzeichnis %lld\n" #: .././db/check.c:2581 #, c-format msgid "no .. entry for directory %lld\n" msgstr "kein ..-Eintrag für Verzeichnis %lld\n" #: .././db/check.c:2585 #, c-format msgid ". and .. same for non-root directory %lld\n" msgstr ".- und ..-Einträge für Nicht-Wurzelverzeichnis %lld gleich\n" #: .././db/check.c:2590 #, c-format msgid "root directory %lld has .. %lld\n" msgstr "Wurzelverzeichnis %lld hat .. %lld\n" #: .././db/check.c:2623 #, c-format msgid "bad size (%lld) or format (%d) for directory inode %lld\n" msgstr "falsche Größe (%lld) oder Format (%d) für Verzeichnis-Inode %lld\n" #: .././db/check.c:2651 #, c-format msgid "bad number of extents %d for inode %lld\n" msgstr "falsche Anzahl von Ausweitungen %d für Inode %lld\n" #: .././db/check.c:2723 #, c-format msgid "bad magic number %#x for inode %lld\n" msgstr "falsche Magische Nummer %#x für Inode %lld\n" #: .././db/check.c:2730 #, c-format msgid "bad version number %#x for inode %lld\n" msgstr "falsche Versionsnummer %#x für Inode %lld\n" #: .././db/check.c:2738 #, c-format msgid "bad nblocks %lld for free inode %lld\n" msgstr "falsche nblocks %lld für freien Inode %lld\n" #: .././db/check.c:2745 #, c-format msgid "bad nlink %d for free inode %lld\n" msgstr "falscher nlink %d für freien Inode %lld\n" #: .././db/check.c:2751 #, c-format msgid "bad mode %#o for free inode %lld\n" msgstr "falscher Modus %#o für freien Inode %lld\n" #: .././db/check.c:2760 #, c-format msgid "bad next unlinked %#x for inode %lld\n" msgstr "falsche nächste gelöste Verknüpfung %#x für Inode %lld\n" #: .././db/check.c:2771 #, c-format msgid "bad format %d for inode %lld type %#o\n" msgstr "falsches Format %d für Inode %lld Typ %#o\n" #: .././db/check.c:2779 #, c-format msgid "bad fork offset %d for inode %lld\n" msgstr "falsche Abspaltungsversatz %d für Inode %lld\n" #: .././db/check.c:2786 #, c-format msgid "bad attribute format %d for inode %lld\n" msgstr "falsches Attributformat %d für Inode %lld\n" #: .././db/check.c:2792 #, c-format msgid "" "inode %lld mode %#o fmt %s afmt %s nex %d anex %d nblk %lld sz %lld%s%s%s%s%s" "%s%s\n" msgstr "" "Inode %lld Modus %#o fmt %s afmt %s nex %d anex %d nblk %lld sz %lld%s%s%s%s" "%s%s%s\n" #: .././db/check.c:2911 #, c-format msgid "bad nblocks %lld for inode %lld, counted %lld\n" msgstr "falsche nblocks %lld für Inode %lld, gezählt %lld\n" #: .././db/check.c:2918 #, c-format msgid "bad nextents %d for inode %lld, counted %d\n" msgstr "falsche nextents %d für Inode %lld, gezählt %d\n" #: .././db/check.c:2924 #, c-format msgid "bad anextents %d for inode %lld, counted %d\n" msgstr "falsche anextents %d für Inode %lld, gezählt %d\n" #: .././db/check.c:2976 #, c-format msgid "local inode %lld data is too large (size %lld)\n" msgstr "lokales Inode-%lld-Daten-Unterelement ist zu groß (Größe = %lld)\n" #: .././db/check.c:2985 #, c-format msgid "local inode %lld attr is too large (size %d)\n" msgstr "lokales Inode-%lld-attr ist zu groß (Größe = %d)\n" #: .././db/check.c:3034 #, c-format msgid "dir inode %lld block %u=%llu\n" msgstr "dir inode %lld Block %u=%llu\n" #: .././db/check.c:3046 #, c-format msgid "can't read block %u for directory inode %lld\n" msgstr "Block %u für Verzeichnis-Inode %lld kann nicht gelesen werden\n" #: .././db/check.c:3060 #, c-format msgid "multiple .. entries in dir %lld\n" msgstr "mehrfache .. Einträge in Verzeichnis-Inode %lld\n" #: .././db/check.c:3082 #, c-format msgid "missing free index for data block %d in dir ino %lld\n" msgstr "freier Index für Datenblock %d in dir ino %lld fehlt\n" #: .././db/check.c:3110 .././db/check.c:3188 #, c-format msgid "bad free block firstdb %d for dir ino %lld block %d\n" msgstr "falscher freier Block firstdb %d für dir ino %lld Block %d\n" #: .././db/check.c:3121 .././db/check.c:3201 #, c-format msgid "bad free block nvalid/nused %d/%d for dir ino %lld block %d\n" msgstr "falscher freier Block nvalid/nused %d/%d für dir ino %lld Block %d\n" #: .././db/check.c:3135 .././db/check.c:3215 #, c-format msgid "bad free block ent %d is %d should be %d for dir ino %lld block %d\n" msgstr "" "falscher freier Block ent %d ist %d, sollte %d sein für dir ino %lld Block " "%d\n" #: .././db/check.c:3149 .././db/check.c:3229 #, c-format msgid "bad free block nused %d should be %d for dir ino %lld block %d\n" msgstr "" "falscher freier nused-Block %d sollte %d sein für dir ino %lld Block %d\n" #: .././db/check.c:3174 #, c-format msgid "bad free block magic # %#x for dir ino %lld block %d\n" msgstr "falsche frei magische Block-# %#x für ino %lld Block %d\n" #: .././db/check.c:3283 #, c-format msgid "bad leaf block forw/back pointers %d/%d for dir ino %lld block %d\n" msgstr "" "Falscher Blattblock Vorwärts-/Rückwärtszeiger %d/%d für dir ino %lld Block " "%d\n" #: .././db/check.c:3292 #, c-format msgid "single leaf block for dir ino %lld block %d should be at block %d\n" msgstr "" "einzelner Blattblock für dir ino %lld Block %d sollte bei Block %d sein\n" #: .././db/check.c:3304 #, c-format msgid "bestfree %d for dir ino %lld block %d doesn't match table value %d\n" msgstr "bestfree %d für dir ino %lld Block %d passt nicht zu Tabellenwert %d\n" #: .././db/check.c:3329 #, c-format msgid "bad node block level %d for dir ino %lld block %d\n" msgstr "falsche Knotenblockstufe %d für dir ino %lld Block %d\n" #: .././db/check.c:3361 #, fuzzy, c-format msgid "dir3 %lld block %d stale mismatch %d/%d\n" msgstr "dir %lld Block %d abgelaufene Nichtübereinstimmung %d/%d\n" #: .././db/check.c:3368 #, c-format msgid "dir %lld block %d stale mismatch %d/%d\n" msgstr "dir %lld Block %d abgelaufene Nichtübereinstimmung %d/%d\n" #: .././db/check.c:3424 #, c-format msgid "can't read block %lld for %s quota inode (fsblock %lld)\n" msgstr "" "Block %lld für %s Quota-Inode (fsblock %lld) kann nicht gelesen werden\n" #: .././db/check.c:3434 #, c-format msgid "%s dqblk %lld entry %d id %u bc %lld ic %lld rc %lld\n" msgstr "%s dqblk %lld Eintrag %d id %u bc %lld ic %lld rc %lld\n" #: .././db/check.c:3442 #, c-format msgid "bad magic number %#x for %s dqblk %lld entry %d id %u\n" msgstr "" "falsche Magische Nummer %#x für %s dqblk %lld Eintrag %d ID %u\n" "\n" #: .././db/check.c:3451 #, c-format msgid "bad version number %#x for %s dqblk %lld entry %d id %u\n" msgstr "falsche Versionsnummer %#x für %s dqblk %lld Eintrag %d ID %u\n" #: .././db/check.c:3461 #, c-format msgid "bad flags %#x for %s dqblk %lld entry %d id %u\n" msgstr "Falsche Markierungen %#x für %s dqblk %lld Eintrag %d ID %u\n" #: .././db/check.c:3470 #, c-format msgid "bad id %u for %s dqblk %lld entry %d id %u\n" msgstr "falsche ID %u für %s dqblk %lld Eintrag %d ID %u\n" #: .././db/check.c:3516 #, c-format msgid "block %lld for rtbitmap inode is missing\n" msgstr "Block %lld für rtbitmap-Inode fehlt\n" #: .././db/check.c:3527 #, c-format msgid "can't read block %lld for rtbitmap inode\n" msgstr "Block %lld für rtbitmap-Inode kann nicht gelesen werden\n" #: .././db/check.c:3583 #, c-format msgid "block %lld for rtsummary inode is missing\n" msgstr "Block %lld für rtsummary-Inode fehlt\n" #: .././db/check.c:3594 #, c-format msgid "can't read block %lld for rtsummary inode\n" msgstr "Block %lld für rtsummary-Inode kann nicht gelesen werden\n" #: .././db/check.c:3627 #, c-format msgid "dir %lld entry . %lld\n" msgstr "dir %lld Eintrag . %lld\n" #: .././db/check.c:3635 #, c-format msgid "dir %llu bad size in entry at %d\n" msgstr "dir %llu falsche Größe im Eintrag bei %d\n" #: .././db/check.c:3647 #, c-format msgid "dir %lld entry %*.*s bad inode number %lld\n" msgstr "dir %lld Eintrag %*.*s falsche Inode-Nummer %lld\n" #: .././db/check.c:3659 #, c-format msgid "dir %lld entry %*.*s offset %d %lld\n" msgstr "dir %lld Eintrag %*.*s Versatz %d %lld\n" #: .././db/check.c:3664 #, c-format msgid "dir %lld entry %*.*s bad offset %d\n" msgstr "dir %lld Eintrag %*.*s falscher Versatz %d\n" #: .././db/check.c:3677 #, c-format msgid "dir %llu size is %lld, should be %u\n" msgstr "dir %llu Größe ist %lld, sollte %u sein\n" #: .././db/check.c:3685 #, c-format msgid "dir %llu offsets too high\n" msgstr "dir %llu Versätze zu groß\n" #: .././db/check.c:3696 #, c-format msgid "dir %lld entry .. bad inode number %lld\n" msgstr "dir %lld Eintrag .. falsche Inode-Nummer %lld\n" #: .././db/check.c:3701 #, c-format msgid "dir %lld entry .. %lld\n" msgstr "dir %lld Eintrag .. %lld\n" #: .././db/check.c:3704 #, c-format msgid "dir %lld i8count mismatch is %d should be %d\n" msgstr "dir %lld i8count Nichtübereinstimmung ist %d sollte %d sein\n" #: .././db/check.c:3786 #, c-format msgid "%s quota id %u, have/exp" msgstr "%s Quota-ID %u, have/exp" #: .././db/check.c:3789 #, c-format msgid " bc %lld/%lld" msgstr " bc %lld/%lld" #: .././db/check.c:3793 #, c-format msgid " ic %lld/%lld" msgstr " ic %lld/%lld" #: .././db/check.c:3797 #, c-format msgid " rc %lld/%lld" msgstr " rc %lld/%lld" #: .././db/check.c:3853 #, c-format msgid "can't read superblock for ag %u\n" msgstr "Superblock für ag %u kann nicht gelesen werden\n" #: .././db/check.c:3862 #, c-format msgid "bad sb magic # %#x in ag %u\n" msgstr "falsche magische sb-# %#x in ag %u\n" #: .././db/check.c:3868 #, c-format msgid "bad sb version # %#x in ag %u\n" msgstr "falsche sb-Version # %#x in ag %u\n" #: .././db/check.c:3878 .././db/sb.c:217 msgid "mkfs not completed successfully\n" msgstr "mkfs nicht erfolgreich vervollständigt\n" #: .././db/check.c:3890 .././db/frag.c:370 #, c-format msgid "can't read agf block for ag %u\n" msgstr "agf-Block für ag %u kann nicht gelesen werden\n" #: .././db/check.c:3896 #, c-format msgid "bad agf magic # %#x in ag %u\n" msgstr "falsche magische agf-# %#x in ag %u\n" #: .././db/check.c:3902 #, c-format msgid "bad agf version # %#x in ag %u\n" msgstr "falsche agf-Version # %#x im ag %u\n" #: .././db/check.c:3918 .././db/frag.c:379 #, c-format msgid "can't read agi block for ag %u\n" msgstr "agi-Block für ag %u kann nicht gelesen werden\n" #: .././db/check.c:3924 #, c-format msgid "bad agi magic # %#x in ag %u\n" msgstr "falsche magische agi-# %#x in ag %u\n" #: .././db/check.c:3930 #, c-format msgid "bad agi version # %#x in ag %u\n" msgstr "falsche agi-Version # %#x in ag %u\n" #: .././db/check.c:3973 .././repair/scan.c:2252 #, c-format msgid "agf_freeblks %u, counted %u in ag %u\n" msgstr "agf_freeblks %u, gezählt %u in ag %u\n" #: .././db/check.c:3980 .././repair/scan.c:2257 #, c-format msgid "agf_longest %u, counted %u in ag %u\n" msgstr "agf_longest %u, gezählt %u in ag %u\n" #: .././db/check.c:3988 #, c-format msgid "agf_btreeblks %u, counted %u in ag %u\n" msgstr "agf_btreeblks %u, gezählt %u in ag %u\n" #: .././db/check.c:3996 .././repair/scan.c:2306 #, c-format msgid "agi_count %u, counted %u in ag %u\n" msgstr "agi_count %u, gezählt %u in ag %u\n" #: .././db/check.c:4003 .././repair/scan.c:2311 #, c-format msgid "agi_freecount %u, counted %u in ag %u\n" msgstr "agi_freecount %u, gezählt %u in ag %u\n" #: .././db/check.c:4012 #, c-format msgid "agi unlinked bucket %d is %u in ag %u (inode=%lld)\n" msgstr "agi gelöster Verweis Behälter %d ist %u in ag %u (Inode=%lld)\n" #: .././db/check.c:4050 #, c-format msgid "can't read agfl block for ag %u\n" msgstr "agfl-Block für ag %u kann nicht gelesen werden\n" #: .././db/check.c:4060 .././db/freesp.c:255 .././repair/scan.c:2142 #, c-format msgid "agf %d freelist blocks bad, skipping freelist scan\n" msgstr "" #: .././db/check.c:4082 #, c-format msgid "freeblk count %u != flcount %u in ag %u\n" msgstr "freeblk-Anzahl %u != flcount %u in ag %u\n" #: .././db/check.c:4111 .././db/check.c:4139 .././db/frag.c:402 #: .././db/frag.c:425 .././db/freesp.c:289 #, c-format msgid "can't read btree block %u/%u\n" msgstr "btree-Block %u/%u kann nicht gelesen werden\n" #: .././db/check.c:4173 #, c-format msgid "bad magic # %#x in inode %lld bmbt block %u/%u\n" msgstr "falsche magische # %#x in Inode %lld bmbt-Block %u/%u\n" #: .././db/check.c:4180 #, c-format msgid "expected level %d got %d in inode %lld bmbt block %u/%u\n" msgstr "erwartete Stufe %d hat %d in Inode %lld bmbt-Block %u/%u\n" #: .././db/check.c:4192 .././db/check.c:4209 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in inode %lld bmap block %lld\n" msgstr "" "falsche btree nrecs (%u, Min=%u, Max=%u) in Inode %lld bmap-Block %lld\n" #: .././db/check.c:4238 #, c-format msgid "bad magic # %#x in btbno block %u/%u\n" msgstr "falsche magische # %#x in btbno-Block %u/%u\n" #: .././db/check.c:4247 #, c-format msgid "expected level %d got %d in btbno block %u/%u\n" msgstr "erwartete Stufe %d hat %d in btbno-Block %u/%u\n" #: .././db/check.c:4256 .././db/check.c:4284 .././db/check.c:4330 #: .././db/check.c:4361 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in btbno block %u/%u\n" msgstr "falsche btree nrecs (%u, Min=%u, Max=%u) in btbno-Block %u/%u\n" #: .././db/check.c:4271 .././repair/scan.c:666 #, c-format msgid "out-of-order bno btree record %d (%u %u) block %u/%u\n" msgstr "außer Betreib bno btree Datensatz %d (%u %u) Block %u/%u\n" #: .././db/check.c:4312 #, c-format msgid "bad magic # %#x in btcnt block %u/%u\n" msgstr "falsche magische # %#x in btcnt-Block %u/%u\n" #: .././db/check.c:4321 #, c-format msgid "expected level %d got %d in btcnt block %u/%u\n" msgstr "erwartete Stufe %d hat %d in btcnt-Block %u/%u\n" #: .././db/check.c:4349 .././repair/scan.c:678 #, c-format msgid "out-of-order cnt btree record %d (%u %u) block %u/%u\n" msgstr "außer Betreib cnt btree Datensatz %d (%u %u) Block %u/%u\n" #: .././db/check.c:4407 #, c-format msgid "bad magic # %#x in inobt block %u/%u\n" msgstr "falsche magische # %#x in inobt-Block %u/%u\n" #: .././db/check.c:4414 #, c-format msgid "expected level %d got %d in inobt block %u/%u\n" msgstr "erwartete Stufe %d hat %d in inobt-Block %u/%u\n" #: .././db/check.c:4423 .././db/check.c:4509 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in inobt block %u/%u\n" msgstr "falsche btree nrecs (%u, Min=%u, Max=%u) in inobt-Block %u/%u\n" #: .././db/check.c:4466 .././db/frag.c:494 #, c-format msgid "can't read inode block %u/%u\n" msgstr "btree-Block %u/%u kann nicht gelesen werden\n" #: .././db/check.c:4497 #, c-format msgid "ir_freecount/free mismatch, inode chunk %u/%u, freecount %d nfree %d\n" msgstr "" "ir_freecount/free Nichtübereinstimmung, Inode Speicherstück %u/%u, freecount " "%d nfree %d\n" #: .././db/check.c:4550 #, fuzzy, c-format msgid "bad magic # %#x in finobt block %u/%u\n" msgstr "falsche magische # %#x in inobt-Block %u/%u\n" #: .././db/check.c:4557 #, fuzzy, c-format msgid "expected level %d got %d in finobt block %u/%u\n" msgstr "erwartete Stufe %d hat %d in inobt-Block %u/%u\n" #: .././db/check.c:4566 .././db/check.c:4609 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in finobt block %u/%u\n" msgstr "falsche btree nrecs (%u, Min=%u, Max=%u) in inobt-Block %u/%u\n" #: .././db/check.c:4636 #, fuzzy, c-format msgid "bad magic # %#x in rmapbt block %u/%u\n" msgstr "falsche magische # %#x in inobt-Block %u/%u\n" #: .././db/check.c:4643 #, fuzzy, c-format msgid "expected level %d got %d in rmapbt block %u/%u\n" msgstr "erwartete Stufe %d hat %d in inobt-Block %u/%u\n" #: .././db/check.c:4656 .././db/check.c:4680 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in rmapbt block %u/%u\n" msgstr "falsche btree nrecs (%u, Min=%u, Max=%u) in inobt-Block %u/%u\n" #: .././db/check.c:4668 #, fuzzy, c-format msgid "out-of-order rmap btree record %d (%u %u) block %u/%u\n" msgstr "außer Betreib bno btree Datensatz %d (%u %u) Block %u/%u\n" #: .././db/check.c:4708 #, fuzzy, c-format msgid "bad magic # %#x in refcntbt block %u/%u\n" msgstr "falsche magische # %#x in inobt-Block %u/%u\n" #: .././db/check.c:4715 #, fuzzy, c-format msgid "expected level %d got %d in refcntbt block %u/%u\n" msgstr "erwartete Stufe %d hat %d in inobt-Block %u/%u\n" #: .././db/check.c:4724 .././db/check.c:4765 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in refcntbt block %u/%u\n" msgstr "falsche btree nrecs (%u, Min=%u, Max=%u) in inobt-Block %u/%u\n" #: .././db/check.c:4736 .././repair/scan.c:1350 #, c-format msgid "leftover CoW extent (%u/%u) len %u\n" msgstr "" #: .././db/check.c:4752 #, fuzzy, c-format msgid "out-of-order refcnt btree record %d (%u %u) block %u/%u\n" msgstr "außer Betreib cnt btree Datensatz %d (%u %u) Block %u/%u\n" #: .././db/check.c:4808 #, c-format msgid "setting inode to %lld for block %u/%u\n" msgstr "Inode wird auf %lld gesetzt für Block %u/%u\n" #: .././db/check.c:4840 #, c-format msgid "setting inode to %lld for rtblock %llu\n" msgstr "Inode wird auf %lld gesetzt für rtblock %llu\n" #: .././db/check.c:4856 #, c-format msgid "inode %lld nlink %u %s dir\n" msgstr "Inode %lld nlink %u %s dir\n" #: .././db/command.c:85 .././db/help.c:56 .././libxcmd/help.c:50 #, c-format msgid "command %s not found\n" msgstr "Befehl %s nicht gefunden\n" #: .././db/command.c:89 #, c-format msgid "bad argument count %d to %s, expected " msgstr "falsche Argument-Anzahl %d bis %s, erwartet" #: .././db/command.c:91 #, c-format msgid "at least %d" msgstr "mindestens %d" #: .././db/command.c:95 #, c-format msgid "between %d and %d" msgstr "zwischen %d und %d" #: .././db/command.c:96 msgid " arguments\n" msgstr "Argumente\n" #: .././db/convert.c:171 #, c-format msgid "bad argument count %d to convert, expected 3,5,7,9 arguments\n" msgstr "" "falsche Argument-Anzahl %d zu konvertieren, 3,5,7,9 Argumente erwartet\n" #: .././db/convert.c:176 .././db/convert.c:183 #, c-format msgid "unknown conversion type %s\n" msgstr "unbekannte Umwandlungstyp %s\n" #: .././db/convert.c:187 msgid "result type same as argument\n" msgstr "Ergebnistyp entspricht Argument\n" #: .././db/convert.c:191 #, c-format msgid "conflicting conversion type %s\n" msgstr "widersprüchlicher Umwandlungstyp %s\n" #: .././db/convert.c:269 #, c-format msgid "%s is not a number\n" msgstr "%s ist keine Zahl\n" #: .././db/crc.c:37 msgid "manipulate crc values for V5 filesystem structures" msgstr "" #: .././db/crc.c:50 msgid "" "\n" " 'crc' validates, invalidates, or recalculates the crc value for\n" " the current on-disk metadata structures in Version 5 filesystems.\n" "\n" " Usage: \"crc [-i|-r|-v]\"\n" "\n" msgstr "" #: .././db/crc.c:81 #, fuzzy, c-format msgid "current type (%s) is not a structure\n" msgstr "aktueller Typ ist nicht Inode\n" #: .././db/crc.c:98 #, fuzzy msgid "bad option for crc command\n" msgstr "falsche Opzion für frag-Befehl\n" #: .././db/crc.c:105 msgid "crc command accepts only one option\n" msgstr "" #: .././db/crc.c:111 #, fuzzy, c-format msgid "%s not in expert mode, writing disabled\n" msgstr "%s: Nicht im Expertenmodus, schreiben ausgeschaltet\n" #: .././db/crc.c:128 #, fuzzy, c-format msgid "No CRC field found for type %s\n" msgstr "keine Felder für Typ %s\n" #: .././db/crc.c:135 .././db/write.c:693 msgid "parsing error\n" msgstr "Auswertungsfehler\n" #: .././db/crc.c:171 msgid "Invalidating CRC:\n" msgstr "" #: .././db/crc.c:173 msgid "Recalculating CRC:\n" msgstr "" #: .././db/crc.c:181 msgid "Verifying CRC:\n" msgstr "" #: .././db/debug.c:27 msgid "[flagbits]" msgstr "[flagbits]" #: .././db/debug.c:28 msgid "set debug option bits" msgstr "Bits für Fehlersuchoptionen setzen" #: .././db/debug.c:42 #, c-format msgid "bad value for debug %s\n" msgstr "falscher Wert für Fehlersuche %s\n" #: .././db/dir2.c:1023 msgid "Unknown directory buffer type!\n" msgstr "" #: .././db/dir2.c:1035 msgid "Writing unknown directory buffer type!\n" msgstr "" #: .././db/dquot.c:37 msgid "[-g|-p|-u] id" msgstr "" #: .././db/dquot.c:38 #, fuzzy msgid "" "set current address to a group, project or user quota block for given ID" msgstr "aktuelle Adresse auf Projekt, Gruppe oder Benutzer-Quota setzen" #: .././db/dquot.c:129 msgid "bad option for dquot command\n" msgstr "falsche Option für dquot-Befehl\n" #: .././db/dquot.c:133 msgid "project" msgstr "Projekt" #: .././db/dquot.c:133 msgid "group" msgstr "Gruppe" #: .././db/dquot.c:133 msgid "user" msgstr "Benutzer" #: .././db/dquot.c:135 #, c-format msgid "dquot command requires one %s id argument\n" msgstr "dquot-Befehl benötigt ein %s ID-Argument\n" #: .././db/dquot.c:145 #, c-format msgid "no %s quota inode present\n" msgstr "kein %s Quota-Inode vorhanden\n" #: .././db/dquot.c:150 #, c-format msgid "bad %s id for dquot %s\n" msgstr "falsche %s ID für dquot %s\n" #: .././db/dquot.c:162 #, c-format msgid "no %s quota data for id %d\n" msgstr "keine %s Quota-Daten für ID %d\n" #: .././db/echo.c:27 msgid "[args]..." msgstr "[args] ..." #: .././db/echo.c:28 msgid "echo arguments" msgstr "echo Argumente" #: .././db/faddr.c:40 .././db/faddr.c:63 msgid "no current allocation group, cannot set new addr\n" msgstr "keine aktuelle Zuteilungsgruppe, neue addr kann nicht gesetzt werden\n" #: .././db/faddr.c:45 .././db/faddr.c:117 .././db/faddr.c:148 #: .././db/faddr.c:180 .././db/faddr.c:202 .././db/faddr.c:232 #: .././db/faddr.c:262 .././db/faddr.c:316 .././db/faddr.c:335 msgid "null block number, cannot set new addr\n" msgstr "Nullblocknummer, neue addr kann nicht gesetzt werden\n" #: .././db/faddr.c:68 .././db/faddr.c:353 .././db/faddr.c:370 #: .././db/faddr.c:387 msgid "null inode number, cannot set new addr\n" msgstr "Null-Inode-Nummer, neue addr kann nicht gesetzt werden\n" #: .././db/faddr.c:88 msgid "null attribute block number, cannot set new addr\n" msgstr "Null-Attributsblocknummer, neue addr kann nicht gesetzt werden\n" #: .././db/faddr.c:94 msgid "attribute block is unmapped\n" msgstr "Attributsblock ist unmapped\n" #: .././db/faddr.c:123 .././db/faddr.c:155 .././db/faddr.c:208 #: .././db/faddr.c:239 msgid "file block is unmapped\n" msgstr "Dateiblock ist unmapped\n" #: .././db/faddr.c:285 msgid "null directory block number, cannot set new addr\n" msgstr "Null-Verzeichnisblocknummer, neue addr kann nicht gesetzt werden\n" #: .././db/faddr.c:292 msgid "directory block is unmapped\n" msgstr "Verzeichnisblock ist unmapped\n" #: .././db/flist.c:149 #, c-format msgid "field %s not found\n" msgstr "Feld %s nicht gefunden\n" #: .././db/flist.c:159 #, c-format msgid "no elements in %s\n" msgstr "keine Elemente in %s\n" #: .././db/flist.c:165 #, c-format msgid "indices %d-%d for field %s out of range %d-%d\n" msgstr "Indizes %d-%d für Feld %s außerhalb des Bereichs %d-%d\n" #: .././db/flist.c:173 #, c-format msgid "index %d for field %s out of range %d-%d\n" msgstr "Index %d für Feld %s außerhalb des Bereichs %d-%d\n" #: .././db/flist.c:187 #, c-format msgid "field %s is not an array\n" msgstr "Feld %s ist kein Array\n" #: .././db/flist.c:200 #, c-format msgid "field %s has no subfields\n" msgstr "Feld %s hat keine Unterfelder\n" #: .././db/flist.c:220 #, c-format msgid "fl@%p:\n" msgstr "fl@%p:\n" #: .././db/flist.c:221 #, c-format msgid "\tname=%s, fld=%p, child=%p, sibling=%p\n" msgstr "\tName=%s, fld=%p, Kind=%p, Geschwister=%p\n" #: .././db/flist.c:223 #, c-format msgid "\tlow=%d, high=%d, flags=%d (%s%s), offset=%d\n" msgstr "\tniedrig=%d, hoch=%d, Kennzeichen=%d (%s%s), Versatz=%d\n" #: .././db/flist.c:225 msgid "oklow " msgstr "oklow" #: .././db/flist.c:226 msgid "okhigh" msgstr "okhigh" #: .././db/flist.c:227 #, c-format msgid "\tfld->name=%s, fld->ftyp=%d (%s)\n" msgstr "\tfld->name=%s, fld->ftyp=%d (%s)\n" #: .././db/flist.c:230 #, c-format msgid "\tfld->flags=%d (%s%s%s%s%s)\n" msgstr "\tfld->flags=%d (%s%s%s%s%s)\n" #: .././db/flist.c:322 #, c-format msgid "bad syntax in field name %s\n" msgstr "falsche Syntax in Feldname %s\n" #: .././db/flist.c:378 #, c-format msgid "missing closing quote %s\n" msgstr "fehlendes schließendes Anführungszeichen %s\n" #: .././db/flist.c:395 #, c-format msgid "bad character in field %s\n" msgstr "falsches Zeichen in Feld %s\n" #: .././db/fprint.c:99 msgid "null" msgstr "null" #: .././db/frag.c:173 #, c-format msgid "actual %llu, ideal %llu, fragmentation factor %.2f%%\n" msgstr "aktuell %llu, ideal %llu, Unterteilungsfaktor %.2f%%\n" #: .././db/frag.c:175 msgid "Note, this number is largely meaningless.\n" msgstr "" #: .././db/frag.c:177 #, fuzzy, c-format msgid "Files on this filesystem average %.2f extents per file\n" msgstr "Statistiken über das Dateisystem der derzeit offenen Datei" #: .././db/frag.c:218 msgid "bad option for frag command\n" msgstr "falsche Opzion für frag-Befehl\n" #: .././db/frag.c:354 #, c-format msgid "inode %lld actual %lld ideal %lld\n" msgstr "Inode %lld aktuell %lld ideal %lld\n" #: .././db/frag.c:448 .././db/frag.c:458 #, c-format msgid "invalid numrecs (%u) in %s block\n" msgstr "ungültige numrecs (%u) in %s-Block\n" #: .././db/freesp.c:110 #, c-format msgid "total free extents %lld\n" msgstr "gesamte freie Extents %lld\n" #: .././db/freesp.c:111 #, c-format msgid "total free blocks %lld\n" msgstr "gesamte freie Blöcke %lld\n" #: .././db/freesp.c:112 #, c-format msgid "average free extent size %g\n" msgstr "durchschnittliche freie Extent-Größe %g\n" #: .././db/freesp.c:203 msgid "" "freesp arguments: [-bcds] [-a agno] [-e binsize] [-h h1]... [-m binmult]\n" msgstr "" "freesp-Argumente: [-bcds] [-a agno] [-e binsize] [-h h1]... [-m binmult]\n" #: .././db/freesp.c:427 msgid "from" msgstr "von" #: .././db/freesp.c:427 msgid "to" msgstr "bis" #: .././db/freesp.c:427 .././repair/progress.c:26 msgid "extents" msgstr "Extents" #: .././db/freesp.c:427 .././repair/progress.c:18 msgid "blocks" msgstr "Blöcke" #: .././db/freesp.c:427 msgid "pct" msgstr "pct" #: .././db/fsmap.c:39 #, c-format msgid "" "%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n" msgstr "" #: .././db/fsmap.c:86 #, c-format msgid "Error %d while reading AGF.\n" msgstr "" #: .././db/fsmap.c:93 #, fuzzy msgid "Not enough memory.\n" msgstr "%s: außerhalb des Speichers\n" #: .././db/fsmap.c:103 #, c-format msgid "Error %d while querying fsmap btree.\n" msgstr "" #: .././db/fsmap.c:127 msgid "Filesystem does not support reverse mapping btree.\n" msgstr "" #: .././db/fsmap.c:134 #, fuzzy msgid "Bad option for fsmap command.\n" msgstr "falsche Option für bmap-Befehl\n" #: .././db/fsmap.c:142 #, c-format msgid "Bad fsmap start_fsb %s.\n" msgstr "" #: .././db/fsmap.c:150 #, c-format msgid "Bad fsmap end_fsb %s.\n" msgstr "" #: .././db/fsmap.c:162 msgid "[start_fsb] [end_fsb]" msgstr "" #: .././db/fsmap.c:163 msgid "display reverse mapping(s)" msgstr "" #: .././db/hash.c:30 msgid "string" msgstr "Zeichenkette" #: .././db/hash.c:31 msgid "calculate hash value" msgstr "Hash-Wert berechnen" #: .././db/hash.c:37 msgid "" "\n" " 'hash' prints out the calculated hash value for a string using the\n" "directory/attribute code hash function.\n" "\n" " Usage: \"hash \"\n" "\n" msgstr "" "\n" "»hash« gibt den berechneten Hash-Wert für eine Zeichenkette unter\n" "Benutzung der Verzeichnis-/Code-Hash-Funktion aus .\n" "\n" "Aufruf: »hash «\n" "\n" #: .././db/help.c:30 .././db/io.c:49 .././libxcmd/help.c:93 msgid "[command]" msgstr "[Befehl]" #: .././db/help.c:31 .././libxcmd/help.c:94 msgid "help for one or all commands" msgstr "Hilfe für einen oder alle Befehle" #: .././db/help.c:40 .././libxcmd/help.c:34 #, c-format msgid "" "\n" "Use 'help commandname' for extended help.\n" msgstr "" "\n" "»help Befehlsname« benutzen, um erweitere Hilfe zu erhalten.\n" #: .././db/help.c:89 #, c-format msgid "(or %s) " msgstr "(oder %s) " #: .././db/init.c:49 #, fuzzy, c-format msgid "Usage: %s [-ifFrxV] [-p prog] [-l logdev] [-c cmd]... device\n" msgstr "Aufruf: %s [-fFrxV] [-p Programm] [-l logdev] [-c Befehl]... Gerät\n" #: .././db/init.c:116 msgid "" "\n" "fatal error -- couldn't initialize XFS library\n" msgstr "" "\n" "fataler Fehler -- XFS-Bibliothek kann nicht initialisiert werden\n" #: .././db/init.c:131 #, c-format msgid "%s: %s is invalid (cannot read first 512 bytes)\n" msgstr "" "%s: %s ist ungültig (die ersten 512 Bytes können nicht gelesen werden)\n" #: .././db/init.c:143 #, c-format msgid "" "%s: %s is not a valid XFS filesystem (unexpected SB magic number 0x%08x)\n" msgstr "" "%s: %s ist kein gültige XFS-Dateisystem (unerwartete SB Magische\n" "Nummer 0x%08x)\n" #: .././db/init.c:146 #, c-format msgid "Use -F to force a read attempt.\n" msgstr "" #: .././db/init.c:155 #, c-format msgid "%s: device %s unusable (not an XFS filesystem?)\n" msgstr "%s: Gerät %s unbenutzbar (kein XFS-Dateisystem?)\n" #: .././db/init.c:170 #, fuzzy, c-format msgid "%s: cannot init perag data (%d). Continuing anyway.\n" msgstr "%s: perag-Daten (%d) konnten nicht initialisiert werden\n" #: .././db/inode.c:419 #, c-format msgid "bad value for inode number %s\n" msgstr "falscher Wert für Inode-Nummer %s\n" #: .././db/inode.c:426 #, c-format msgid "current inode number is %lld\n" msgstr "aktuelle Inode-Nummer ist %lld\n" #: .././db/inode.c:660 #, c-format msgid "bad inode number %lld\n" msgstr "falsche Inode-Nummer %lld\n" #: .././db/inode.c:707 #, fuzzy, c-format msgid "Metadata CRC error detected for ino %lld\n" msgstr "falsche Anzahl von Ausweitungen %d für Inode %lld\n" #: .././db/input.c:43 msgid "source-file" msgstr "Quelldatei" #: .././db/input.c:44 msgid "get commands from source-file" msgstr "Befehle aus Quelldatei beziehen" #: .././db/input.c:320 #, c-format msgid "can't open %s\n" msgstr "%s kann nicht geöffnet werden\n" #: .././db/io.c:47 msgid "pop location from the stack" msgstr "Ort vom Stack hervorholen" #: .././db/io.c:50 msgid "push location to the stack" msgstr "Ort auf den Stack bewegen" #: .././db/io.c:53 msgid "view the location stack" msgstr "den Stack-Ort ansehen" #: .././db/io.c:56 msgid "move forward to next entry in the position ring" msgstr "vorwärts zum nächsten Eintrag im Positionsring bewegen" #: .././db/io.c:59 msgid "move to the previous location in the position ring" msgstr "zum vorherigen Ort im Positionsring bewegen" #: .././db/io.c:62 msgid "show position ring or move to a specific entry" msgstr "Positionsring anzeigen oder zu einem bestimmten Eintrag bewegen" #: .././db/io.c:92 #, c-format msgid "can't set block offset to %d\n" msgstr "Blockversatz kann nicht auf %d gesetzt werden\n" #: .././db/io.c:105 msgid "can't pop anything from I/O stack\n" msgstr "vom I/O-Stack kann nichts hervorgeholt werden\n" #: .././db/io.c:139 msgid "" "\n" " Changes the address and data type to the first entry on the stack.\n" "\n" msgstr "" "\n" " Ändert die Adresse und den Datentyp auf den ersten Eintrag auf dem\n" " Stack.\n" "\n" #: .././db/io.c:153 #, c-format msgid "\tbyte offset %lld, length %d\n" msgstr "\tByte Versatz %lld, Länge %d\n" #: .././db/io.c:154 #, c-format msgid "\tbuffer block %lld (fsbno %lld), %d bb%s\n" msgstr "\tPufferblock %lld (fsbno %lld), %d bb%s\n" #: .././db/io.c:158 .././db/io.c:544 #, c-format msgid "\tblock map" msgstr "\tBlockekarte" #: .././db/io.c:164 #, c-format msgid "\tinode %lld, dir inode %lld, type %s\n" msgstr "\tInode %lld, dir Inode %lld, Typ %s\n" #: .././db/io.c:165 .././growfs/xfs_growfs.c:88 .././logprint/log_misc.c:107 #: .././mkfs/xfs_mkfs.c:2366 #, c-format msgid "none" msgstr "keine" #: .././db/io.c:175 msgid "no entries in location ring.\n" msgstr "keine Einträge im Positionsring.\n" #: .././db/io.c:179 msgid " type bblock bblen fsbno inode\n" msgstr " Typ bblock bblen fsbno Inode\n" #: .././db/io.c:233 #, c-format msgid "no such command %s\n" msgstr "kein solcher Befehl -- %s\n" #: .././db/io.c:237 #, c-format msgid "no push form allowed for %s\n" msgstr "keine Verschiebeform für %s erlaubt\n" #: .././db/io.c:261 msgid "" "\n" " Allows you to push the current address and data type on the stack for\n" " later return. 'push' also accepts an additional command to execute after\n" " storing the current address (ex: 'push a rootino' from the superblock).\n" "\n" msgstr "" "\n" " Erlaubt Ihnen die aktuelle Adresse und den Datentyp für eine spätere\n" " Rückgabe auf den Stack zu verschieben. »push« akzeptiert außerdem die\n" " Ausführung eines zusätzlichen Befehls nach dem Speichern der aktuellen\n" " Adresse (z.B.: »push a rootino« von einem Superblock).\n" "\n" #: .././db/io.c:277 .././db/io.c:317 msgid "ring is empty\n" msgstr "Ring ist leer\n" #: .././db/io.c:281 msgid "no further entries\n" msgstr "keine weiteren Einträge\n" #: .././db/io.c:300 msgid "" "\n" " The 'forward' ('f') command moves to the next location in the position\n" " ring, updating the current position and data type. If the current " "location\n" " is the top entry in the ring, then the 'forward' command will have\n" " no effect.\n" "\n" msgstr "" "\n" " Der »forward«-Befehl (»f«) bewegt zum nächsten Ort im Positionsring und\n" " aktualisiert dabei die aktuelle Position und den Datentyp. Wenn der\n" " aktuelle Ort der oberste Eintrag im Ring ist, dann hat der\n" " »forward«-Befehl keine Auswirkung.\n" "\n" #: .././db/io.c:321 msgid "no previous entries\n" msgstr "keine vorherigen Einträge\n" #: .././db/io.c:340 msgid "" "\n" " The 'back' ('b') command moves to the previous location in the position\n" " ring, updating the current position and data type. If the current " "location\n" " is the last entry in the ring, then the 'back' command will have no " "effect.\n" "\n" msgstr "" "\n" " Der »back«-Befehl (»b«) bewegt zum vorherigen Ort im Positionsring und\n" " aktualisiert dabei die aktuelle Position und den Datentyp. Wenn der\n" " aktuelle Ort der letzte Eintrag im Ring ist, dann hat der\n" "»forward«-Befehl keine Auswirkung.\n" "\n" #: .././db/io.c:363 #, c-format msgid "invalid entry: %d\n" msgstr "ungültiger Eintrag: %d\n" #: .././db/io.c:382 #, c-format msgid "" "\n" " The position ring automatically keeps track of each disk location and\n" " structure type for each change of position you make during your xfs_db\n" " session. The last %d most recent entries are kept in the ring.\n" "\n" " To display the current list of ring entries type 'ring' by itself on\n" " the command line. The entry highlighted by an asterisk ('*') is the\n" " current entry.\n" "\n" " To move to another entry in the ring type 'ring ' where is\n" " your desired entry from the ring position list.\n" "\n" " You may also use the 'forward' ('f') or 'back' ('b') commands to move\n" " to the previous or next entry in the ring, respectively.\n" "\n" " Note: Unlike the 'stack', 'push' and 'pop' commands, the ring tracks your\n" " location implicitly. Use the 'push' and 'pop' commands if you wish to\n" " store a specific location explicitly for later return.\n" "\n" msgstr "" "\n" " Der Positionsring verfolgt automatisch jeden Plattenort und -Strukturtyp\n" " von jeder Positionsänderung, die Sie während einer xfs_db-Sitzung\n" " vornehmen. Die aktuellsten %d Einträge werden im Ring behalten.\n" "\n" " Um die aktuelle Liste der Ringeinträge anzuzeigen tippen Sie\n" " selbstständig »ring« auf der Befehlszeile ein. Der von einem Stern (»*«)\n" " hervorgehobene Eintrag ist der aktuelle Eintrag.\n" "\n" " Um sich zu einem anderen Eintrag im Ring zu bewegen, tippen Sie\n" " »Ring « wobei Ihr gewümschter Eintrag von der\n" " Ringpositionsliste ist.\n" "\n" " Sie könnten außerdem die »forward«- (»f«) oder »back« (»b«) -Befehle\n" " benutzen, um sich zum vorherigen beziehungsweise nächsten Eintrag im Ring\n" " zu bewegen.\n" "\n" " Anmerkung: Anders als bei den »stack«-, »push«- und »pop«-Befehlen,\n" " verfolgt der Ring vorbehaltlos ihrem Ort. Benutzen Sie die »push«- und\n" " »pop«-Befehle, wenn Sie einen bestimmten Ort für eine spätere Rückkehr\n" " ausdrücklich speichern möchten.\n" "\n" #: .././db/io.c:435 .././db/io.c:451 #, c-format msgid "write error: %s\n" msgstr "Schreibfehler: %s\n" #: .././db/io.c:441 .././db/io.c:457 #, c-format msgid "read error: %s\n" msgstr "Lesefehler: %s\n" #: .././db/io.c:480 msgid "nothing to write\n" msgstr "nichts zu schreiben\n" #: .././db/io.c:529 msgid "set_cur no stack element to set\n" msgstr "set_cur kein Stack-Element zu setzen\n" #: .././db/io.c:543 #, c-format msgid "xfs_db got a bbmap for %lld\n" msgstr "xfs_db hat eine bbmap für %lld\n" #: .././db/io.c:619 msgid "" "\n" " The stack is used to explicitly store your location and data type\n" " for later return. The 'push' operation stores the current address\n" " and type on the stack, the 'pop' operation returns you to the\n" " position and datatype of the top entry on the stack.\n" "\n" " The 'stack' allows explicit location saves, see 'ring' for implicit\n" " position tracking.\n" "\n" msgstr "" "\n" " Der Stack wird benutzt, um Ihren Ort und Datentyp explizit für eine\n" " spätere Rückgabe zu speichern. Die »push«-Operation speichert die\n" " aktuelle Adresse und den Typ auf dem Stack, die»pop«-Operation gibt\n" " Ihnen die Position und den Datentyp des obersten Eintrags auf dem Stack\n" " zurück.\n" "\n" " Der »Stack« erlaubt explizite Ortsspeicherungen. Sehen Sie »ring« für\n" " ausdrückliche Psoitionsvefolgung.\n" "\n" #: .././db/logformat.c:89 msgid "The log is dirty. Please mount to replay the log.\n" msgstr "" #: .././db/logformat.c:121 msgid "" "\n" " The 'logformat' command reformats (clears) the log to the specified log\n" " cycle and log stripe unit. If the log cycle is not specified, the log is\n" " reformatted to the current cycle. If the log stripe unit is not specified,\n" " the stripe unit from the filesystem superblock is used.\n" "\n" msgstr "" #: .././db/logformat.c:137 msgid "[-c cycle] [-s sunit]" msgstr "" #: .././db/logformat.c:138 msgid "reformat the log" msgstr "" #: .././db/malloc.c:27 #, c-format msgid "%s: out of memory\n" msgstr "%s: außerhalb des Speichers\n" #: .././db/metadump.c:60 #, fuzzy msgid "[-a] [-e] [-g] [-m max_extent] [-w] [-o] filename" msgstr "[-e] [-g] [-m max_extent] [-w] [-o] Dateiname" #: .././db/metadump.c:61 msgid "dump metadata to a file" msgstr "Metadatenauszug in eine Datei" #: .././db/metadump.c:92 #, fuzzy, c-format msgid "" "\n" " The 'metadump' command dumps the known metadata to a compact file suitable\n" " for compressing and sending to an XFS maintainer for corruption analysis \n" " or xfs_repair failures.\n" "\n" " Options:\n" " -a -- Copy full metadata blocks without zeroing unused space\n" " -e -- Ignore read errors and keep going\n" " -g -- Display dump progress\n" " -m -- Specify max extent size in blocks to copy (default = %d blocks)\n" " -o -- Don't obfuscate names and extended attributes\n" " -w -- Show warnings of bad metadata information\n" "\n" msgstr "" "\n" " Der »Metadaten«-Befehl macht einen Auszug der bekannten Metadaten in eine\n" " kompakte Datei, die geeignet ist, um komprimiert und an einen\n" " XFS-Betreuer zur Beschädigungsanalyse oder xfs_repair-Ausfälle gesendet\n" " zu werden.\n" "\n" " Optionen:\n" " -e -- Lesefehler ignorieren und am Laufen halten\n" " -g -- Auszugsfortschritt anzeigen\n" " -m -- Maximale Extent-Größe in Blocks zum Kopieren angeben\n" " (Vorgabe = %d Blöcke)\n" " -o -- Namen und erweiterte Attribute nicht verschleiern\n" " -w -- Warnungen von flaschen Metadateninformationen anzeigen\n" "\n" #: .././db/metadump.c:2728 msgid "" "Filesystem log is dirty; image will contain unobfuscated metadata in log." msgstr "" #: .././db/metadump.c:2734 msgid "Could not discern log; image will contain unobfuscated metadata in log." msgstr "" #: .././db/output.c:30 msgid "[stop|start ]" msgstr "[stop|start ]" #: .././db/output.c:31 msgid "start or stop logging to a file" msgstr "Protokollieren in eine Datei starten oder stoppen" #: .././db/output.c:68 #, c-format msgid "logging to %s\n" msgstr "Protokollieren nach %s\n" #: .././db/output.c:70 .././db/output.c:77 msgid "no log file\n" msgstr "kein Protokolldatei\n" #: .././db/output.c:80 #, c-format msgid "already logging to %s\n" msgstr "es wird bereits nach %s protokolliet\n" #: .././db/output.c:84 #, c-format msgid "can't open %s for writing\n" msgstr "%s kann nicht zum Schreiben geöffnet werden\n" #: .././db/output.c:90 msgid "bad log command, ignored\n" msgstr "falscher Protokollbefehl, ignoriert\n" #: .././db/print.c:41 msgid "[value]..." msgstr "[Wert] ..." #: .././db/print.c:42 msgid "print field values" msgstr "Feldwerte ausgeben" #: .././db/print.c:79 #, c-format msgid "no print function for type %s\n" msgstr "keine Ausgabefunktion für Typ %s\n" #: .././db/print.c:156 msgid "(empty)\n" msgstr "(leer)\n" #: .././db/print.c:218 msgid "(empty)" msgstr "(leer)" #: .././db/print.c:278 msgid "no arguments allowed\n" msgstr "keine Argumente erlaubt\n" #: .././db/quit.c:27 msgid "exit xfs_db" msgstr "xfs_db beenden" #: .././db/sb.c:45 msgid "set current address to sb header" msgstr "aktuelle Adresse auf sb-Kopfzeilen setzen" #: .././db/sb.c:47 msgid "[uuid]" msgstr "[uuid]" #: .././db/sb.c:48 msgid "write/print FS uuid" msgstr "FS uuid schreiben/ausgeben" #: .././db/sb.c:50 msgid "[label]" msgstr "[Etikett]" #: .././db/sb.c:51 msgid "write/print FS label" msgstr "FS-Etikett schreiben/ausgeben" #: .././db/sb.c:53 msgid "[feature | [vnum fnum]]" msgstr "[feature | [vnum fnum]]" #: .././db/sb.c:54 msgid "set feature bit(s) in the sb version field" msgstr "Merkmal-Bit(s) im sb-Versionsfeld setzen" #: .././db/sb.c:140 msgid "" "\n" " set allocation group superblock\n" "\n" " Example:\n" "\n" " 'sb 7' - set location to 7th allocation group superblock, set type to 'sb'\n" "\n" " Located in the first sector of each allocation group, the superblock\n" " contains the base information for the filesystem.\n" " The superblock in allocation group 0 is the primary. The copies in the\n" " remaining allocation groups only serve as backup for filesystem recovery.\n" " The icount/ifree/fdblocks/frextents are only updated in superblock 0.\n" "\n" msgstr "" "\n" " Zuweisungsgruppen-Superblock setzen\n" "\n" "\n" " Beispiel:\n" "\n" " 'sb 7' - setzt Ort auf den 7. Zuweisungsgruppen-Superblock, setzt Typ auf\n" " »sb«\n" "\n" " Im ersten Abschnitt jeder Zuweisungsgruppe gelegen, enthält der\n" " Superblock die Basisinformationen des Dateisystems.\n" " Der Superblock in Zuweisungsgruppe 0 ist der Primäre. Die Kopien in den\n" " verbleibenden Zuweisungsgruppen dienen nur als Sicherung zur\n" " Wiederherstellung des Dateisystems. Die icount/ifree/fdblocks/frextents\n" " werden nur im Superblock 0 aktualisiert.\n" "\n" #: .././db/sb.c:199 #, c-format msgid "can't read superblock for AG %u\n" msgstr "Superblock für AG %u kann nicht gelesen werden\n" #: .././db/sb.c:207 #, c-format msgid "bad sb magic # %#x in AG %u\n" msgstr "falsche magische sb # %#x in AG %u\n" #: .././db/sb.c:212 #, c-format msgid "bad sb version # %#x in AG %u\n" msgstr "falsche sb-Version # %#x in AG %u\n" #: .././db/sb.c:236 msgid "aborting - external log specified for FS with an internal log\n" msgstr "" "Abbruch - externes Protokoll für FS mit einem internen Protokoll angegeben\n" #: .././db/sb.c:242 msgid "aborting - no external log specified for FS with an external log\n" msgstr "" "Abbruch - kein externes Protokoll für FS mit einem externen Protokoll\n" "angegeben\n" #: .././db/sb.c:252 msgid "ERROR: cannot find log head/tail, run xfs_repair\n" msgstr "" "FEHLER: Protokoll head/tail wurde nicht gefunden, führen Sie xfs_repair\n" "aus\n" #: .././db/sb.c:256 #, c-format msgid "" "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running %s. If you are unable to mount the filesystem, then use\n" "the xfs_repair -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n" msgstr "" "FEHLER: Das Dateisystem hat wertvolle Metadaten-Änderungen in einem\n" "Protokoll, das wiederholt werden sollte. Hängen Sie das Dateisystem ein,\n" "um das Protokoll zu wiederholen und hängen Sie es wieder aus before Sie\n" "%s erneut auszuführen. Wenn Sie außer Stande sind, das Dateisystem\n" "einzuhängen, benutzen Sie die xfs_repair-Option -L, um das Protokoll zu\n" "zerstören und versuchen Sie eine Reparatur.\n" "Beachten Sie, dass die Zerstörung des Protokolls Schaden verursachen\n" "kann -- bitte versuchen Sie, das Dateisystem einzuhängen ehe Sie dies tun.\n" #: .././db/sb.c:284 msgid "Clearing log and setting UUID\n" msgstr "Protokoll wird geleert und UUID gesetzt\n" #: .././db/sb.c:293 msgid "ERROR: cannot clear the log\n" msgstr "FEHLER: Protokoll kann nicht geleert werden\n" #: .././db/sb.c:305 msgid "" "\n" " write/print FS uuid\n" "\n" " Example:\n" "\n" " 'uuid' - print UUID\n" " 'uuid 01234567-0123-0123-0123-0123456789ab' - write UUID\n" " 'uuid generate' - generate and write\n" " 'uuid rewrite' - copy UUID from SB 0\n" "\n" "The print function checks the UUID in each SB and will warn if the UUIDs\n" "differ between AGs (the log is not checked). The write commands will\n" "set the uuid in all AGs to either a specified value, a newly generated\n" "value or the value found in the first superblock (SB 0) respectively.\n" "As a side effect of writing the UUID, the log is cleared (which is fine\n" "on a CLEANLY unmounted FS).\n" "\n" msgstr "" "\n" " FS-uuid schreiben/ausgeben\n" "\n" " Beispiel:\n" "\n" " 'uuid' - gibt UUID aus\n" " 'uuid 01234567-0123-0123-0123-0123456789ab' - schreibt UUID\n" " 'uuid generate' - generiert und schreibt\n" " 'uuid rewrite' - kopiert UUID von SB 0\n" "\n" "Die Ausgabefunktion prüft die UUID in jedem SB und wird warnen, wenn die\n" "UUIDs sich zwischen AGs unterscheiden (das Protokoll ist nicht geprüft).\n" "Die Schreibbefehle werden die UUIDs in allen AGs entweder auf einen\n" "angegebenen Wert, einen neu generierten Wert beziehungsweise den im ersten\n" "Superblock (SB 0) gefundenen Wert setzen. Als ein Nebeneffekt des\n" "Schreibens der UUID wird das Protokoll geleert (was bei einem ORDENTLICH\n" "ausgehängten FS fein ist).\n" "\n" #: .././db/sb.c:383 .././db/sb.c:546 msgid "invalid parameters\n" msgstr "ungültige Parameter\n" #: .././db/sb.c:390 .././db/sb.c:553 .././db/sb.c:720 #, c-format msgid "%s: not in expert mode, writing disabled\n" msgstr "%s: Nicht im Expertenmodus, schreiben ausgeschaltet\n" #: .././db/sb.c:402 msgid "failed to read UUID from AG 0\n" msgstr "Lesen der UUID von AG 0 fehlgeschlagen\n" #: .././db/sb.c:407 #, c-format msgid "old UUID = %s\n" msgstr "alte UUID = %s\n" #: .././db/sb.c:421 msgid "invalid UUID\n" msgstr "ungültige UUID\n" #: .././db/sb.c:430 .././db/sb.c:558 .././db/sb.c:806 msgid "writing all SBs\n" msgstr "Schreiben aller SBs\n" #: .././db/sb.c:433 #, c-format msgid "failed to set UUID in AG %d\n" msgstr "UUID in AG %d zu setzen fehlgeschlagen\n" #: .././db/sb.c:438 #, c-format msgid "new UUID = %s\n" msgstr "neue UUID = %s\n" #: .././db/sb.c:446 #, c-format msgid "failed to read UUID from AG %d\n" msgstr "Lesen der UUID von AG %d fehlgeschlagen\n" #: .././db/sb.c:452 #, c-format msgid "warning: UUID in AG %d differs to the primary SB\n" msgstr "Warnung:UUID in AG %d unterscheidet sich vom primären SB\n" #: .././db/sb.c:463 msgid "warning - external log specified for FS with an internal log\n" msgstr "" "Warnung - externes Protokoll für FS mit einem internen Protokoll angegeben\n" #: .././db/sb.c:466 msgid "warning - no external log specified for FS with an external log\n" msgstr "" "Warnung - kein externes Protokoll für FS mit einem externen Protokoll\n" "angegeben\n" #: .././db/sb.c:471 #, c-format msgid "UUID = %s\n" msgstr "UUID = %s\n" #: .././db/sb.c:482 msgid "" "\n" " write/print FS label\n" "\n" " Example:\n" "\n" " 'label' - print label\n" " 'label 123456789012' - write label\n" " 'label --' - write an empty label\n" "\n" "The print function checks the label in each SB and will warn if the labels\n" "differ between AGs. The write commands will set the label in all AGs to the\n" "specified value. The maximum length of a label is 12 characters - use of a\n" "longer label will result in truncation and a warning will be issued.\n" "\n" msgstr "" "\n" " FS-Etikett schreiben/ausgeben\n" "\n" " Beispiel:\n" "\n" " 'label' - Etikett ausgeben\n" " 'label 123456789012' - Etikett schreiben\n" " 'label --' - ein leeres Etikett schreiben\n" "\n" "Die Ausgabefunktion prüft das Etikett in jedem SB und wird warnen, wenn\n" "sich die Etiketten zwischen AGs unterscheiden. Die Schreibbefehlewerden\n" "Etiketten in allen AGs auf den angegebenen Wert setzen. Die maximale\n" "Länge eine Etiketts ist zwölf Zeichen - Benutzen eines längeren Etiketts\n" "führt zu Kürzung und eine Warnung wird ausgegeben.\n" "\n" #: .././db/sb.c:519 #, c-format msgid "%s: truncating label length from %d to %d\n" msgstr "%s: Etikettlänge von %d auf %d kürzen\n" #: .././db/sb.c:561 #, c-format msgid "failed to set label in AG %d\n" msgstr "Setzen von Etikett in AG %d fehlgeschlagen\n" #: .././db/sb.c:564 #, c-format msgid "new label = \"%s\"\n" msgstr "neues Etikett = »%s«\n" #: .././db/sb.c:571 #, c-format msgid "failed to read label in AG %d\n" msgstr "Lesen von Etikett in AG %d fehlgeschlagen\n" #: .././db/sb.c:577 #, c-format msgid "warning: AG %d label differs\n" msgstr "Warnung: AG %d Etikett unterschiedlich\n" #: .././db/sb.c:579 #, c-format msgid "label = \"%s\"\n" msgstr "Etikett = »%s«\n" #: .././db/sb.c:589 msgid "" "\n" " set/print feature bits in sb version\n" "\n" " Example:\n" "\n" " 'version' - print current feature bits\n" " 'version extflg' - enable unwritten extents\n" " 'version attr1' - enable v1 inline extended attributes\n" " 'version attr2' - enable v2 inline extended attributes\n" " 'version log2' - enable v2 log format\n" "\n" "The version function prints currently enabled features for a filesystem\n" "according to the version field of its primary superblock.\n" "It can also be used to enable selected features, such as support for\n" "unwritten extents. The updated version is written into all AGs.\n" "\n" msgstr "" "\n" " setzen/ausgeben von Merkmal-Bits in sb-Version\n" "\n" " »version« - gibt aktuelle Merkmal-Bis aus\n" " »version extflg« - ungeschriebene Extents einschalten\n" " »version attr1« - v1 erweiterte Inline-Attribute einschalten\n" " »version attr2« - v2 erweiterte Inline-Attribute einschalten\n" " »version log2« - v2 Protokolformat einschalten\n" "\n" "Die Versionsfunktion gibt aktuell eingeschaltete Merkmale für ein\n" "Dateisystem aus, entsprechende dem Versionsfeld seines primären\n" "Superblocks. Es kann außerdem benutzt werden, um ausgewählte Merkmale\n" "einzuschalten, wie etwa Unterstützung für ungeschriebene Bereiche. Die\n" "aktualisierte Version wird in alle AGs geschrieben.\n" "\n" #: .././db/sb.c:617 #, fuzzy msgid "Superblock has mismatched features2 fields, skipping modification\n" msgstr "" "Superblock hat eine fehlende features2-Übereinstimmung, wird berichtigt\n" #: .././db/sb.c:740 msgid "unwritten extents flag is already enabled\n" msgstr "Merkaml für ungeschriebene Bereiche ist bereits eingeschaltet\n" #: .././db/sb.c:747 #, fuzzy msgid "unwritten extents always enabled for v5 superblocks.\n" msgstr "Merkaml für ungeschriebene Bereiche ist bereits eingeschaltet\n" #: .././db/sb.c:764 msgid "version 2 log format is already in use\n" msgstr "Protokollformat der Version 2 wird bereits benutzt\n" #: .././db/sb.c:771 msgid "Version 2 logs always enabled for v5 superblocks.\n" msgstr "" #: .././db/sb.c:776 #, c-format msgid "%s: Cannot change %s on v5 superblocks.\n" msgstr "" #: .././db/sb.c:800 #, c-format msgid "%s: invalid version change command \"%s\"\n" msgstr "%s: ungültiger Versionswechselbefehl »%s«\n" #: .././db/sb.c:809 #, c-format msgid "failed to set versionnum in AG %d\n" msgstr "Versionsnummer in AG %d zu setzen fehlgeschlagen\n" #: .././db/sb.c:827 #, c-format msgid "versionnum [0x%x+0x%x] = %s\n" msgstr "versionnum [0x%x+0x%x] = %s\n" #: .././db/type.c:49 msgid "[newtype]" msgstr "[newtype]" #: .././db/type.c:50 msgid "set/show current data type" msgstr "aktuellen Datentyp setzen/anzeigen" #: .././db/type.c:210 #, c-format msgid "current type is \"%s\"\n" msgstr "aktueller Typ ist »%s«\n" #: .././db/type.c:212 msgid "" "\n" " supported types are:\n" " " msgstr "" "\n" " unterstützte Typen sind:\n" " " #: .././db/type.c:229 #, c-format msgid "no such type %s\n" msgstr "kein solcher Typ %s\n" #: .././db/type.c:232 msgid "no current object\n" msgstr "kein aktuelles Objekt\n" #: .././db/write.c:41 #, fuzzy msgid "[-c] [field or value]..." msgstr "[Feld oder Wert] ..." #: .././db/write.c:42 msgid "write value to disk" msgstr "Wert auf Platte schreiben" #: .././db/write.c:58 #, fuzzy msgid "" "\n" " The 'write' command takes on different personalities depending on the\n" " type of object being worked with.\n" "\n" " Write has 3 modes:\n" " 'struct mode' - is active anytime you're looking at a filesystem object\n" " which contains individual fields (ex: an inode).\n" " 'data mode' - is active anytime you set a disk address directly or set\n" " the type to 'data'.\n" " 'string mode' - only used for writing symlink blocks.\n" "\n" " Examples:\n" " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n" " 'write fname \"hello\\000\"' - write superblock fname.\n" " (note: in struct mode strings are not null terminated)\n" " 'write fname #6669736800' - write superblock fname with " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - write superblock uuid.\n" " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n" " 'write lshift 3' - shift the block 3 bytes to the left\n" " 'write sequence 1 5' - write a cycle of number [1-5] through\n" " the entire block.\n" " String mode: 'write \"This_is_a_filename\" - write null terminated " "string.\n" "\n" " In data mode type 'write' by itself for a list of specific commands.\n" "\n" " Specifying the -c option will allow writes of invalid (corrupt) data with\n" " an invalid CRC. Specifying the -d option will allow writes of invalid " "data,\n" " but still recalculate the CRC so we are forced to check and detect the\n" " invalid data appropriately.\n" "\n" msgstr "" "\n" " Der »write«-Befehl nimmt abhängig vom Typ des Objekts, mit dem gearbeitet\n" " wird, unterschiedliche Persönlichkeiten an.\n" "\n" " Write hat drei Modi:\n" " »Strukturmodus« - ist jederzeit aktiv, wenn Sie ein\n" " Dateisystemobjekt ansehen, das individuelle\n" " Felder enthält (z.B.: Einen Inode.\n" " »Datenmodus« - ist jederzeit aktiv, wenn Sie eine Plattenadresse\n" " direkt setzen oder den Typ auf »data« setzen.\n" " »Zeichenkettenmodus« - nur benutzt, um symbolische Verweisblöcke zu\n" " schreiben.\n" "\n" " Beispiele:\n" " Strukturmodus: »write core.uid 23« - setzt eine Inode-uid-Feld\n" " auf 23.\n" " »write fname \"hello\\000\"«\n" " - schreibt Superblock fname.\n" " (Anmerkung: Zeichenketten werden in »struct mode« " "nicht\n" " mit Null beendet)\n" " »write fname #6669736800«\n" " - schreibt Superblock fname\n" " hexadezimal.\n" " »write uuid 00112233-4455-6677-8899-aabbccddeeff«\n" " - schreibt Superblock-uuid.\n" " Datenmodus: »write fill 0xff« - füllt den ganzen Block mit\n" " 0xffs\n" " »write lshift 3« - verschiebt den Block drei\n" " Bytes nach links\n" " »write sequence 1 5« - schreibt einen Zyklus von\n" " Nummern [1-5] durch den\n" " ganzen Block\n" " Zeichenkettenmodus: »write \"This_is_a_filename\"«\n" " - schreibt mit Null beendete\n" " Zeichenkette\n" "\n" " Tippen Sie im Datenmodus »write« ein, um eine Liste spezieller Befehle zu\n" " erhalten.\n" "\n" #: .././db/write.c:104 #, c-format msgid "%s started in read only mode, writing disabled\n" msgstr "%s im Nur-Lese-Modus gestartet, Schreiben ausgeschaltet\n" #: .././db/write.c:116 #, c-format msgid "no handler function for type %s, write unsupported.\n" msgstr "" "keine Funktion zum Behandeln von Typ %s, Schreiben nicht unterstützt.\n" #: .././db/write.c:130 #, fuzzy msgid "bad option for write command\n" msgstr "falsche Opzion für frag-Befehl\n" #: .././db/write.c:136 #, fuzzy msgid "Cannot specify both -c and -d options\n" msgstr "Beides kann nicht angegeben werden -%c %s und -%c %s\n" #: .././db/write.c:141 msgid "Cannot recalculate CRCs on this type of object\n" msgstr "" #: .././db/write.c:166 msgid "Allowing write of corrupted data and bad CRC\n" msgstr "" #: .././db/write.c:169 msgid "Allowing write of corrupted data with good CRC\n" msgstr "" #: .././db/write.c:225 .././db/write.c:254 .././db/write.c:284 #: .././db/write.c:317 .././db/write.c:353 .././db/write.c:402 #: .././db/write.c:431 #, c-format msgid "length (%d) too large for data block size (%d)" msgstr "Länge (%d) zu groß für Datenblockgröße (%d)" #: .././db/write.c:673 msgid "usage: write fieldname value\n" msgstr "Aufruf: write Feldname Wert\n" #: .././db/write.c:679 #, c-format msgid "unable to parse '%s'.\n" msgstr "»%s« kann nicht ausgewertet werden.\n" #: .././db/write.c:728 #, c-format msgid "unable to convert value '%s'.\n" msgstr "Wert »%s« kann nicht konvertiert werden.\n" #: .././db/write.c:752 msgid "usage (in string mode): write \"string...\"\n" msgstr "Aufruf (im Zeichenkettenmodus): write »Zeichenkette ...«\n" #: .././db/write.c:794 msgid "write: invalid subcommand\n" msgstr "write: ungültiger Unterbefehl\n" #: .././db/write.c:799 #, c-format msgid "write %s: invalid number of arguments\n" msgstr "write %s: ungültige Anzahl von Argumenten\n" #: .././db/write.c:823 msgid "usage: write (in data mode)\n" msgstr "Aufruf: write (im Datenmodus)\n" #: .././estimate/xfs_estimate.c:78 #, fuzzy, c-format msgid "" "Usage: %s [opts] directory [directory ...]\n" "\t-b blocksize (fundamental filesystem blocksize)\n" "\t-i logsize (internal log size)\n" "\t-e logsize (external log size)\n" "\t-v prints more verbose messages\n" "\t-V prints version and exits\n" "\t-h prints this usage message\n" "\n" "Note:\tblocksize may have 'k' appended to indicate x1024\n" "\tlogsize may also have 'm' appended to indicate (1024 x 1024)\n" msgstr "" "Aufruf: %s [Optionen] Verzeichnis [Verzeichnis ...]\n" "\t-b Blockgröße (grundlegende Dateisystemblockgröße)\n" "\t-i Protokollgröße (interne Protokollgröße)\n" "\t-e Protokollgröße (externe Protokollgröße)\n" "\t-v gibt detailliertere Nachrichten aus\n" "\t-h gibt diese Aufrufnachricht aus\n" "\n" #: .././estimate/xfs_estimate.c:109 #, c-format msgid "blocksize %llu too small\n" msgstr "Blockgröße %llu zu klein\n" #: .././estimate/xfs_estimate.c:114 #, c-format msgid "blocksize %llu too large\n" msgstr "Blockgröße %llu zu groß\n" #: .././estimate/xfs_estimate.c:121 #, c-format msgid "already have external log noted, can't have both\n" msgstr "externes Protokoll wurde bereits notiert, beide nicht möglich\n" #: .././estimate/xfs_estimate.c:130 #, c-format msgid "already have internal log noted, can't have both\n" msgstr "internes Protokoll wurde bereits notiert, beide nicht möglich\n" #: .././estimate/xfs_estimate.c:160 #, c-format msgid "" "directory bsize blocks megabytes " "logsize\n" msgstr "" "Verzeichnis bsize Blöcke Megabytes " "Protokollgröße\n" #: .././estimate/xfs_estimate.c:174 #, c-format msgid "dirsize=%llu\n" msgstr "dirsize=%llu\n" #: .././estimate/xfs_estimate.c:175 #, c-format msgid "fullblocks=%llu\n" msgstr "fullblocks=%llu\n" #: .././estimate/xfs_estimate.c:176 #, c-format msgid "isize=%llu\n" msgstr "isize=%llu\n" #: .././estimate/xfs_estimate.c:178 #, c-format msgid "%llu regular files\n" msgstr "%llu reguläre Dateien\n" #: .././estimate/xfs_estimate.c:179 #, c-format msgid "%llu symbolic links\n" msgstr "%llu symbolische Verweise\n" #: .././estimate/xfs_estimate.c:180 #, c-format msgid "%llu directories\n" msgstr "%llu Verzeichnisse\n" #: .././estimate/xfs_estimate.c:181 #, c-format msgid "%llu special files\n" msgstr "%llu Spezialdateien\n" #: .././estimate/xfs_estimate.c:194 #, c-format msgid "%s will take about %.1f megabytes\n" msgstr "%s wird etwa %.lf Megabytes einnehmen\n" #: .././estimate/xfs_estimate.c:201 #, c-format msgid "%-39s %5llu %8llu %10.1fMB %10llu\n" msgstr "%-39s %5llu %8llu %10.1fMB %10llu\n" #: .././estimate/xfs_estimate.c:207 #, c-format msgid "\twith the external log using %llu blocks " msgstr "\tmit dem externen Protokoll belegt %llu Blöcke " #: .././estimate/xfs_estimate.c:209 #, c-format msgid "or about %.1f megabytes\n" msgstr "oder über %.1f Megabytes\n" #: .././fsr/xfs_fsr.c:268 #, c-format msgid "%s: Stats not yet supported for XFS\n" msgstr "%s: Status noch nicht für XFS unterstützt\n" #: .././fsr/xfs_fsr.c:332 #, c-format msgid "%s: could not stat: %s: %s\n" msgstr "%s: kann Status für »%s« nicht abfragen: %s\n" #: .././fsr/xfs_fsr.c:351 #, c-format msgid "%s: char special not supported: %s\n" msgstr "%s: Sonderzeichen nicht unterstützt: %s\n" #: .././fsr/xfs_fsr.c:357 #, c-format msgid "%s: cannot defragment: %s: Not XFS\n" msgstr "%s: kann nicht defragmentiert werden: %s: Kein XFS\n" #: .././fsr/xfs_fsr.c:367 #, c-format msgid "%s: not fsys dev, dir, or reg file, ignoring\n" msgstr "%s: nicht fsys dev, dir oder reg-Datei, wird ignoriert\n" #: .././fsr/xfs_fsr.c:382 #, fuzzy, c-format msgid "" "Usage: %s [-d] [-v] [-g] [-t time] [-p passes] [-f leftf] [-m mtab]\n" " %s [-d] [-v] [-g] xfsdev | dir | file ...\n" " %s -V\n" "\n" "Options:\n" " -g Print to syslog (default if stdout not a tty).\n" " -t time How long to run in seconds.\n" " -p passes Number of passes before terminating global re-org.\n" " -f leftoff Use this instead of %s.\n" " -m mtab Use something other than /etc/mtab.\n" " -d Debug, print even more.\n" " -v Verbose, more -v's more verbose.\n" " -V Print version number and exit.\n" msgstr "" "Aufruf: %s [-d] [-v] [-n] [-s] [-g] [-t Zeit] [-p Durchläufe] [-f leftf] \n" " [-m mtab] %s [-d] [-v] [-n] [-s] [-g] xfsdev | Verz. | Datei ...\n" "\n" "Optionen:\n" " -n Nichts tun, nur interessant mit -v. Im mtab-Modus\n" " nicht effektiv.\n" " -s\t\tNur Statistiken ausgeben.\n" " -g Ausgabe in's Syslog (Vorgabe, wenn stdout kein tty).\n" " -t Zeit Ausführdauer in Sekunden.\n" " -p Durchläufe Anzahl der Durchläufe vor Beenden der globalen\n" " Reorganisation.\n" " -f leftoff Benutzen Sie dies anstelle von %s.\n" " -m mtab Etwas anderes als /etc/mtab benutzen.\n" " -d Fehlersuche, noch mehr ausgeben.\n" " -v\t\tDetailliert, mehr vs - mehr Details.\n" #: .././fsr/xfs_fsr.c:412 .././fsr/xfs_fsr.c:450 #, c-format msgid "out of memory: %s\n" msgstr "außerhalb des Speichers: %s\n" #: .././fsr/xfs_fsr.c:441 #, c-format msgid "Skipping %s: not mounted rw\n" msgstr "%s wird übersprungen: Nicht rw-eingehängt\n" #: .././fsr/xfs_fsr.c:455 #, c-format msgid "out of memory on realloc: %s\n" msgstr "außerhalb des Speichers bei realloc: %s\n" #: .././fsr/xfs_fsr.c:466 .././fsr/xfs_fsr.c:470 #, c-format msgid "strdup(%s) failed\n" msgstr "strdup(%s) fehlgeschlagen\n" #: .././fsr/xfs_fsr.c:481 #, c-format msgid "no rw xfs file systems in mtab: %s\n" msgstr "keine rw-XFS-Dateisysteme in mtab: %s\n" #: .././fsr/xfs_fsr.c:485 #, c-format msgid "Found %d mounted, writable, XFS filesystems\n" msgstr "%d eingehängte, schreibbare XFS-Dateisysteme gefunden\n" #: .././fsr/xfs_fsr.c:515 #, c-format msgid "%s: open failed\n" msgstr "%s: Öffnen fehlgeschlagen\n" #: .././fsr/xfs_fsr.c:530 #, c-format msgid "Can't use %s: mode=0%o own=%d nlink=%d\n" msgstr "%s kann nicht benutzt werden: Modus=0%o Besitzer=%d nlink=%d\n" #: .././fsr/xfs_fsr.c:550 #, c-format msgid "could not read %s, starting with %s\n" msgstr "%s kann nicht gelesen werden, es wird mit %s gestartet\n" #: .././fsr/xfs_fsr.c:589 #, c-format msgid "START: pass=%d ino=%llu %s %s\n" msgstr "START: Durchlauf=%d ino=%llu %s %s\n" #: .././fsr/xfs_fsr.c:606 #, c-format msgid "Completed all %d passes\n" msgstr "Alle %d Durchläufe wurden komplettiert\n" #: .././fsr/xfs_fsr.c:616 msgid "couldn't fork sub process:" msgstr "Unterprozess kann nicht verzweigt werden:" #: .././fsr/xfs_fsr.c:651 #, c-format msgid "%s startpass %d, endpass %d, time %d seconds\n" msgstr "%s Durchlaufstart %d, Durchlaufende %d, Zeit %d Sekunden\n" #: .././fsr/xfs_fsr.c:658 #, c-format msgid "open(%s) failed: %s\n" msgstr "Öffnen (%s) fehlgeschlagen: %s\n" #: .././fsr/xfs_fsr.c:664 #, c-format msgid "write(%s) failed: %s\n" msgstr "Schreiben (%s) fehlgeschlagen: %s\n" #: .././fsr/xfs_fsr.c:688 #, c-format msgid "%s start inode=%llu\n" msgstr "%s Start-Inode=%llu\n" #: .././fsr/xfs_fsr.c:693 #, c-format msgid "unable to get handle: %s: %s\n" msgstr "es konnte kein »handle« ermittelt werden: %s: %s\n" #: .././fsr/xfs_fsr.c:699 #, c-format msgid "unable to open: %s: %s\n" msgstr "konnte nicht geöffnet werden: %s: %s\n" #: .././fsr/xfs_fsr.c:706 #, c-format msgid "Skipping %s: could not get XFS geometry\n" msgstr "%s wird übersprungen: XFS-Geometrie konnte nicht ermittelt werden\n" #: .././fsr/xfs_fsr.c:741 #, c-format msgid "could not open: inode %llu\n" msgstr "kann nicht geöffnet werden: Inode %llu\n" #: .././fsr/xfs_fsr.c:771 #, c-format msgid "%s: xfs_bulkstat: %s\n" msgstr "%s: xfs_bulkstat: %s\n" #: .././fsr/xfs_fsr.c:798 #, c-format msgid "%s: Directory defragmentation not supported\n" msgstr "%s: Verzeichnis-Defragmentierung nicht unterstützt\n" #: .././fsr/xfs_fsr.c:817 #, c-format msgid "unable to construct sys handle for %s: %s\n" msgstr "sys-handle für %s kann nicht konstruiert werden: %s\n" #: .././fsr/xfs_fsr.c:828 #, c-format msgid "unable to open sys handle for %s: %s\n" msgstr "sys-handle für %s kann nicht geöffnet werden: %s\n" #: .././fsr/xfs_fsr.c:834 #, c-format msgid "unable to get bstat on %s: %s\n" msgstr "bstat auf %s kann nicht ermittelt werden: %s\n" #: .././fsr/xfs_fsr.c:841 #, c-format msgid "unable to open handle %s: %s\n" msgstr "handle %s kann nicht geöffnet werden: %s\n" #: .././fsr/xfs_fsr.c:848 #, c-format msgid "Unable to get geom on fs for: %s\n" msgstr "geom auf fs kann nicht ermittelt werden für: %s\n" #: .././fsr/xfs_fsr.c:899 #, c-format msgid "sync failed: %s: %s\n" msgstr "sync fehlgeschlagen: %s: %s\n" #: .././fsr/xfs_fsr.c:905 #, c-format msgid "%s: zero size, ignoring\n" msgstr "%s: Größe null, wird ignoriert\n" #: .././fsr/xfs_fsr.c:924 #, c-format msgid "locking check failed: %s\n" msgstr "Prüfen der Sperre fehlgeschlagen: %s\n" #: .././fsr/xfs_fsr.c:931 #, c-format msgid "mandatory lock: %s: ignoring\n" msgstr "verbindliche Sperre: %s: wird ignoriert\n" #: .././fsr/xfs_fsr.c:944 #, c-format msgid "unable to get fs stat on %s: %s\n" msgstr "fs-stat auf %s kann nicht ermittelt werden: %s\n" #: .././fsr/xfs_fsr.c:951 #, c-format msgid "insufficient freespace for: %s: size=%lld: ignoring\n" msgstr "unzureichender freier Speicher für: %s: Größe=%lld: wird ignoriert\n" #: .././fsr/xfs_fsr.c:958 #, c-format msgid "failed to get inode attrs: %s\n" msgstr "Ermitteln von Inode-attrs fehlgeschlagen: %s\n" #: .././fsr/xfs_fsr.c:963 #, c-format msgid "%s: immutable/append, ignoring\n" msgstr "%s: unveränderlich/anhängen, wird ignoriert\n" #: .././fsr/xfs_fsr.c:968 #, c-format msgid "%s: marked as don't defrag, ignoring\n" msgstr "%s: als nicht zu defragmentieren markiert, wird ignoriert\n" #: .././fsr/xfs_fsr.c:974 #, c-format msgid "cannot get realtime geometry for: %s\n" msgstr "Echtzeitgeometrie kann nicht ermittelt werden für: %s\n" #: .././fsr/xfs_fsr.c:979 #, c-format msgid "low on realtime free space: %s: ignoring file\n" msgstr "geringer freier Echtzeit-Raum: %s: Datei wird ignoriert\n" #: .././fsr/xfs_fsr.c:986 #, c-format msgid "cannot open: %s: Permission denied\n" msgstr "kann nicht geöffnet werden: %s: Erlaubnis verweigert\n" #: .././fsr/xfs_fsr.c:1045 .././fsr/xfs_fsr.c:1095 .././fsr/xfs_fsr.c:1175 #, fuzzy msgid "could not set ATTR\n" msgstr "ATTR auf tmp kann nicht gesetzt werden: %s:\n" #: .././fsr/xfs_fsr.c:1054 #, fuzzy, c-format msgid "unable to stat temp file: %s\n" msgstr "bstat auf %s kann nicht ermittelt werden: %s\n" #: .././fsr/xfs_fsr.c:1072 #, fuzzy, c-format msgid "unable to get bstat on temp file: %s\n" msgstr "bstat auf %s kann nicht ermittelt werden: %s\n" #: .././fsr/xfs_fsr.c:1077 #, c-format msgid "orig forkoff %d, temp forkoff %d\n" msgstr "" #: .././fsr/xfs_fsr.c:1130 msgid "big ATTR set failed\n" msgstr "" #: .././fsr/xfs_fsr.c:1151 #, fuzzy, c-format msgid "forkoff diff %d too large!\n" msgstr "Blockgröße %llu zu groß\n" #: .././fsr/xfs_fsr.c:1168 #, fuzzy, c-format msgid "data fork growth unimplemented\n" msgstr "%s: Echtzeit-Wachstum nicht implementiert\n" #: .././fsr/xfs_fsr.c:1183 #, fuzzy msgid "set temp attr\n" msgstr "%s setzt temp attr\n" #: .././fsr/xfs_fsr.c:1186 #, fuzzy msgid "failed to match fork offset\n" msgstr "memalign des Superblock-Puffers fehlgeschlagen\n" #: .././fsr/xfs_fsr.c:1233 #, c-format msgid "%s already fully defragmented.\n" msgstr "%s ist bereits vollständig defragmentiert.\n" #: .././fsr/xfs_fsr.c:1239 #, c-format msgid "%s extents=%d can_save=%d tmp=%s\n" msgstr "%s extents=%d can_save=%d tmp=%s\n" #: .././fsr/xfs_fsr.c:1245 #, c-format msgid "could not open tmp file: %s: %s\n" msgstr "tmp-Datei kann nicht geöffnet werden: %s: %s\n" #: .././fsr/xfs_fsr.c:1253 #, fuzzy, c-format msgid "failed to set ATTR fork on tmp: %s:\n" msgstr "ATTR auf tmp kann nicht gesetzt werden: %s:\n" #: .././fsr/xfs_fsr.c:1260 #, c-format msgid "could not set inode attrs on tmp: %s\n" msgstr "Inode-attrs auf tmp können nicht gesetzt werden: %s\n" #: .././fsr/xfs_fsr.c:1267 #, c-format msgid "could not get DirectIO info on tmp: %s\n" msgstr "DirekIO-Information auf tmp kann nicht ermittelt werden: %s\n" #: .././fsr/xfs_fsr.c:1282 #, c-format msgid "DEBUG: fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n" msgstr "FEHLERSUCHE: fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n" #: .././fsr/xfs_fsr.c:1289 #, c-format msgid "could not allocate buf: %s\n" msgstr "buf kann nicht zugewiesen werden: %s\n" #: .././fsr/xfs_fsr.c:1299 #, c-format msgid "could not open fragfile: %s : %s\n" msgstr "fragfile kann nicht geöffnet werden: %s : %s\n" #: .././fsr/xfs_fsr.c:1314 #, c-format msgid "could not trunc tmp %s\n" msgstr "tmp %s kann nicht gekürzt werden\n" #: .././fsr/xfs_fsr.c:1318 .././fsr/xfs_fsr.c:1338 .././fsr/xfs_fsr.c:1366 #, fuzzy, c-format msgid "could not lseek in tmpfile: %s : %s\n" msgstr "tmp-Datei kann nicht geöffnet werden: %s: %s\n" #: .././fsr/xfs_fsr.c:1333 #, c-format msgid "could not pre-allocate tmp space: %s\n" msgstr "tmp-Raum kann nicht vorab zugewiesen werden: %s\n" #: .././fsr/xfs_fsr.c:1346 msgid "Couldn't rewind on temporary file\n" msgstr "es konnte auf temporäre Datei zurückgesetzt werden\n" #: .././fsr/xfs_fsr.c:1353 #, c-format msgid "Temporary file has %d extents (%d in original)\n" msgstr "Temporäre Datei hat %d extents (%d im Original)\n" #: .././fsr/xfs_fsr.c:1356 #, c-format msgid "No improvement will be made (skipping): %s\n" msgstr "Es wird keine Verbesserung vorgenommen (übersprungen): %s\n" #: .././fsr/xfs_fsr.c:1371 #, fuzzy, c-format msgid "could not lseek in file: %s : %s\n" msgstr "fragfile kann nicht geöffnet werden: %s : %s\n" #: .././fsr/xfs_fsr.c:1407 #, c-format msgid "bad read of %d bytes from %s: %s\n" msgstr "fehlerhaftes Lesen von %d Bytes auf %s: %s\n" #: .././fsr/xfs_fsr.c:1411 .././fsr/xfs_fsr.c:1443 #, c-format msgid "bad write of %d bytes to %s: %s\n" msgstr "fehlerhaftes Schreiben von %d Bytes auf %s: %s\n" #: .././fsr/xfs_fsr.c:1428 #, c-format msgid "bad write2 of %d bytes to %s: %s\n" msgstr "fehlerhaftes write2 von %d Bytes auf %s: %s\n" #: .././fsr/xfs_fsr.c:1433 #, c-format msgid "bad copy to %s\n" msgstr "fehlerhafte Kopie auf %s\n" #: .././fsr/xfs_fsr.c:1451 #, fuzzy, c-format msgid "could not truncate tmpfile: %s : %s\n" msgstr "tmp-Datei kann nicht geöffnet werden: %s: %s\n" #: .././fsr/xfs_fsr.c:1456 #, fuzzy, c-format msgid "could not fsync tmpfile: %s : %s\n" msgstr "tmp-Datei kann nicht geöffnet werden: %s: %s\n" #: .././fsr/xfs_fsr.c:1471 #, c-format msgid "failed to fchown tmpfile %s: %s\n" msgstr "fchown tmpfile fehlgeschlagen: %s: %s\n" #: .././fsr/xfs_fsr.c:1481 #, c-format msgid "%s: file type not supported\n" msgstr "%s: Dateityp nicht unterstützt\n" #: .././fsr/xfs_fsr.c:1485 #, c-format msgid "%s: file modified defrag aborted\n" msgstr "%s: Datei geändert, Defragmentierung abgebrochen\n" #: .././fsr/xfs_fsr.c:1490 #, c-format msgid "%s: file busy\n" msgstr "%s: Datei wird benutzt\n" #: .././fsr/xfs_fsr.c:1492 #, c-format msgid "XFS_IOC_SWAPEXT failed: %s: %s\n" msgstr "XFS_IOC_SWAPEXT fehlgeschlagen: %s: %s\n" #: .././fsr/xfs_fsr.c:1500 #, c-format msgid "extents before:%d after:%d %s %s\n" msgstr "extents vorher: %d nachher: %d %s %s\n" #: .././fsr/xfs_fsr.c:1534 #, c-format msgid "tmp file name too long: %s\n" msgstr "tmp-Dateiname zu lang: %s\n" #: .././fsr/xfs_fsr.c:1584 #, c-format msgid "realloc failed: %s\n" msgstr "realloc fehlgeschlagen: %s\n" #: .././fsr/xfs_fsr.c:1597 #, c-format msgid "malloc failed: %s\n" msgstr "malloc fehlgeschlagen: %s\n" #: .././fsr/xfs_fsr.c:1627 #, c-format msgid "failed reading extents: inode %llu" msgstr "Lesen der Extents fehlgeschlagen: Inode %llu" #: .././fsr/xfs_fsr.c:1677 msgid "failed reading extents" msgstr "Lesen der Extents fehlgeschlagen" #: .././fsr/xfs_fsr.c:1765 .././fsr/xfs_fsr.c:1779 #, c-format msgid "tmpdir already exists: %s\n" msgstr "tmpdir exisitiert bereits: %s\n" #: .././fsr/xfs_fsr.c:1768 #, c-format msgid "could not create tmpdir: %s: %s\n" msgstr "tmpdir könnte nicht erstellt werden: %s: %s\n" #: .././fsr/xfs_fsr.c:1781 #, c-format msgid "cannot create tmpdir: %s: %s\n" msgstr "tmpdir kann nicht erstellt werden: %s: %s\n" #: .././fsr/xfs_fsr.c:1819 .././fsr/xfs_fsr.c:1827 #, c-format msgid "could not remove tmpdir: %s: %s\n" msgstr "tmpdir könnte nicht entfernt werden: %s: %s\n" #: .././growfs/xfs_growfs.c:26 #, fuzzy, c-format msgid "" "Usage: %s [options] mountpoint\n" "\n" "Options:\n" "\t-d grow data/metadata section\n" "\t-l grow log section\n" "\t-r grow realtime section\n" "\t-n don't change anything, just show geometry\n" "\t-i convert log from external to internal format\n" "\t-t alternate location for mount table (/etc/mtab)\n" "\t-x convert log from internal to external format\n" "\t-D size grow data/metadata section to size blks\n" "\t-L size grow/shrink log section to size blks\n" "\t-R size grow realtime section to size blks\n" "\t-e size set realtime extent size to size blks\n" "\t-m imaxpct set inode max percent to imaxpct\n" "\t-V print version information\n" msgstr "" "Aufruf: %s [Optionen] Einhängepunkt\n" "\n" "Optionen:\n" "\t-d Daten-/Metadaten-Bereich vergrößern\n" "\t-l Protokoll-Bereich vergrößern\n" "\t-r Echtzeit-Bereich vergrößern\n" "\t-n nichts ändern, nur Geometrie anzeigen\n" "\t-I Inode-Nummern erlauben %d signifikante Bits zu übersteigen\n" "\t-i Protokoll vom externen auf das interne Format umwandeln\n" "\t-t alternativer Ort der Einhängepunkt-Tabelle (/etc/mtab)\n" "\t-x Protokoll vom internen auf das externe Format umwandeln\n" "\t-D Größe Daten-/Metadaten-Bereich auf blks-Größe vergrößern\n" "\t-L Größe vergrößern/verkleinern des Protokoll-Bereiches auf blks-Größe\n" "\t-R Größe Echtzeit-Bereich auf blks-Größe vergrößern\n" "\t-e Größe Echtezeit-Umfang auf blks-Größe setzen\n" "\t-m imaxpct Inodes auf maximal imaxcpt Prozent setzen\n" "\t-V Versions-Information anzeigen\n" #: .././growfs/xfs_growfs.c:66 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u rmapbt=%u\n" " =%-22s reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" msgstr "" "Metadaten =%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u\n" "Daten =%-22s bsize=%-6u Blöcke=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "Benennung =Version %-14u bsize=%-6u ascii-ci=%d\n" "Protokoll =%-22s bsize=%-6u Blöcke=%u, Version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "Echtzeit =%-22s extsz=%-6u Blöcke=%llu, rtextents=%llu\n" #: .././growfs/xfs_growfs.c:85 .././growfs/xfs_growfs.c:466 #: .././growfs/xfs_growfs.c:467 msgid "internal" msgstr "Intern" #: .././growfs/xfs_growfs.c:85 .././growfs/xfs_growfs.c:88 #: .././growfs/xfs_growfs.c:466 .././growfs/xfs_growfs.c:467 msgid "external" msgstr "extern" #: .././growfs/xfs_growfs.c:207 #, c-format msgid "%s: %s is not a mounted XFS filesystem\n" msgstr "%s: %s ist kein eingehängtes XFS-Dateisystem\n" #: .././growfs/xfs_growfs.c:224 #, c-format msgid "%s: specified file [\"%s\"] is not on an XFS filesystem\n" msgstr "%s: angegebene Datei [»%s«] ist kein XFS-Dateisystem\n" #: .././growfs/xfs_growfs.c:241 #, c-format msgid "%s: cannot determine geometry of filesystem mounted at %s: %s\n" msgstr "" "%s: Geometrie des auf %s eingehängten Dateisystems kann nicht ermittelt\n" "werden: %s\n" #: .././growfs/xfs_growfs.c:285 #, c-format msgid "%s: failed to access data device for %s\n" msgstr "%s: Zugriff auf Datenträger für %s fehlgeschlagen\n" #: .././growfs/xfs_growfs.c:290 #, c-format msgid "%s: failed to access external log for %s\n" msgstr "%s: Zugriff auf externes Protokoll für %s fehlgeschlagen.\n" #: .././growfs/xfs_growfs.c:296 #, c-format msgid "%s: failed to access realtime device for %s\n" msgstr "%s: Zugriff auf Echtzeit-Gerät für %s fehlgeschlagen.\n" #: .././growfs/xfs_growfs.c:336 #, c-format msgid "data size %lld too large, maximum is %lld\n" msgstr "Datengröße %lld zu groß, Maximum ist %lld\n" #: .././growfs/xfs_growfs.c:343 #, c-format msgid "data size %lld too small, old size is %lld\n" msgstr "Datengröße %lld zu klein, alte Größe ist %lld\n" #: .././growfs/xfs_growfs.c:351 #, c-format msgid "data size unchanged, skipping\n" msgstr "Datengröße unverändert, wird übersprungen\n" #: .././growfs/xfs_growfs.c:354 #, c-format msgid "inode max pct unchanged, skipping\n" msgstr "»inode max pct« unverändert, wird übersprungen\n" #: .././growfs/xfs_growfs.c:361 .././growfs/xfs_growfs.c:400 #: .././growfs/xfs_growfs.c:435 #, c-format msgid "%s: growfs operation in progress already\n" msgstr "%s: growfs-Operation wird immer noch ausgeführt.\n" #: .././growfs/xfs_growfs.c:365 #, c-format msgid "%s: XFS_IOC_FSGROWFSDATA xfsctl failed: %s\n" msgstr "%s: XFS_IOC_FSGROWFSDATA xfsctl fehlgeschlagen: %s\n" #: .././growfs/xfs_growfs.c:381 #, c-format msgid "realtime size %lld too large, maximum is %lld\n" msgstr "Echtzeit-Größe %lld zu groß, Maximum ist %lld\n" #: .././growfs/xfs_growfs.c:387 #, c-format msgid "realtime size %lld too small, old size is %lld\n" msgstr "Echtzeit-Größe %lld zu klein, alte Größe ist %lld\n" #: .././growfs/xfs_growfs.c:393 #, c-format msgid "realtime size unchanged, skipping\n" msgstr "Echtzeit-Größe unverändert, wird übersprungen\n" #: .././growfs/xfs_growfs.c:404 #, c-format msgid "%s: realtime growth not implemented\n" msgstr "%s: Echtzeit-Wachstum nicht implementiert\n" #: .././growfs/xfs_growfs.c:408 #, c-format msgid "%s: XFS_IOC_FSGROWFSRT xfsctl failed: %s\n" msgstr "%s: XFS_IOC_FSGROWFSRT xfsctl fehlgeschlagen: %s\n" #: .././growfs/xfs_growfs.c:429 #, c-format msgid "log size unchanged, skipping\n" msgstr "Protokoll-Größe unverändert, wird übersprungen\n" #: .././growfs/xfs_growfs.c:439 #, c-format msgid "%s: log growth not supported yet\n" msgstr "%s: Protokoll-Wachstum nicht implementiert\n" #: .././growfs/xfs_growfs.c:443 #, c-format msgid "%s: XFS_IOC_FSGROWFSLOG xfsctl failed: %s\n" msgstr "%s: XFS_IOC_FSGROWFSLOG xfsctl fehlgeschlagen: %s\n" #: .././growfs/xfs_growfs.c:451 #, c-format msgid "%s: XFS_IOC_FSGEOMETRY xfsctl failed: %s\n" msgstr "%s: XFS_IOC_FSGEOMETRY xfsctl fehlgeschlagen: %s\n" #: .././growfs/xfs_growfs.c:456 #, c-format msgid "data blocks changed from %lld to %lld\n" msgstr "Datenblöcke von %lld auf %lld geändert.\n" #: .././growfs/xfs_growfs.c:459 #, c-format msgid "inode max percent changed from %d to %d\n" msgstr "Maximale Inode-Prozentzahl von %d auf %d geändert\n" #: .././growfs/xfs_growfs.c:462 #, c-format msgid "log blocks changed from %d to %d\n" msgstr "Protokollblöcke von %d auf %d geändert\n" #: .././growfs/xfs_growfs.c:465 #, c-format msgid "log changed from %s to %s\n" msgstr "Protokoll von %s auf %s geändert\n" #: .././growfs/xfs_growfs.c:469 #, c-format msgid "realtime blocks changed from %lld to %lld\n" msgstr "Echtzeit-Blöcke von %lld auf %lld geändert\n" #: .././growfs/xfs_growfs.c:472 #, c-format msgid "realtime extent size changed from %d to %d\n" msgstr "Echtzeit-Umfang von %d auf %d geändert\n" #: .././io/attr.c:60 #, fuzzy, c-format msgid "" "\n" " displays the set of extended inode flags associated with the current file\n" "\n" " Each individual flag is displayed as a single character, in this order:\n" " r -- file data is stored in the realtime section\n" " p -- file has preallocated extents (cannot be changed using chattr)\n" " i -- immutable, file cannot be modified\n" " a -- append-only, file can only be appended to\n" " s -- all updates are synchronous\n" " A -- the access time is not updated for this inode\n" " d -- do not include this file in a dump of the filesystem\n" " t -- child created in this directory has realtime bit set by default\n" " P -- child created in this directory has parents project ID by default\n" " n -- symbolic links cannot be created in this directory\n" " e -- for non-realtime files, observe the inode extent size value\n" " E -- children created in this directory inherit the extent size value\n" " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" " x -- Use direct access (DAX) for data in this file\n" " C -- for files with shared blocks, observe the inode CoW extent size value\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, but only list attributes on directories\n" " -a -- show all flags which can be set alongside those which are set\n" " -v -- verbose mode; show long names of flags, not single characters\n" "\n" msgstr "" "\n" " zeigt den Satz von erweiterten Inode-Markierungen an, die zu der\n" " aktuellen Datei zugehörig sind.\n" "\n" " Jede einzelne Markierung wird als einzelner Buchstabe in dieser\n" " Reihenfolge angezeigt:\n" " r -- Dateiinhalt ist im Echtzeit-Bereich gespeichert\n" " p -- Datei hat vorher zugeteilten Umfang (kann nicht mit chattr\n" " geändert werden)\n" " i -- unveränderlich, Datei kann nicht verändert werden\n" " a -- nur anhängen, Datei kann nur daran angehängt werden\n" " s -- alle Aktualisierungen sind synchron\n" " A -- die Zugriffszeit für diesen Inode ist nicht aktualisiert\n" " d -- diese Datei nicht in die Ausgabe des Dateisystems einschließen\n" " t -- das in diesem Verzeichnis erzeugte Kind hat standardmäßig ein\n" " gesetztes Echtzeit-Bit.\n" " P -- das in diesem Verzeichnis erzeugte Kind hat standardmäßig die\n" " Projekt-ID der Eltern.\n" " n -- in diesem Verzeichnis können keine symbolischen Verweise erstellt\n" " werden\n" " e -- für Nicht-Echtzeit-Dateien wird die Größe des Inode-Umfangs beachtet\n" " E -- in diesem Verzeichnis erzeugt Kinder erben die Größe des Umfangs\n" " f -- diese Datei nicht bei der Defragmentierung des Dateisystems\n" " einschließen\n" "\n" " Optionen:\n" " -R -- rekursiv absteigend (nützlich, wenn die aktuelle Datei ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, aber nur die Attribute von Verzeichnissen\n" " auflisten\n" " -a -- alle Merkmale zeigen, die neben denen gesetzt werden können, die\n" " gesetzt sind.\n" " -v -- gesprächiger Modus; zeige lange Namen der Merkmale, keine einzelnen\n" " Zeichen\n" "\n" #: .././io/attr.c:93 #, fuzzy, c-format msgid "" "\n" " modifies the set of extended inode flags associated with the current file\n" "\n" " Examples:\n" " 'chattr +a' - sets the append-only flag\n" " 'chattr -a' - clears the append-only flag\n" "\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, only modifying attributes on directories\n" " +/-r -- set/clear the realtime flag\n" " +/-i -- set/clear the immutable flag\n" " +/-a -- set/clear the append-only flag\n" " +/-s -- set/clear the sync flag\n" " +/-A -- set/clear the no-atime flag\n" " +/-d -- set/clear the no-dump flag\n" " +/-t -- set/clear the realtime inheritance flag\n" " +/-P -- set/clear the project ID inheritance flag\n" " +/-n -- set/clear the no-symbolic-links flag\n" " +/-e -- set/clear the extent-size flag\n" " +/-E -- set/clear the extent-size inheritance flag\n" " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " +/-x -- set/clear the direct access (DAX) flag\n" " +/-C -- set/clear the CoW extent-size flag\n" " Note1: user must have certain capabilities to modify immutable/append-" "only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" " Note3: the realtime flag can only be set if the filesystem has a realtime\n" " section, and the (regular) file must be empty when the flag is set.\n" "\n" msgstr "" "\n" " verändert den Satz von erweiterten Inode-Merkmalen, die zu der\n" " aktuellen Datei zugehörig sind.\n" "\n" " Beispiele:\n" " »chattr +a« - setzt das Nur-anhängen-Merkmal\n" " »chattr -a« - löscht das Nur-anhängen-Merkmal\n" "\n" " -R -- rekursiv absteigend (nützlich, wenn die aktuelle Datei ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, aber nur die Attribute von Verzeichnissen\n" " auflisten\n" " +/-r -- setzen/löschen des Echtzeit-Merkmals\n" " +/-i -- setzen/löschen des Unveränderlich-Merkmals\n" " +/-a -- setzen/löschen des Nur-anhängen-Merkmals\n" " +/-s -- setzen/löschen des Sync-Merkmals\n" " +/-A -- setzen/löschen des No-atime-Merkmals\n" " +/-d -- setzen/löschen des No-dump-Merkmals\n" " +/-t -- setzen/löschen des Echtzeit-Vererbungs-Merkmals\n" " +/-P -- setzen/löschen des Projekt-ID-Vererbungs-Merkmals\n" " +/-n -- setzen/löschen des Kein-symbolischer-Verweis-Merkmals\n" " +/-e -- setzen/löschen des Erweiterte-Größe-Merkmals\n" " +/-E -- setzen/löschen des Erweiterte-Größe-Vererbungs-Merkmals\n" " +/-f -- setzen/löschen des Nicht-Defragmentierungs-Merkmals\n" " +/-S -- setzen/löschen des Datenstrom-Zuteiler-Merkmals\n" " Anmerkung1: Der Anwender muss gewisse Fähigkeiten haben, um das zu ändern,\n" " das unveränderlich oder zum Nur-Ändern ist.\n" " Anmerkung2: Unveränderliche-/Nur-Ändern-Dateien können nicht gelöscht\n" " werden; diese Dateien zu entfernen erfordert das vorherige\n" " Löschen des Unveränderlich-/Nur-Ändern-Merkmals.\n" " Anmerkung3: Das Echtzeit-Merkmal kann nur gesetzt werden, wenn das\n" " Dateisystem einen Echtzeit-Bereich hat, und die (reguläre)\n" " Datei muss leer sein, wenn das Merkmal gesetzt wird.\n" "\n" #: .././io/attr.c:176 .././io/attr.c:252 .././io/cowextsize.c:109 #: .././io/cowextsize.c:132 .././io/open.c:426 .././io/open.c:498 #: .././io/open.c:622 .././io/open.c:644 .././libxfs/init.c:127 #: .././mkfs/proto.c:302 .././quota/project.c:118 .././quota/project.c:163 #: .././quota/project.c:210 #, c-format msgid "%s: cannot open %s: %s\n" msgstr "%s: %s kann nicht geöffnet werden: %s\n" #: .././io/attr.c:179 .././io/attr.c:226 .././io/attr.c:255 .././io/attr.c:326 #: .././quota/project.c:122 .././quota/project.c:168 .././quota/project.c:215 #, c-format msgid "%s: cannot get flags on %s: %s\n" msgstr "%s: Es werden keine Merkmale von %s erlangt: %s\n" #: .././io/attr.c:261 .././io/attr.c:332 #, c-format msgid "%s: cannot set flags on %s: %s\n" msgstr "%s: Markierungen auf %s können nicht gesetzt werden: %s\n" #: .././io/attr.c:296 .././io/attr.c:310 #, c-format msgid "%s: unknown flag\n" msgstr "%s: unbekannte Markierung\n" #: .././io/attr.c:316 #, c-format msgid "%s: bad chattr command, not +/-X\n" msgstr "%s: schlechter chattr-Befehl, nicht +/-X\n" #: .././io/attr.c:343 msgid "[-R|-D] [+/-" msgstr "[-R|-D] [+/-" #: .././io/attr.c:348 msgid "change extended inode flags on the currently open file" msgstr "erweiterte Inode-Markierungen bei der derzeit offenen Datei ändern" #: .././io/attr.c:353 msgid "[-R|-D|-a|-v]" msgstr "[-R|-D|-a|-v]" #: .././io/attr.c:358 msgid "list extended inode flags set on the currently open file" msgstr "" "gesetzte erweiterte Inode-Markierungen bei der derzeit offenen Dateianzeigen" #: .././io/bmap.c:30 #, fuzzy, c-format msgid "" "\n" " prints the block mapping for an XFS file's data or attribute forks\n" " Example:\n" " 'bmap -vp' - tabular format verbose map, including unwritten extents\n" "\n" " bmap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -c -- prints the copy-on-write fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" " -e -- print delayed allocation extents.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are " "unwritten.)\n" " -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" " Note: the bmap for non-regular files can be obtained provided the file\n" " was opened appropriately (in particular, must be opened read-only).\n" "\n" msgstr "" "\n" " gibt die Block-Kartierung für die Daten- oder Attribus-Verzweigungen einer\n" " XFS-Datei aus\n" " Beispiel:\n" " »bmap -vp« - aussagekräftige Karte im Tabellenformat, einschließlich\n" " ungeschriebenem Umfang\n" "\n" " »bmap« schreibt die Karte der Plattenblöcke, die von der derzeitigen Datei\n" " belegt werden.\n" " Die Karte listet jeden Bereich, der von der Datei belegt wird, sowie \n" " Regionen in der Datei, die keine zugehörigen Blöcke (Löcher) haben auf.\n" " Standardmäßig nimmt jede Zeile der Liste die folgende Form an:\n" " Bereich: [Startversatz..Endversatz]: Startblock..Endblock\n" " Löcher sind durch den Ersatz von Startblock..Endblock durch »Loch«\n" " markiert.\n" " Alle Datei-Offsets und Plattenblöcke sind Einheiten aus 512-Byte-Blöcken.\n" " -a -- gibt die Attributs-Verzweigungs-Karte statt der\n" " Daten-Verzweigung aus.\n" " -d -- unterdrückt ein DMAPI-Lese-Ereignis, Offline-Teile werden als Löcher\n" " betrachtet.\n" " -l -- zeigt außerdem die Länge von jedem Bereich in 512-Byte Blöcken.\n" " Anmerkung: Das »bmap« für irreguläre Dateien kann bereitgestellt werden,\n" " statt der Datei die passend geöffnet wurde (im Einzelnen darf sie\n" " Nur-Lesend geöffnet werden)\n" "\n" #: .././io/bmap.c:133 #, c-format msgid "%s: can't get geometry [\"%s\"]: %s\n" msgstr "%s: Geometrie [»%s«] kann nicht ermittelt werden: %s\n" #: .././io/bmap.c:141 #, c-format msgid "%s: cannot read attrs on \"%s\": %s\n" msgstr "%s: attrs auf »%s« können nicht gelesen werden: %s\n" #: .././io/bmap.c:159 .././io/fiemap.c:258 #, c-format msgid "%s: malloc of %d bytes failed.\n" msgstr "%s: Speicherallokation von %d Bytes fehlgeschlagen.\n" #: .././io/bmap.c:207 #, c-format msgid "%s: xfsctl(XFS_IOC_GETBMAPX) iflags=0x%x [\"%s\"]: %s\n" msgstr "%s: xfsctl(XFS_IOC_GETBMAPX) iflags=0x%x [\"%s\"]: %s\n" #: .././io/bmap.c:238 #, c-format msgid "%s: cannot realloc %d bytes\n" msgstr "%s: %d Bytes können nicht realloziert werden.\n" #: .././io/bmap.c:247 #, c-format msgid "%s: no extents\n" msgstr "%s: keine Bereiche\n" #: .././io/bmap.c:261 .././io/bmap.c:396 .././io/fiemap.c:104 #: .././io/fiemap.c:339 .././io/fiemap.c:343 #, c-format msgid "hole" msgstr "Loch" #: .././io/bmap.c:263 .././io/bmap.c:404 #, fuzzy, c-format msgid "delalloc" msgstr "falloc" #: .././io/bmap.c:272 #, c-format msgid " %lld blocks\n" msgstr "%lld Blöcke\n" #: .././io/bmap.c:352 .././io/fiemap.c:93 msgid "EXT" msgstr "EXT" #: .././io/bmap.c:353 .././io/fiemap.c:94 msgid "FILE-OFFSET" msgstr "DATEI-VERSATZ" #: .././io/bmap.c:354 msgid "RT-BLOCK-RANGE" msgstr "RT-BLOCK-AUSWAHL" #: .././io/bmap.c:354 .././io/fiemap.c:95 msgid "BLOCK-RANGE" msgstr "BLOCK-AUSWAHL" #: .././io/bmap.c:355 msgid "AG" msgstr "AG" #: .././io/bmap.c:356 msgid "AG-OFFSET" msgstr "AG-VERSATZ" #: .././io/bmap.c:357 .././io/fiemap.c:96 msgid "TOTAL" msgstr "GESAMT" #: .././io/bmap.c:358 msgid " FLAGS" msgstr "MARKIERUNGEN" #: .././io/bmap.c:438 #, c-format msgid " FLAG Values:\n" msgstr "MARKIERUNGS-Werte:\n" #: .././io/bmap.c:439 #, fuzzy, c-format msgid " %*.*o Shared extent\n" msgstr " %*.*o Ungeschriebener vorher zugeteiler Bereich\n" #: .././io/bmap.c:441 #, c-format msgid " %*.*o Unwritten preallocated extent\n" msgstr " %*.*o Ungeschriebener vorher zugeteiler Bereich\n" #: .././io/bmap.c:443 #, c-format msgid " %*.*o Doesn't begin on stripe unit\n" msgstr " %*.*o Beginnt nicht auf der Stripe-Einheit\n" #: .././io/bmap.c:445 #, c-format msgid " %*.*o Doesn't end on stripe unit\n" msgstr " %*.*o Endet nicht auf der Stripe-Einheit\n" #: .././io/bmap.c:447 #, c-format msgid " %*.*o Doesn't begin on stripe width\n" msgstr " %*.*o Beginnt nicht auf der Stripe-Breite\n" #: .././io/bmap.c:449 #, c-format msgid " %*.*o Doesn't end on stripe width\n" msgstr " %*.*o Endet nicht auf der Stripe-Breite\n" #: .././io/bmap.c:465 msgid "[-adlpv] [-n nx]" msgstr "[-adlpv] [-n nx]" #: .././io/bmap.c:466 msgid "print block mapping for an XFS file" msgstr "Blockkarte für eine XFS-Datei ausgeben" #: .././io/copy_file_range.c:32 #, c-format msgid "" "\n" " Copies a range of bytes from a file into the open file, overwriting any " "data\n" " already there.\n" "\n" " Example:\n" " 'copy_range -s 100 -d 200 -l 300 some_file' - copies 300 bytes from " "some_file\n" " at offset 100 into the open\n" "\t\t\t\t\t file at offset 200\n" " 'copy_range some_file' - copies all bytes from some_file into the open " "file\n" " at position 0\n" msgstr "" #: .././io/copy_file_range.c:97 #, fuzzy, c-format msgid "invalid source offset -- %s\n" msgstr "Falsche Projekt-ID -- %s\n" #: .././io/copy_file_range.c:104 #, fuzzy, c-format msgid "invalid destination offset -- %s\n" msgstr "Falsche Projekt-ID -- %s\n" #: .././io/copy_file_range.c:111 #, fuzzy, c-format msgid "invalid length -- %s\n" msgstr "Falsche Projekt-ID -- %s\n" #: .././io/copy_file_range.c:143 msgid "[-s src_off] [-d dst_off] [-l len] src_file" msgstr "" #: .././io/copy_file_range.c:144 msgid "Copy a range of data between two files" msgstr "" #: .././io/cowextsize.c:40 #, fuzzy, c-format msgid "" "\n" " report or modify preferred CoW extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying cowextsize on directories\n" "\n" msgstr "" "\n" " zeigt oder ändert die vorgesehene Größe des Extents (in Bytes) des\n" " aktuellen Verzeichnisses\n" "\n" " -R -- rekursiv absteigend (nützlich, wenn der aktuelle Pfad ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, nur die »extsize« von Verzeichnissen ändern\n" "\n" #: .././io/cowextsize.c:81 .././io/open.c:595 #, c-format msgid "invalid target file type - file %s\n" msgstr "ungültiger Ziel-Dateityp - Datei %s\n" #: .././io/cowextsize.c:169 #, fuzzy, c-format msgid "non-numeric cowextsize argument -- %s\n" msgstr "nicht-numerisches »extsize«-Argument -- %s\n" #: .././io/cowextsize.c:193 #, fuzzy msgid "[-D | -R] [cowextsize]" msgstr "[-D | -R] [extsize]" #: .././io/cowextsize.c:198 #, fuzzy msgid "get/set preferred CoW extent size (in bytes) for the open file" msgstr "gib/setze bevorzugte Extent-Größe (in Bytes) für die offene Datei" #: .././io/fadvise.c:30 #, c-format msgid "" "\n" " advise the page cache about expected I/O patterns on the current file\n" "\n" " Modifies kernel page cache behaviour when operating on the current file.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_FADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_FADV_DONTNEED) [*]\n" " -n -- data will be accessed once (POSIX_FADV_NOREUSE) [*]\n" " -r -- expect random page references (POSIX_FADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_FADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_FADV_WILLNEED) [*]\n" " Notes: these interfaces are not supported in Linux kernels before 2.6.\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED and NOREUSE are equivalent, and force the maximum readahead.\n" "\n" msgstr "" "\n" " benachrichtigt den Zwischenspeicher über voraussichtliche I/O-Muster der\n" " aktuellen Datei\n" "\n" " Verändert das Verhalten des Kernelseiten-Zwischenspeichers während der\n" " Bearbeitung der vorliegenden Datei.\n" " Die Bereichs-Argumente werden von einigen Benachrichtigungs-Befehlen\n" " ([*] unten) benötigt. Ohne Argumente ist die POSIX_FADV_NORMAL-" "Benachrichtigung impliziert.\n" " -d -- diese Seiten werden nicht benötigt (POSIX_FADV_DONTNEED) [*]\n" " -n -- auf die Daten wird einmal zugegriffen (POSIX_FADV_NOREUSE) [*]\n" " -r -- erwartet zufällige Seiten Referenzen (POSIX_FADV_RANDOM)\n" " -s -- erwartet fortlaufende Seiten-Referenzen (POSIX_FADV_SEQUENTIAL)\n" " -w -- möchte diese Seiten (POSIX_FADV_WILLNEED) [*]\n" " Anmerkungen: Diese Schnittstellen werden nicht von Linux-Kerneln vor 2.6.\n" " unterstützt. NORMAL stellt die Standard-Vorauslesen-" "Einstellung für diese Datei ein.\n" " RANDOM stellt die Vorauslesen-Einstellung für diese Datei auf Null.\n" " SEQUENTIAL setzt die doppelte Standard-Vorauslesen-Einstellung für diese\n" " Datei ein.\n" " WILLNEED und NOREUSE sind gleichbedeutend und erzwingen maximales\n" " Vorauslesen.\n" "\n" #: .././io/fadvise.c:91 .././io/madvise.c:86 .././io/mincore.c:47 #: .././io/mmap.c:213 .././io/mmap.c:320 .././io/mmap.c:406 .././io/mmap.c:565 #: .././io/mmap.c:647 .././io/prealloc.c:73 .././io/pwrite.c:346 #: .././io/sendfile.c:124 .././io/sync_file_range.c:74 #, c-format msgid "non-numeric offset argument -- %s\n" msgstr "nicht-numerisches Versatz-Argument -- %s\n" #: .././io/fadvise.c:98 .././io/madvise.c:93 .././io/mincore.c:53 #: .././io/mmap.c:219 .././io/mmap.c:327 .././io/mmap.c:413 .././io/mmap.c:572 #: .././io/pread.c:454 .././io/pread.c:462 .././io/prealloc.c:78 #: .././io/pwrite.c:352 .././io/sendfile.c:131 .././io/sync_file_range.c:81 #, c-format msgid "non-numeric length argument -- %s\n" msgstr "nicht-numerisches Längen-Argument -- %s\n" #: .././io/fadvise.c:121 msgid "[-dnrsw] [off len]" msgstr "[-dnrsw] [off len]" #: .././io/fadvise.c:122 msgid "advisory commands for sections of a file" msgstr "Benachrichtigungsbefehl für Bereiche einer Datei" #: .././io/fiemap.c:31 #, fuzzy, c-format msgid "" "\n" " prints the block mapping for a file's data or attribute forks\n" " Example:\n" " 'fiemap -v' - tabular format verbose map\n" "\n" " fiemap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -v -- Verbose information\n" "\n" msgstr "" "\n" " gibt die Block-Kartierung für die Daten- oder Attribus-Verzweigungen einer\n" " XFS-Datei aus\n" " Beispiel:\n" " »bmap -vp« - aussagekräftige Karte im Tabellenformat, einschließlich\n" " ungeschriebenem Umfang\n" "\n" " »bmap« schreibt die Karte der Plattenblöcke, die von der derzeitigen Datei\n" " belegt werden.\n" " Die Karte listet jeden Bereich, der von der Datei belegt wird, sowie \n" " Regionen in der Datei, die keine zugehörigen Blöcke (Löcher) haben auf.\n" " Standardmäßig nimmt jede Zeile der Liste die folgende Form an:\n" " Bereich: [Startversatz..Endversatz]: Startblock..Endblock\n" " Löcher sind durch den Ersatz von Startblock..Endblock durch »Loch«\n" " markiert.\n" " Alle Datei-Offsets und Plattenblöcke sind Einheiten aus 512-Byte-Blöcken.\n" " -a -- gibt die Attributs-Verzweigungs-Karte statt der\n" " Daten-Verzweigung aus.\n" " -d -- unterdrückt ein DMAPI-Lese-Ereignis, Offline-Teile werden als Löcher\n" " betrachtet.\n" " -l -- zeigt außerdem die Länge von jedem Bereich in 512-Byte Blöcken.\n" " Anmerkung: Das »bmap« für irreguläre Dateien kann bereitgestellt werden,\n" " statt der Datei die passend geöffnet wurde (im Einzelnen darf sie\n" " Nur-Lesend geöffnet werden)\n" "\n" #: .././io/fiemap.c:97 #, fuzzy msgid "FLAGS" msgstr "MARKIERUNGEN" #: .././io/fiemap.c:146 .././io/fiemap.c:160 .././io/fiemap.c:345 #, fuzzy, c-format msgid " %llu blocks\n" msgstr "%lld Blöcke\n" #: .././io/fiemap.c:365 #, fuzzy msgid "[-alv] [-n nx]" msgstr "[-adlpv] [-n nx]" #: .././io/fiemap.c:366 #, fuzzy msgid "print block mapping for a file" msgstr "Blockkarte für eine XFS-Datei ausgeben" #: .././io/file.c:38 #, fuzzy, c-format msgid "%c%03d%c %-14s (%s,%s,%s,%s%s%s%s%s)\n" msgstr "%c%03d%c %-14s (%s,%s,%s,%s%s%s%s)\n" #: .././io/file.c:40 msgid "foreign" msgstr "fremd" #: .././io/file.c:40 msgid "xfs" msgstr "xfs" #: .././io/file.c:41 .././io/open.c:98 msgid "sync" msgstr "synchronisieren" #: .././io/file.c:41 .././io/open.c:98 msgid "non-sync" msgstr "nicht synchronisieren" #: .././io/file.c:42 .././io/open.c:99 msgid "direct" msgstr "direkt" #: .././io/file.c:42 .././io/open.c:99 msgid "non-direct" msgstr "nicht direkt" #: .././io/file.c:43 .././io/open.c:100 msgid "read-only" msgstr "Nur-lesen" #: .././io/file.c:43 .././io/open.c:100 msgid "read-write" msgstr "Nur-schreiben" #: .././io/file.c:44 .././io/open.c:101 msgid ",real-time" msgstr "Echtzeit" #: .././io/file.c:45 .././io/open.c:102 msgid ",append-only" msgstr "Nur-anhängen" #: .././io/file.c:46 .././io/open.c:103 msgid ",non-block" msgstr "Nicht-Block" #: .././io/file.c:47 .././io/open.c:104 #, fuzzy msgid ",tmpfile" msgstr "Datei" #: .././io/file.c:81 .././io/sendfile.c:101 .././quota/path.c:126 #, c-format msgid "value %d is out of range (0-%d)\n" msgstr "Wert %d ist außerhalb des Bereichs (0-%d)\n" #: .././io/file.c:94 .././quota/path.c:140 msgid "[N]" msgstr "[N]" #: .././io/file.c:99 msgid "set the current file" msgstr "derzeitige Datei setzen" #: .././io/file.c:108 msgid "list current open files and memory mappings" msgstr "gibt derzeit offene Dateien und Speicherauszüge an" #: .././io/freeze.c:36 #, c-format msgid "%s: cannot freeze filesystem at %s: %s\n" msgstr "%s: Dateisystem kann nicht bei %s gesperrt werden: %s\n" #: .././io/freeze.c:53 #, c-format msgid "%s: cannot unfreeze filesystem mounted at %s: %s\n" msgstr "%s: das auf %s einhängte Dateisystem kann nicht entsperrt werden: %s\n" #: .././io/freeze.c:69 msgid "freeze filesystem of current file" msgstr "Dateisystem der aktuellen Datei sperren" #: .././io/freeze.c:76 msgid "unfreeze filesystem of current file" msgstr "Dateisystem der aktuellen Datei entsperren" #: .././io/fsync.c:59 msgid "calls fsync(2) to flush all in-core file state to disk" msgstr "" "ruft fsync(2) auf, um alle Dateistatusse aus dem Kern auf die\n" "Platte zu leeren" #: .././io/fsync.c:66 msgid "calls fdatasync(2) to flush the files in-core data to disk" msgstr "" "ruft fsync(2) auf, um alle Dateiinhalte aus dem Kern auf die\n" "Platte zu leeren" #: .././io/getrusage.c:117 msgid "report process resource usage" msgstr "Bericht, Prozess, Ressource, Aufruf" #: .././io/imap.c:54 #, c-format msgid "ino %10llu count %2d mask %016llx\n" msgstr "ino %10llu Anzahl %2d Maske %016llx\n" #: .././io/imap.c:74 msgid "[nentries]" msgstr "[nentries]" #: .././io/imap.c:76 msgid "inode map for filesystem of current file" msgstr "Inode-Karte für das Dateisystem der " #: .././io/init.c:37 #, fuzzy, c-format msgid "Usage: %s [-adfinrRstVx] [-m mode] [-p prog] [-c cmd]... file\n" msgstr "Aufruf: %s [-adFfmrRstx] [-p Programm] [-c Befehl]... Datei\n" #: .././io/init.c:111 .././io/mmap.c:171 .././io/mmap.c:178 .././io/mmap.c:181 #: .././io/open.c:294 #, c-format msgid "no files are open, try 'help open'\n" msgstr "es sind keine Dateien geöffnet, versuchen sie »help open«\n" #: .././io/init.c:115 .././io/mmap.c:170 .././io/mmap.c:177 #, c-format msgid "no mapped regions, try 'help mmap'\n" msgstr "keine kartierten Bereiche, versuchen sie »help open«\n" #: .././io/init.c:121 #, c-format msgid "foreign file active, %s command is for XFS filesystems only\n" msgstr "Fremde Datei aktiv, der %s-Befehl ist nur für das XFS-Dateisystem\n" #: .././io/init.c:169 .././io/open.c:316 #, c-format msgid "non-numeric mode -- %s\n" msgstr "nicht-numerischer Modus -- %s\n" #: .././io/inject.c:120 #, c-format msgid "" "\n" " inject errors into the filesystem of the currently open file\n" "\n" " Example:\n" " 'inject readagf' - cause errors on allocation group freespace reads\n" "\n" " Causes the kernel to generate and react to errors within XFS, provided\n" " the XFS kernel code has been built with debugging features enabled.\n" " With no arguments, displays the list of error injection tags.\n" "\n" msgstr "" "\n" " speist Fehler in das Dateisystem der aktuell geöffneten Datei ein\n" "\n" " Beispiel:\n" " »inject readagf« - ruft Fehler hervor beim Lesen des für die Gruppe\n" " reservierten freien Raumes hervor\n" "\n" " Veranlasst den Kernel zu generieren und auf Fehler im XFS zu reagieren,\n" " vorausgesetzt, der Kernel-Kode wurde mit eingeschalteten\n" " Fehlersuche-Merkmalen erzeugt. Ohne Argumente wird eine Liste der\n" " Fehler-Einspeisungs-Kennzeichen angezeigt.\n" "\n" #: .././io/inject.c:146 #, c-format msgid "no such tag -- %s\n" msgstr "kein solches Kennzeichen -- %s\n" #: .././io/inject.c:167 msgid "[tag ...]" msgstr "[Kennzeichen ...]" #: .././io/inject.c:168 msgid "inject errors into a filesystem" msgstr "Fehler in ein Dateisystem einspeisen" #: .././io/link.c:34 #, c-format msgid "" "\n" "link the open file descriptor to the supplied filename\n" "\n" "\n" msgstr "" #: .././io/link.c:63 #, fuzzy msgid "filename" msgstr "Datei" #: .././io/link.c:65 msgid "link the open file descriptor to the supplied filename" msgstr "" #: .././io/madvise.c:31 #, c-format msgid "" "\n" " advise the page cache about access patterns expected for a mapping\n" "\n" " Modifies page cache behavior when operating on the current mapping.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_MADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_MADV_DONTNEED) [*]\n" " -r -- expect random page references (POSIX_MADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_MADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_MADV_WILLNEED) [*]\n" " Notes:\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED forces the maximum readahead.\n" "\n" msgstr "" "\n" " teilt dem Seiten-Zwischenspeicher die erwarteten Zugriffs-Vorlagen für\n" " eine Kartierung mit\n" "\n" " Ändert das Verhalten des Seiten-Zwischenspeichers beim Operieren auf der\n" " gegenwärtigen Kartierung. Die Bereichs-Argumente werden von einigen\n" " Ankündigungs-Befehlen benötigt([*] unten).\n" " Ohne Argumente ist die POSIX_MADV_NORMAL-Benachrichtigung impliziert.\n" " -d -- diese Seiten werden nicht benötigt (POSIX_MADV_DONTNEED) [*]\n" " -r -- erwartet zufällige Seiten Referenzen (POSIX_MADV_RANDOM)\n" " -s -- erwartet fortlaufende Seiten-Referenzen (POSIX_MADV_SEQUENTIAL)\n" " -w -- möchte diese Seiten (POSIX_MADV_WILLNEED) [*]\n" " NORMAL stellt die Standard-Vorauslesen-Einstellung für diese Datei ein.\n" " RANDOM stellt die Vorauslesen-Einstellung für diese Datei auf Null.\n" " SEQUENTIAL setzt die doppelte Standard-Vorauslesen-Einstellung für diese\n" " Datei ein.\n" " WILLNEED und NOREUSE sind gleichbedeutend und erzwingen maximales\n" " Vorauslesen.\n" "\n" #: .././io/madvise.c:97 .././io/mincore.c:57 #, fuzzy, c-format msgid "length argument too large -- %lld\n" msgstr "nicht-numerisches Längen-Argument -- %s\n" #: .././io/madvise.c:126 msgid "[-drsw] [off len]" msgstr "[-drsw] [off len]" #: .././io/madvise.c:127 msgid "give advice about use of memory" msgstr "einen Rat über den Gebrauch des Speichers geben" #: .././io/mincore.c:91 .././io/mincore.c:101 #, c-format msgid "0x%lx %lu pages (%llu : %lu)\n" msgstr "0x%lx %lu Seiten (%llu : %lu)\n" #: .././io/mincore.c:121 msgid "[off len]" msgstr "[off len]" #: .././io/mincore.c:122 msgid "find mapping pages that are memory resident" msgstr "Kartierungsseiten finden, die speicherresident sind" #: .././io/mmap.c:78 #, c-format msgid "offset (%lld) is before start of mapping (%lld)\n" msgstr "Versatz (%lld) liegt vor dem Start der Kartierung (%lld)\n" #: .././io/mmap.c:84 #, c-format msgid "offset (%lld) is beyond end of mapping (%lld)\n" msgstr "Versatz (%lld) liegt hinter dem Ende der Kartierung (%lld)\n" #: .././io/mmap.c:89 #, c-format msgid "range (%lld:%lld) is beyond mapping (%lld:%ld)\n" msgstr "Bereich (%lld:%lld) liegt außerhalb der Kartierung (%lld:%ld)\n" #: .././io/mmap.c:95 #, c-format msgid "offset address (%p) is not page aligned\n" msgstr "Versatz-Adresse (%p) ist nicht an der Seite ausgerichtet\n" #: .././io/mmap.c:135 #, fuzzy, c-format msgid "" "\n" " maps a range within the current file into memory\n" "\n" " Example:\n" " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" "\n" " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" " With no arguments, mmap shows the current mappings. The current mapping\n" " can be set by using the single argument form (mapping number or address).\n" " If two arguments are specified (a range), a new mapping is created and the\n" " following options are available:\n" " -r -- map with PROT_READ protection\n" " -w -- map with PROT_WRITE protection\n" " -x -- map with PROT_EXEC protection\n" " -s -- first do mmap(size)/munmap(size), try to reserve some free " "space\n" " If no protection mode is specified, all are used by default.\n" "\n" msgstr "" "\n" " bildet einen Bereich innerhalb der aktuellen Datei im Speicher ab.\n" "\n" " Beispiel:\n" " »mmap -rw 0 1m« - bildet ein Megabyte vom Anfang der aktuellen Datei ab\n" "\n" " Speicher eines Dateibereiches für eine nachfolgende Benutzung durch andere\n" " xfs-io-Befehle abbilden.\n" " Ohne Argumente zeigt mmap die derzeitige Kartierung. Die derzeitige\n" " Kartierung kann durch Benutzung einer einzelnen Argument-Form\n" " (Kartierungsnummer oder Adresse) gesetzt werden.\n" " Wenn zwei Argumente angegeben wurden (ein Bereich) wird eine neue\n" " Kartierung erstellt und die folgenden Optionen sind verfügbar:\n" " -r -- Karte mit PROT_READ-Schutz\n" " -w -- Karte mit PROT_WRITE-Schutz\n" " -x -- Karte mit PROT_EXEC-Schutz\n" " Wenn kein Schutz-Modus angegeben wurde, werden standardmäßig alle benutzt.\n" "\n" #: .././io/mmap.c:273 #, c-format msgid "" "\n" " flushes a range of bytes in the current memory mapping\n" "\n" " Writes all modified copies of pages over the specified range (or entire\n" " mapping if no range specified) to their backing storage locations. Also,\n" " optionally invalidates so that subsequent references to the pages will be\n" " obtained from their backing storage locations (instead of cached copies).\n" " -a -- perform asynchronous writes (MS_ASYNC)\n" " -i -- invalidate mapped pages (MS_INVALIDATE)\n" " -s -- perform synchronous writes (MS_SYNC)\n" "\n" msgstr "" "\n" " leert einen Bereich von Bytes in der aktuellen Speicher-Kartierung\n" "\n" " Schreibt alle veränderten Seitenkopien über den angegebenen Bereich (oder \n" " die vollständige Kartierung, wenn kein Bereich angegeben wurde) auf ihre\n" " zusätzlichen Speicherorte. Außerdem werden optional alle außer Kraft\n" " gesetzt, so dass nachfolgende Verweise von den zusätzlichen Speicherorten\n" " (anstelle der Kopien im Zwischenspeicher) erhalten werden.\n" " -a -- asynchrones Schreiben ausführen (MS_ASYNC)\n" " -i -- kartierte Seiten ungültig erklären (MS_INVALIDATE)\n" " -s -- synchrones Schreiben ausführen (MS_SYNC)\n" "\n" #: .././io/mmap.c:349 #, c-format msgid "" "\n" " reads a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n" "\n" " Accesses a range of the current memory mapping, optionally dumping it to\n" " the standard output stream (with -v option) for subsequent inspection.\n" " -f -- verbose mode, dump bytes with offsets relative to start of file.\n" " -r -- reverse order; start accessing from the end of range, moving " "backward\n" " -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n" " The accesses are performed sequentially from the start offset by default.\n" " Notes:\n" " References to whole pages following the end of the backing file results\n" " in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n" " on various filesystem conditions, including quota exceeded errors, and\n" " for physical device errors (such as unreadable disk blocks). No attempt\n" " has been made to catch signals at this stage...\n" "\n" msgstr "" "\n" " liest einen Bereich von Bytes in die aktuelle Speicherkartierung\n" "\n" " Beispiel:\n" " »mread -v 512 20« - Auszug von gelesenen 20 Bytes von 512 Bytes in die\n" " Kartierung\n" "\n" " Greift auf einen Bereich der aktuellen Speicherkartierung zu oder gibt\n" " sie optional zum Standard-Ausgabe-Strom aus (mit der »-v«-Option) für die\n" " nachfolgende Überprüfung.\n" " -f -- detaillierte Ausgabe - gibt Bytes mit relativem Versatz zum Anfang\n" " der Datei aus.\n" " -r -- umgekehrte Reihenfolge; Zugriff vom Ende des Bereiches beginnen und\n" " rückwärts bewegen.\n" " -v -- detaillierte Ausgabe - gibt Bytes mit relativem Versatz zum Anfang\n" " der Kartierung aus.\n" " Standardmäßig werden die Zugriffe der Reihe nach vom Versatz des Anfangs\n" " durchgeführt.\n" " Anmerkungen:\n" " Bezieht sich auf die ganzen Seiten, die dem Ende der\n" " Zusatzdatei-Ergebnisse bei der Zusendung des SIGBUS-Signals folgen.\n" " SIGBUS-Signale können außerdem unter unterschiedlichen\n" " Dateisystem-Bedingungen gesandt werden, einschließlich\n" " Quota-Überschreitungs-Fehlern und physischen Gerätefehlern (wie\n" " unlesbaren Platten-Blocks). Es wurde kein Versuch unternommen auf dieser\n" " Ebene Signale abzufangen...\n" "\n" #: .././io/mmap.c:513 #, c-format msgid "" "\n" " dirties a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n" "\n" " Stores a byte into memory for a range within a mapping.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -S -- use an alternate seed character\n" " -r -- reverse order; start storing from the end of range, moving backward\n" " The stores are performed sequentially from the start offset by default.\n" "\n" msgstr "" "\n" " verunreinigt einen Bereich von Bytes in die aktuelle Speicherkartierung\n" "\n" " Beispiel:\n" " »mwrite 512 20« - schreibt 20 Bytes von 512 Bytes a in die aktuelle\n" " Kartierung\n" "\n" " Speichert ein Byte in den Speicher für einen Bereich innerhalb einer \n" " Kartierung. Der Standard-Speicherwert ist »X«, das wiederholt wird um \n" " den angegebenen Bereich zu füllen.\n" " -S -- verwende ein anderes Füllzeichen\n" " -r -- umgekehrte Reihenfolge; Speichern vom Ende des Bereiches beginnen\n" " und rückwärts bewegen.\n" " Standardmäßig wird der Reihe nach vom Versatz des Anfangs gespeichert.\n" "\n" #: .././io/mmap.c:549 .././io/pread.c:439 .././io/pwrite.c:305 #: .././io/pwrite.c:332 #, c-format msgid "non-numeric seed -- %s\n" msgstr "Nicht-numerische Füllzeichen -- %s\n" #: .././io/mmap.c:601 #, c-format msgid "" "\n" " resizes the current memory mapping\n" "\n" " Examples:\n" " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" "\n" " Resizes the mappping, growing or shrinking from the current size.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -f -- use MREMAP_FIXED flag to mremap on new_address\n" " -m -- use the MREMAP_MAYMOVE flag\n" "\n" msgstr "" #: .././io/mmap.c:678 #, fuzzy msgid "[N] | [-rwx] [-s size] [off len]" msgstr "[N] | [-rwx] [off len]" #: .././io/mmap.c:680 msgid "mmap a range in the current file, show mappings" msgstr "mmap eines Bereiches der aktuellen Datei, Kartierungen anzeigen" #: .././io/mmap.c:689 msgid "[-r] [off len]" msgstr "[-r] [off len]" #: .././io/mmap.c:691 msgid "reads data from a region in the current memory mapping" msgstr "liest Daten aus einer Region der derzeitigen Speicherkartierung" #: .././io/mmap.c:700 msgid "[-ais] [off len]" msgstr "[-ais] [off len]" #: .././io/mmap.c:701 msgid "flush a region in the current memory mapping" msgstr "leere eine Region der derzeitigen Speicherkartierung" #: .././io/mmap.c:710 msgid "unmaps the current memory mapping" msgstr "die aktuelle Speicherkartierung entladen" #: .././io/mmap.c:718 msgid "[-r] [-S seed] [off len]" msgstr "[-r] [-S seed] [off len]" #: .././io/mmap.c:720 msgid "writes data into a region in the current memory mapping" msgstr "schreibt Daten in eine Region der derzeitigen Speicherkartierung" #: .././io/mmap.c:730 msgid "[-m|-f ] newsize" msgstr "" #: .././io/mmap.c:732 #, fuzzy msgid "alters the size of the current memory mapping" msgstr "die aktuelle Speicherkartierung entladen" #: .././io/open.c:69 msgid "socket" msgstr "Socket" #: .././io/open.c:71 .././repair/da_util.c:105 msgid "directory" msgstr "Verzeichnis" #: .././io/open.c:73 msgid "char device" msgstr "zeichenorientiertes Gerät" #: .././io/open.c:75 msgid "block device" msgstr "blockorientiertes Gerät" #: .././io/open.c:77 msgid "regular file" msgstr "reguläre Datei" #: .././io/open.c:79 msgid "symbolic link" msgstr "symbolischer Verweis" #: .././io/open.c:81 msgid "fifo" msgstr "fifo" #: .././io/open.c:96 .././io/open.c:709 #, c-format msgid "fd.path = \"%s\"\n" msgstr "fd.path = \"%s\"\n" #: .././io/open.c:97 #, fuzzy, c-format msgid "fd.flags = %s,%s,%s%s%s%s%s\n" msgstr "fd.flags = %s,%s,%s%s%s%s\n" #: .././io/open.c:108 #, c-format msgid "stat.ino = %lld\n" msgstr "stat.ino = %lld\n" #: .././io/open.c:109 #, c-format msgid "stat.type = %s\n" msgstr "stat.type = %s\n" #: .././io/open.c:110 #, c-format msgid "stat.size = %lld\n" msgstr "stat.size = %lld\n" #: .././io/open.c:111 #, c-format msgid "stat.blocks = %lld\n" msgstr "stat.blocks = %lld\n" #: .././io/open.c:113 #, c-format msgid "stat.atime = %s" msgstr "stat.atime = %s" #: .././io/open.c:114 #, c-format msgid "stat.mtime = %s" msgstr "stat.mtime = %s" #: .././io/open.c:115 #, c-format msgid "stat.ctime = %s" msgstr "stat.ctime = %s" #: .././io/open.c:124 #, c-format msgid "fsxattr.xflags = 0x%x " msgstr "fsxattr.xflags = 0x%x " #: .././io/open.c:126 #, c-format msgid "fsxattr.projid = %u\n" msgstr "fsxattr.projid = %u\n" #: .././io/open.c:127 #, c-format msgid "fsxattr.extsize = %u\n" msgstr "fsxattr.extsize = %u\n" #: .././io/open.c:128 #, fuzzy, c-format msgid "fsxattr.cowextsize = %u\n" msgstr "fsxattr.extsize = %u\n" #: .././io/open.c:129 #, c-format msgid "fsxattr.nextents = %u\n" msgstr "fsxattr.nextents = %u\n" #: .././io/open.c:130 #, c-format msgid "fsxattr.naextents = %u\n" msgstr "fsxattr.naextents = %u\n" #: .././io/open.c:135 #, c-format msgid "dioattr.mem = 0x%x\n" msgstr "dioattr.mem = 0x%x\n" #: .././io/open.c:136 #, c-format msgid "dioattr.miniosz = %u\n" msgstr "dioattr.miniosz = %u\n" #: .././io/open.c:137 #, c-format msgid "dioattr.maxiosz = %u\n" msgstr "dioattr.maxiosz = %u\n" #: .././io/open.c:256 #, fuzzy, c-format msgid "" "\n" " opens a new file in the requested mode\n" "\n" " Example:\n" " 'open -cd /tmp/data' - creates/opens data file read-write for direct IO\n" "\n" " Opens a file for subsequent use by all of the other xfs_io commands.\n" " With no arguments, open uses the stat command to show the current file.\n" " -a -- open with the O_APPEND flag (append-only mode)\n" " -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n" " -f -- open with O_CREAT (create the file if it doesn't exist)\n" " -m -- permissions to use in case a new file is created (default 0600)\n" " -n -- open with O_NONBLOCK\n" " -r -- open with O_RDONLY, the default is O_RDWR\n" " -s -- open with O_SYNC\n" " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n" " -R -- mark the file as a realtime XFS file immediately after opening it\n" " -T -- open with O_TMPFILE (create a file not visible in the namespace)\n" " Note1: usually read/write direct IO requests must be blocksize aligned;\n" " some kernels, however, allow sectorsize alignment for direct IO.\n" " Note2: the bmap for non-regular files can be obtained provided the file\n" " was opened correctly (in particular, must be opened read-only).\n" "\n" msgstr "" "\n" " öffnet eine Datei in der angeforderten Weise\n" "\n" " Beispiel:\n" " »open -cd /tmp/data« - erstellt/öffnet Datei zum Lesen/Schreiben für\n" " direkte IO\n" "\n" " Öffnet eine Datei zum anschließenden Gebrauch durch alle anderen\n" " XFS-Befehle\n" " Ohne Argumente benutzt »Öffnen« den »stat«-Befehl um die aktuelle Datei\n" " anzuzeigen.\n" " -F -- Datei eines fremden Dateisystems, erlaube keine XFS-spezifischen\n" " Befehle\n" " -a -- öffne mit der O_APPEND-Markierung (Nur-anhängen-Modus)\n" " -d -- öffne mit O_DIRECT (nicht gepufferte IO, vermerkt\n" " Ausrichtungsbeschränkungen)\n" " -f -- öffne mit O_CREAT (erstellt die Datei, wenn es sie nicht gibt)\n" " -m -- Rechte, die bei der Erstellung neuer Dateien gesetzt werden\n" " (Vorgabe 0600)\n" " -n -- öffne mit O_NONBLOCK\n" " -r -- öffne mit O_RDONLY, Vorgabe ist O_RDWR\n" " -s -- öffne mit O_SYNC\n" " -t -- öffne mit O_TRUNC (Datei auf die Länge Null kürzen, wenn es sie gibt\n" " -R -- Datei direkt nach dem Öffnen als Echtzeit-XFS-Datei markieren.\n" " Anmerkung1: Direkte Lese-/Schreib-IO-Abfragen müssen üblicherweise an der\n" " Blockgröße ausgerichtet werden. Einige Kernel erlauben jedoch\n" " Ausrichtung an der Sektorgröße für direktes IO.\n" " Anmerkung2: Das »bmap« für irreguläre Dateien kann bereitgestellt werden,\n" " statt der Datei die passend geöffnet wurde (im Einzelnen darf\n" " sie Nur-Lesend geöffnet werden)\n" "\n" #: .././io/open.c:348 #, c-format msgid "-T and -r options are incompatible\n" msgstr "" #: .././io/open.c:403 #, c-format msgid "" "\n" " displays the project identifier associated with the current path\n" "\n" " Options:\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, but only list projects on directories\n" "\n" msgstr "" "\n" " zeigt die Projektkennung, die mit dem derzeitigen Pfad verbunden wird\n" "\n" " Optionen:\n" " -R -- rekursiv absteigend (nützlich, wenn die aktuelle Datei ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, aber nur die Attribute von Verzeichnissen\n" " auflisten\n" "\n" #: .././io/open.c:469 #, c-format msgid "projid = %u\n" msgstr "projid = %u\n" #: .././io/open.c:477 #, c-format msgid "" "\n" " modifies the project identifier associated with the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying projects on directories\n" "\n" msgstr "" "\n" " zeigt die Projektkennung, die mit dem derzeitigen Pfad verbunden wird\n" "\n" " -R -- rekursiv absteigend (nützlich, wenn die aktuelle Datei ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, aber nur die Attribute von Verzeichnissen\n" " auflisten\n" "\n" #: .././io/open.c:536 #, c-format msgid "invalid project ID -- %s\n" msgstr "Falsche Projekt-ID -- %s\n" #: .././io/open.c:552 #, c-format msgid "" "\n" " report or modify preferred extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying extsize on directories\n" "\n" msgstr "" "\n" " zeigt oder ändert die vorgesehene Größe des Extents (in Bytes) des\n" " aktuellen Verzeichnisses\n" "\n" " -R -- rekursiv absteigend (nützlich, wenn der aktuelle Pfad ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, nur die »extsize« von Verzeichnissen ändern\n" "\n" #: .././io/open.c:681 #, c-format msgid "non-numeric extsize argument -- %s\n" msgstr "nicht-numerisches »extsize«-Argument -- %s\n" #: .././io/open.c:713 #, c-format msgid "statfs.f_bsize = %lld\n" msgstr "statfs.f_bsize = %lld\n" #: .././io/open.c:714 #, c-format msgid "statfs.f_blocks = %lld\n" msgstr "statfs.f_blocks = %lld\n" #: .././io/open.c:716 #, c-format msgid "statfs.f_frsize = %lld\n" msgstr "statfs.f_frsize = %lld\n" #: .././io/open.c:718 #, c-format msgid "statfs.f_bavail = %lld\n" msgstr "statfs.f_bavail = %lld\n" #: .././io/open.c:720 #, c-format msgid "statfs.f_files = %lld\n" msgstr "statfs.f_files = %lld\n" #: .././io/open.c:721 #, c-format msgid "statfs.f_ffree = %lld\n" msgstr "statfs.f_ffree = %lld\n" #: .././io/open.c:728 #, c-format msgid "geom.bsize = %u\n" msgstr "geom.bsize = %u\n" #: .././io/open.c:729 #, c-format msgid "geom.agcount = %u\n" msgstr "geom.agcount = %u\n" #: .././io/open.c:730 #, c-format msgid "geom.agblocks = %u\n" msgstr "geom.agblocks = %u\n" #: .././io/open.c:731 #, c-format msgid "geom.datablocks = %llu\n" msgstr "geom.datablocks = %llu\n" #: .././io/open.c:733 #, c-format msgid "geom.rtblocks = %llu\n" msgstr "geom.rtblocks = %llu\n" #: .././io/open.c:735 #, c-format msgid "geom.rtextents = %llu\n" msgstr "geom.rtextents = %llu\n" #: .././io/open.c:737 #, c-format msgid "geom.rtextsize = %u\n" msgstr "geom.rtextsize = %u\n" #: .././io/open.c:738 #, c-format msgid "geom.sunit = %u\n" msgstr "geom.sunit = %u\n" #: .././io/open.c:739 #, c-format msgid "geom.swidth = %u\n" msgstr "geom.swidth = %u\n" #: .././io/open.c:744 #, c-format msgid "counts.freedata = %llu\n" msgstr "counts.freedata = %llu\n" #: .././io/open.c:746 #, c-format msgid "counts.freertx = %llu\n" msgstr "counts.freertx = %llu\n" #: .././io/open.c:748 #, c-format msgid "counts.freeino = %llu\n" msgstr "counts.freeino = %llu\n" #: .././io/open.c:750 #, c-format msgid "counts.allocino = %llu\n" msgstr "counts.allocino = %llu\n" #: .././io/open.c:760 #, c-format msgid "" "\n" "Query physical information about an inode\n" " Default:\t-- Return 1 if any inode number greater than 32 bits exists in\n" "\t\t the filesystem, or 0 if none exist\n" " num\t\t-- Return inode number [num] if in use, or 0 if not in use\n" " -n num\t-- Return the next used inode after [num]\n" " -v\t\t-- Verbose mode - display returned inode number's size in bits\n" "\n" msgstr "" #: .././io/open.c:843 #, fuzzy, c-format msgid "%s is not a numeric inode value\n" msgstr "%s ist keine Zahl\n" #: .././io/open.c:922 #, fuzzy msgid "[-acdrstxT] [-m mode] [path]" msgstr "[-acdrstx] [Pfad]" #: .././io/open.c:923 msgid "open the file specified by path" msgstr "öffne die Datei, die durch den Pfad gegeben ist" #: .././io/open.c:931 msgid "[-v]" msgstr "[-v]" #: .././io/open.c:932 msgid "statistics on the currently open file" msgstr "Statistiken über die derzeit geöffnete Datei" #: .././io/open.c:940 msgid "close the current open file" msgstr "die derzeit offene Datei schließen" #: .././io/open.c:946 msgid "statistics on the filesystem of the currently open file" msgstr "Statistiken über das Dateisystem der derzeit offenen Datei" #: .././io/open.c:950 msgid "[-D | -R] projid" msgstr "[-D | -R] projid" #: .././io/open.c:955 msgid "change project identifier on the currently open file" msgstr "ändert Projekt-Kennzeichnung der derzeit offenen Datei" #: .././io/open.c:960 msgid "[-D | -R]" msgstr "[-D | -R]" #: .././io/open.c:965 msgid "list project identifier set on the currently open file" msgstr "" "zeigt die für die derzeit offene Datei gesetzten Projekt-Kennzeichnungen" #: .././io/open.c:970 msgid "[-D | -R] [extsize]" msgstr "[-D | -R] [extsize]" #: .././io/open.c:975 msgid "get/set preferred extent size (in bytes) for the open file" msgstr "gib/setze bevorzugte Extent-Größe (in Bytes) für die offene Datei" #: .././io/open.c:980 msgid "[-nv] [num]" msgstr "" #: .././io/open.c:985 #, fuzzy msgid "Query inode number usage in the filesystem" msgstr "Fehler - nicht genug freier Platz im Dateisystem\n" #: .././io/parent.c:48 #, c-format msgid "%s%s" msgstr "%s%s" #: .././io/parent.c:53 #, c-format msgid "inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n" msgstr "Inode-Pfad für Inode: %llu ist falsch - Pfad »%s« gibt es nicht\n" #: .././io/parent.c:57 #, c-format msgid "path \"%s\" does not stat for inode: %llu; err = %s\n" msgstr "Pfad »%s« enthält keinen Status für Inode: %llu; err = %s\n" #: .././io/parent.c:66 #, c-format msgid "path \"%s\" found\n" msgstr "Pfad »%s« nicht gefunden\n" #: .././io/parent.c:72 #, c-format msgid "inode-path for inode: %llu is incorrect - wrong inode#\n" msgstr "Inode-Pfad für Inode: %llu ist falsch - falscher Inode#\n" #: .././io/parent.c:76 .././io/parent.c:106 #, c-format msgid "ino mismatch for path \"%s\" %llu vs %llu\n" msgstr "ino für Pfad »%s« stimmt nicht überein %llu gegen %llu\n" #: .././io/parent.c:84 #, c-format msgid "inode number match: %llu\n" msgstr "Inode-Nummer stimmt überein: %llu\n" #: .././io/parent.c:94 #, c-format msgid "parent path \"%s\" does not stat: %s\n" msgstr "Elternpfad »%s« enthält keinen Status: %s\n" #: .././io/parent.c:102 #, c-format msgid "inode-path for inode: %llu is incorrect - wrong parent inode#\n" msgstr "Inode-Pfad für Inode: %llu ist falsch - falscher Eltern-Inode#\n" #: .././io/parent.c:115 #, c-format msgid "parent ino match for %llu\n" msgstr "Eltern-»ino« stimmt überein für %llu\n" #: .././io/parent.c:137 #, c-format msgid "parentpaths failed for ino %llu: %s\n" msgstr "»parentpaths« fehlgeschlagen für »ino« %llu: %s\n" #: .././io/parent.c:148 #, c-format msgid "inode-path for inode: %llu is missing\n" msgstr "Inode-Pfad für Inode: %llu fehlt\n" #: .././io/parent.c:172 #, c-format msgid "can't stat mount point \"%s\": %s\n" msgstr "Status für Einhängepunkt »%s« kann nicht abgefragt werden: %s\n" #: .././io/parent.c:193 #, c-format msgid "failed to get bulkstat information for inode %llu\n" msgstr "Bulkstat-Information für Inode %llu zu bekommen ist fehlgeschlagen\n" #: .././io/parent.c:199 #, c-format msgid "failed to get valid bulkstat information for inode %llu\n" msgstr "" "gültige Bulkstat-Information für Inode %llu zu bekommen ist\n" "fehlgeschlagen\n" #: .././io/parent.c:211 #, c-format msgid "checking inode %llu\n" msgstr "Inode %llu wird geprüft\n" #: .././io/parent.c:226 #, c-format msgid "syssgi bulkstat failed: %s\n" msgstr "syssgi bulkstat fehlgeschlagen:%s\n" #: .././io/parent.c:248 #, c-format msgid "unable to open \"%s\" for jdm: %s\n" msgstr "außerstande »%s« für jdm zu öffnen: %s\n" #: .././io/parent.c:258 #, c-format msgid "unable to allocate buffers: %s\n" msgstr "außerstande Puffer zu allozieren: %s\n" #: .././io/parent.c:268 #, c-format msgid "num errors: %d\n" msgstr "»num«-Fehler: %d\n" #: .././io/parent.c:270 #, c-format msgid "succeeded checking %llu inodes\n" msgstr "Prüfung von %llu Inodes erfolgreich\n" #: .././io/parent.c:283 #, c-format msgid "p_ino = %llu\n" msgstr "p_ino = %llu\n" #: .././io/parent.c:284 #, c-format msgid "p_gen = %u\n" msgstr "p_gen = %u\n" #: .././io/parent.c:285 #, c-format msgid "p_reclen = %u\n" msgstr "p_reclen = %u\n" #: .././io/parent.c:287 #, c-format msgid "p_name = \"%s%s\"\n" msgstr "p_name = »%s%s«\n" #: .././io/parent.c:289 #, c-format msgid "p_name = \"%s\"\n" msgstr "p_name = »%s«\n" #: .././io/parent.c:311 #, c-format msgid "%s: failed path_to_fshandle \"%s\": %s\n" msgstr "%s: path_to_fshandle »%s« fehlgeschlagen: %s\n" #: .././io/parent.c:319 #, c-format msgid "%s: path_to_handle failed for \"%s\"\n" msgstr "%s: path_to_handle fehlgeschlagen für»%s«\n" #: .././io/parent.c:326 #, c-format msgid "%s: unable to allocate parent buffer: %s\n" msgstr "%s: außerstande Eltern-Puffer zu allozieren: %s\n" #: .././io/parent.c:347 #, c-format msgid "%s: %s call failed for \"%s\": %s\n" msgstr "%s: %s-Aufruf fehlgeschlagen für »%s«: %s\n" #: .././io/parent.c:356 #, c-format msgid "%s: inode-path is missing\n" msgstr "%s: Inode-Pfad fehlt\n" #: .././io/parent.c:388 #, c-format msgid "file argument, \"%s\", is not in a mounted XFS filesystem\n" msgstr "Datei-Argument »%s« ist nicht in einem eingehängten XFS-Dateisystem\n" #: .././io/parent.c:428 #, c-format msgid "" "\n" " list the current file's parents and their filenames\n" "\n" " -c -- check the current file's file system for parent consistency\n" " -p -- list the current file's parents and their full paths\n" " -v -- verbose mode\n" "\n" msgstr "" "\n" " liste die Eltern der derzeitigen Datei und ihre Dateinamen auf\n" "\n" " -c -- prüfe das Dateisystem der derzeitigen Datei auf Vollständigkeit der\n" " Eltern\n" " -p -- liste die Eltern der derzeitigen Datei und ihre vollständigen\n" " Dateinamen auf\n" " -v -- detaillierte Ausgabe\n" "\n" #: .././io/parent.c:444 msgid "[-cpv]" msgstr "[-cpv]" #: .././io/parent.c:446 msgid "print or check parent inodes" msgstr "Eltern-Inodes ausgeben oder prüfen" #: .././io/pread.c:32 #, fuzzy, c-format msgid "" "\n" " reads a range of bytes in a specified block size from the given offset\n" "\n" " Example:\n" " 'pread -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n" "\n" " Reads a segment of the currently open file, optionally dumping it to the\n" " standard output stream (with -v option) for subsequent inspection.\n" " The reads are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different pattern is requested.\n" " -B -- read backwards through the range from offset (backwards N bytes)\n" " -F -- read forwards through the range of bytes from offset (default)\n" " -v -- be verbose, dump out buffers (used when reading forwards)\n" " -R -- read at random offsets in the range of bytes\n" " -Z N -- zeed the random number generator (used when reading randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" " -V N -- use vectored IO with N iovecs of blocksize each (preadv)\n" "\n" " When in \"random\" mode, the number of read operations will equal the\n" " number required to do a complete forward/backward scan of the range.\n" " Note that the offset within the range is chosen at random each time\n" " (an offset may be read more than once when operating in this mode).\n" "\n" msgstr "" "\n" " liest einen Bereich von Bytes in einer angegeben Block-Größe vom gegebenen\n" " Versatz\n" "\n" " Beispiel:\n" " »pread -v 512 20« - Auszug von gelesenen 20 Bytes aus 512 Bytes in die\n" " Datei\n" "\n" " Liest einen Ausschnitt der derzeit offenen Datei, leert sie optional in " "den\n" " Standard-Ausgabe-Datenstrom (mit »-v-Option«) für die nachfolgende\n" " Überprüfung. Das Lesen wird, vom Versatz beginnend, in fortlaufenden\n" " Blöcken mit durch die »-b«-Option einstellbarer Blockgröße ausgeführt\n" " (Standard-Blockgröße ist 4096 Bytes), außer wenn ein anderes Muster\n" " angefordert ist.\n" " -B -- liest vom Versatz rückwärts durch den Bereich (Rückwärts N Bytes)\n" " -F -- liest vom Versatz vorwärts durch den Bereich (Standard)\n" " -v -- detaillierte Ausgabe, Puffer leeren (beim Vorwärtslesen benutzt)\n" " -R -- von zufälligem Versatz im Bereich der Bytes lesen\n" " -Z N -- »zeedet« den Zufallszahlengenerator (benutzt beim zufälligen " "Lesen)\n" " (Heh, Zorry, die -s-/-S-Argumente sind in Benutzung durch pwrite)\n" " Im »Zufalls«-Modus entspricht die Anzahl der Leseoperationen der " "benötigten\n" " Anzahl, um einen kompletten Vor-/Rückwärtsscan des Bereiches zu machen.\n" " Merken Sie sich, dass der Versatz innerhalb des Bereiches jedesmal " "zufällig\n" " gewählt wird (ein Versatz könnte mehr als einmal beim Ausführen dieses\n" " Modus gelesen werden).\n" "\n" #: .././io/pread.c:400 .././io/pwrite.c:271 #, c-format msgid "non-numeric bsize -- %s\n" msgstr "nicht-numerische bsize -- %s\n" #: .././io/pread.c:430 .././io/pwrite.c:318 #, fuzzy, c-format msgid "non-numeric vector count == %s\n" msgstr "nicht-numerisches Argument -- %s\n" #: .././io/pread.c:507 #, fuzzy msgid "[-b bs] [-v] [-i N] [-FBR [-Z N]] off len" msgstr "[-b bs] [-v] off len" #: .././io/pread.c:508 msgid "reads a number of bytes at a specified offset" msgstr "liest eine Anzahl von Bytes beim angegebenen Versatz" #: .././io/prealloc.c:175 #, c-format msgid "" "\n" " modifies space associated with part of a file via fallocate\n" " Example:\n" " 'falloc 0 1m' - fills all holes within the first megabyte\n" "\n" " falloc uses the fallocate system call to alter space allocations in the\n" " open file. The following operations are supported:\n" " All the file offsets are in units of bytes.\n" " -c -- collapses the given range.\n" " -i -- inserts a hole into the given range of the file.\n" " -k -- do not change file size.\n" " -p -- unmap the given range from the file.\n" " -u -- unshare shared extents in the given range.\n" "\n" msgstr "" #: .././io/prealloc.c:347 .././io/prealloc.c:355 .././io/prealloc.c:363 #: .././io/prealloc.c:371 .././io/prealloc.c:381 .././io/prealloc.c:408 #: .././io/prealloc.c:418 .././io/prealloc.c:428 .././io/prealloc.c:448 msgid "off len" msgstr "off len" #: .././io/prealloc.c:348 msgid "allocates zeroed space for part of a file" msgstr "stellt genullten Speicher für einen Teil der Datei bereit" #: .././io/prealloc.c:356 msgid "frees space associated with part of a file" msgstr "leert Speicher, der mit einem Teil einer Datei verbunden ist" #: .././io/prealloc.c:365 msgid "reserves space associated with part of a file" msgstr "reserviert Speicher, der mit einem Teil einer Datei verbunden ist" #: .././io/prealloc.c:374 msgid "frees reserved space associated with part of a file" msgstr "" "gibt reservierten Speicher frei, der mit einem Teil einer Datei verbunden ist" #: .././io/prealloc.c:383 msgid "Converts the given range of a file to allocated zeros" msgstr "" #: .././io/prealloc.c:397 #, fuzzy msgid "[-c] [-k] [-p] [-u] off len" msgstr "[-b bs] [-v] off len" #: .././io/prealloc.c:399 msgid "allocates space associated with part of a file via fallocate" msgstr "" "weist Speicher zu, der mit einem Teil der Datei über fallocate verbunden ist" #: .././io/prealloc.c:410 #, fuzzy msgid "de-allocates space assocated with part of a file via fallocate" msgstr "" "weist Speicher zu, der mit einem Teil der Datei über fallocate verbunden ist" #: .././io/prealloc.c:420 msgid "de-allocates space and eliminates the hole by shifting extents" msgstr "" #: .././io/prealloc.c:430 msgid "creates new space for writing within file by shifting extents" msgstr "" #: .././io/prealloc.c:438 msgid "[-k] off len" msgstr "[-k] [off len]" #: .././io/prealloc.c:440 msgid "zeroes space and eliminates holes by preallocating" msgstr "" #: .././io/prealloc.c:450 msgid "unshares shared blocks within the range" msgstr "" #: .././io/pwrite.c:31 #, fuzzy, c-format msgid "" "\n" " writes a range of bytes (in block size increments) from the given offset\n" "\n" " Example:\n" " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Writes into a segment of the currently open file, using either a buffer\n" " filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n" " The writes are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different write pattern is requested.\n" " -S -- use an alternate seed number for filling the write buffer\n" " -i -- input file, source of data to write (used when writing forward)\n" " -d -- open the input file for direct IO\n" " -s -- skip a number of bytes at the start of the input file\n" " -w -- call fdatasync(2) at the end (included in timing results)\n" " -W -- call fsync(2) at the end (included in timing results)\n" " -B -- write backwards through the range from offset (backwards N bytes)\n" " -F -- write forwards through the range of bytes from offset (default)\n" " -R -- write at random offsets in the specified range of bytes\n" " -Z N -- zeed the random number generator (used when writing randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" " -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n" "\n" msgstr "" "\n" " schreibt einen Bereich von Bytes (Erhöhungen in Blockgröße) vom gegebenen\n" " Versatz\n" "\n" " Beispiel:\n" " »pwite 512 20« - schreibt 20 Bytes aus 512 Bytes in die Datei\n" "\n" " Schreibt unter Benutzung eines Puffers, der mit einem Mustersatz oder mit\n" " aus einer Eingabedatei gelesenen Daten gefüllt wurde, in einen Ausschnitt\n" " der derzeit offenen Datei. Das Lesen wird, vom Versatz beginnend, in " "fortlaufenden\n" " Blöcken mit durch die »-b«-Option einstellbarer Blockgröße ausgeführt\n" " (Standard-Blockgröße ist 4096 Bytes), außer wenn ein anderes Muster\n" " angefordert ist.\n" " -S -- alternative Füllnummer benutzen um den Schreibpuffer zu füllen\n" " -i -- Eingabedatei, Datenquelle zum Schreiben (benutzt, wenn vorwärts\n" " geschrieben wird)\n" " -d -- Eingabedatei für direktes IO öffnen\n" " -s -- eine Anzahl von Bytes am Anfang der Eingabedatei überspringen\n" " -w -- am Ende fdatasync(2) aufrufen (einschließlich zeitlicher " "Resultate)\n" " -W -- am Ende fsync(2) aufrufen (einschließlich zeitlicher Resultate)\n" " -B -- liest vom Versatz rückwärts durch den Bereich (Rückwärts N Bytes)\n" " -F -- liest vom Versatz vorwärts durch den Bereich (Standard)\n" " -R -- von zufälligem Versatz im Bereich der Bytes lesen\n" " -Z N -- »zeedet« den Zufallszahlengenerator (benutzt beim zufälligen " "Lesen)\n" " (Heh, Zorry, die -s-/-S-Argumente sind in Benutzung durch pwrite)\n" "\n" #: .././io/pwrite.c:298 #, c-format msgid "non-numeric skip -- %s\n" msgstr "nicht-numerische überspringen -- %s\n" #: .././io/pwrite.c:409 #, fuzzy msgid "" "[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] [-FBR [-Z N]] [-V N] off " "len" msgstr "[-i infile [-d] [-s überspringen]] [-b bs] [-S seed] [-wW] off len" #: .././io/pwrite.c:411 msgid "writes a number of bytes at a specified offset" msgstr "schreibt ein Anzahl von Bytes ab dem angegebenen Versatz" #: .././io/readdir.c:193 #, fuzzy, c-format msgid "read %llu bytes from offset %lld\n" msgstr "sende %lld/%lld Bytes vom Versatz %lld\n" #: .././io/readdir.c:194 #, fuzzy, c-format msgid "%s, %d ops, %s (%s/sec and %.4f ops/sec)\n" msgstr "%s, %d ops; %s (%s/Sek und %.4f ops/Sek)\n" #: .././io/readdir.c:207 #, fuzzy msgid "[-v][-o offset][-l length]" msgstr "[-r] [off len]" #: .././io/readdir.c:208 #, fuzzy msgid "read directory entries" msgstr "Verzeichnisse" #: .././io/reflink.c:32 #, c-format msgid "" "\n" " Links a range of bytes (in block size increments) from a file into a range\n" " of bytes in the open file. The contents of both file ranges must match.\n" "\n" " Example:\n" " 'dedupe some_file 0 4096 32768' - links 32768 bytes from some_file at\n" " offset 0 to into the open file at\n" " position 4096\n" "\n" " Reflink a range of blocks from a given input file to the open file. Both\n" " files share the same range of physical disk blocks; a write to the shared\n" " range of either file should result in the write landing in a new block and\n" " that range of the file being remapped (i.e. copy-on-write). Both files\n" " must reside on the same filesystem, and the contents of both ranges must\n" " match.\n" msgstr "" #: .././io/reflink.c:87 msgid "Extents did not match." msgstr "" #: .././io/reflink.c:141 .././io/reflink.c:264 #, fuzzy, c-format msgid "non-numeric src offset argument -- %s\n" msgstr "nicht-numerisches Versatz-Argument -- %s\n" #: .././io/reflink.c:147 .././io/reflink.c:270 #, fuzzy, c-format msgid "non-numeric dest offset argument -- %s\n" msgstr "nicht-numerisches Versatz-Argument -- %s\n" #: .././io/reflink.c:153 .././io/reflink.c:276 #, fuzzy, c-format msgid "non-positive length argument -- %s\n" msgstr "nicht-numerisches Längen-Argument -- %s\n" #: .././io/reflink.c:178 #, c-format msgid "" "\n" " Links a range of bytes (in block size increments) from a file into a range\n" " of bytes in the open file. The two extent ranges need not contain " "identical\n" " data.\n" "\n" " Example:\n" " 'reflink some_file 0 4096 32768' - links 32768 bytes from some_file at\n" " offset 0 to into the open file at\n" " position 4096\n" " 'reflink some_file' - links all bytes from some_file into the open file\n" " at position 0\n" "\n" " Reflink a range of blocks from a given input file to the open file. Both\n" " files share the same range of physical disk blocks; a write to the shared\n" " range of either file should result in the write landing in a new block and\n" " that range of the file being remapped (i.e. copy-on-write). Both files\n" " must reside on the same filesystem.\n" msgstr "" #: .././io/reflink.c:309 .././io/reflink.c:323 #, fuzzy msgid "infile src_off dst_off len" msgstr "-i infile | -f N [off len]" #: .././io/reflink.c:311 #, fuzzy msgid "reflinks a number of bytes at a specified offset" msgstr "liest eine Anzahl von Bytes beim angegebenen Versatz" #: .././io/reflink.c:325 #, fuzzy msgid "dedupes a number of bytes at a specified offset" msgstr "liest eine Anzahl von Bytes beim angegebenen Versatz" #: .././io/resblks.c:38 #, c-format msgid "non-numeric argument -- %s\n" msgstr "nicht-numerisches Argument -- %s\n" #: .././io/resblks.c:50 #, c-format msgid "reserved blocks = %llu\n" msgstr "reservierte Blöcke = %llu\n" #: .././io/resblks.c:52 #, c-format msgid "available reserved blocks = %llu\n" msgstr "verfügbare reservierte Blöcke = %llu\n" #: .././io/resblks.c:65 msgid "[blocks]" msgstr "[Blöcke]" #: .././io/resblks.c:67 msgid "get and/or set count of reserved filesystem blocks" msgstr "Anzahl derreservierten Dateisystem-Blöcke angeben und/oder setzen" #: .././io/seek.c:32 #, c-format msgid "" "\n" " returns the next hole and/or data offset at or after the requested offset\n" "\n" " Example:\n" " 'seek -d 512'\t\t- offset of data at or following offset 512\n" " 'seek -a -r 0'\t- offsets of all data and hole in entire file\n" "\n" " Returns the offset of the next data and/or hole. There is an implied hole\n" " at the end of file. If the specified offset is past end of file, or there\n" " is no data past the specified offset, EOF is returned.\n" " -a\t-- return the next data and hole starting at the specified offset.\n" " -d\t-- return the next data starting at the specified offset.\n" " -h\t-- return the next hole starting at the specified offset.\n" " -r\t-- return all remaining type(s) starting at the specified offset.\n" " -s\t-- also print the starting offset.\n" "\n" msgstr "" #: .././io/seek.c:218 msgid "-a | -d | -h [-r] off" msgstr "" #: .././io/seek.c:219 msgid "locate the next data and/or hole" msgstr "" #: .././io/sendfile.c:31 #, c-format msgid "" "\n" " transfer a range of bytes from the given offset between files\n" "\n" " Example:\n" " 'send -f 2 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Copies data between one file descriptor and another. Because this copying\n" " is done within the kernel, sendfile does not need to transfer data to and\n" " from user space.\n" " -f -- specifies an input file from which to source data to write\n" " -i -- specifies an input file name from which to source data to write.\n" " An offset and length in the source file can be optionally specified.\n" "\n" msgstr "" "\n" " einen Bereich von Bytes von gegebenen Versatz zwischen Dateien übertragen\n" "\n" " Beispiel:\n" " »send -f 2 512 20« - überträge 20 von 512 Bytes in die offene Datei\n" "\n" " Kopiert Daten zwischen einem Datei-Deskriptor und einem anderen. Weil\n" " dieses Kopieren innerhalb des Kernels erledigt wird, müssen keine Daten " "der\n" " Sendedatei zum und vom Benutzerraum übertragen werden.\n" " -f -- gibt eine Eingabedatei an, aus der die Quelldaten zu schreiben sind.\n" " -i -- gibt einen Eingabedateinamen an, von dem die Quelldaten zu schreiben\n" " sind.\n" " Optional kann ein Versatz und eine Länge in der Quelldatei angegeben\n" " werden.\n" "\n" #: .././io/sendfile.c:171 msgid "-i infile | -f N [off len]" msgstr "-i infile | -f N [off len]" #: .././io/sendfile.c:173 msgid "Transfer data directly between file descriptors" msgstr "Daten direkt zwischen Datei-Deskriptoren übertragen" #: .././io/shutdown.c:58 msgid "[-f]" msgstr "[-f]" #: .././io/shutdown.c:60 msgid "shuts down the filesystem where the current file resides" msgstr "fährt das Dateisystem herunter auf dem die aktuelle Datei liegt" #: .././io/sync.c:57 #, fuzzy msgid "calls sync(2) to flush all in-core filesystem state to disk" msgstr "" "ruft fsync(2) auf, um alle Dateistatusse aus dem Kern auf die\n" "Platte zu leeren" #: .././io/sync.c:66 #, fuzzy msgid "calls syncfs(2) to flush all in-core filesystem state to disk" msgstr "" "ruft fsync(2) auf, um alle Dateistatusse aus dem Kern auf die\n" "Platte zu leeren" #: .././io/sync_file_range.c:30 #, c-format msgid "" "\n" " Trigger specific writeback commands on a range of the current file\n" "\n" " With no options, the SYNC_FILE_RANGE_WRITE is implied.\n" " -a -- wait for IO to finish after writing (SYNC_FILE_RANGE_WAIT_AFTER).\n" " -b -- wait for IO to finish before writing (SYNC_FILE_RANGE_WAIT_BEFORE).\n" " -w -- write dirty data in range (SYNC_FILE_RANGE_WRITE).\n" "\n" msgstr "" #: .././io/sync_file_range.c:101 #, fuzzy msgid "[-abw] off len" msgstr "[-k] [off len]" #: .././io/sync_file_range.c:102 msgid "Control writeback on a range of a file" msgstr "" #: .././io/truncate.c:37 #, c-format msgid "non-numeric truncate argument -- %s\n" msgstr "nicht-numerisches Kürzungs-Argument -- %s\n" #: .././io/truncate.c:57 msgid "off" msgstr "aus" #: .././io/truncate.c:59 msgid "truncates the current file at the given offset" msgstr "kürzt die aktuelle Datei am gegebenen Versatz" #: .././libxcmd/command.c:85 #, c-format msgid "bad argument count %d to %s, expected at least %d arguments\n" msgstr "falsche Argument-Anzahl %d für %s, mindestens %d Argumente erwartet\n" #: .././libxcmd/command.c:89 #, c-format msgid "bad argument count %d to %s, expected %d arguments\n" msgstr "falsche Argument-Anzahl %d für %s, %d Argumente erwartet\n" #: .././libxcmd/command.c:93 #, c-format msgid "bad argument count %d to %s, expected between %d and %d arguments\n" msgstr "" "falsche Argument-Anzahl %d für %s, zwischen %d und %d Argumente erwartet\n" #: .././libxcmd/command.c:155 #, c-format msgid "cannot strdup command '%s': %s\n" msgstr "strdup-Befehl »%s« konnte nicht ausgeführt werden: %s\n" #: .././libxcmd/command.c:171 .././libxcmd/command.c:189 #, c-format msgid "command \"%s\" not found\n" msgstr "Befehl »%s« nicht gefunden\n" #: .././libxcmd/command.c:212 #, fuzzy, c-format msgid "%s %lld/%lld bytes at offset %lld\n" msgstr "%lld/%lld Bytes lesen beim Versatz %lld lesen\n" #: .././libxcmd/command.c:214 #, c-format msgid "%s, %d ops; %s (%s/sec and %.4f ops/sec)\n" msgstr "%s, %d ops; %s (%s/Sek und %.4f ops/Sek)\n" #: .././libxcmd/paths.c:285 #, fuzzy, c-format msgid "%s: unable to extract mount options for \"%s\"\n" msgstr "geom auf fs kann nicht ermittelt werden für: %s\n" #: .././libxcmd/paths.c:371 #, c-format msgid "%s: getmntinfo() failed: %s\n" msgstr "%s: getmntinfo() fehlgeschlagen: %s\n" #: .././libxcmd/paths.c:440 #, c-format msgid "%s: cannot setup path for mount %s: %s\n" msgstr "%s: Pfad zum Einhängen von %s kann nicht eingerichtet werden: %s\n" #: .././libxcmd/paths.c:462 #, c-format msgid "%s: cannot find mount point for path `%s': %s\n" msgstr "%s: Einhängepunkt für Pfad »%s« kann nicht gefunden werden: %s\n" #: .././libxcmd/paths.c:490 #, c-format msgid "%s: cannot setup path for project %s: %s\n" msgstr "%s: der Pfad für Projekt %s kann nicht eingerichtet werden: %s\n" #: .././libxcmd/paths.c:531 #, c-format msgid "%s: cannot initialise path table: %s\n" msgstr "%s: Pfad-Tabelle kann nicht initialisiert werden: %s\n" #: .././libxcmd/paths.c:551 #, c-format msgid "%s: cannot setup path for project dir %s: %s\n" msgstr "" "%s: der Pfad für Projektverzeichnis %s kann nicht eingerichtet werden: %s\n" #: .././libxcmd/quit.c:43 msgid "exit the program" msgstr "das Programm beenden" #: .././libxcmd/topology.c:165 #, c-format msgid "%s: %s appears to contain an existing filesystem (%s).\n" msgstr "%s: %s scheint ein existierendes Dateisystem zu enthalten (%s).\n" #: .././libxcmd/topology.c:169 #, c-format msgid "%s: %s appears to contain a partition table (%s).\n" msgstr "%s: %s scheint eine Partitionstabelle (%s) zu enthalten.\n" #: .././libxcmd/topology.c:173 #, fuzzy, c-format msgid "%s: %s appears to contain something weird according to blkid\n" msgstr "%s: %s scheint eine Partitionstabelle (%s) zu enthalten.\n" #: .././libxcmd/topology.c:182 #, fuzzy, c-format msgid "%s: probe of %s failed, cannot detect existing filesystem.\n" msgstr "%s: %s scheint ein existierendes Dateisystem zu enthalten (%s).\n" #: .././libxcmd/topology.c:204 #, c-format msgid "%s: Warning: trying to probe topology of a file %s!\n" msgstr "" #: .././libxcmd/topology.c:245 #, c-format msgid "warning: device is not properly aligned %s\n" msgstr "" #: .././libxcmd/topology.c:250 #, c-format msgid "Use -f to force usage of a misaligned device\n" msgstr "" #: .././libxcmd/topology.c:264 #, c-format msgid "warning: unable to probe device topology for device %s\n" msgstr "" #: .././libxfs/darwin.c:41 #, c-format msgid "%s: error opening the device special file \"%s\": %s\n" msgstr "%s: Fehler beim Öffnen der gerätspezifischen Datei »%s«: %s\n" #: .././libxfs/darwin.c:48 #, c-format msgid "%s: can't tell if \"%s\" is writable: %s\n" msgstr "%s: ob Datei %s schreibbar ist, kann nicht gesagt werden: %s\n" #: .././libxfs/darwin.c:76 .././libxfs/freebsd.c:116 .././libxfs/irix.c:58 #: .././libxfs/linux.c:170 #, c-format msgid "%s: cannot stat the device file \"%s\": %s\n" msgstr "%s: kann Status für Gerätedatei »%s« nicht abfragen: %s\n" #: .././libxfs/darwin.c:86 #, c-format msgid "%s: can't determine device size: %s\n" msgstr "%s: Gerätgröße kann nicht bestimmt werden: %s\n" #: .././libxfs/darwin.c:139 .././libxfs/freebsd.c:196 .././libxfs/irix.c:106 #: .././libxfs/linux.c:260 #, c-format msgid "%s: can't determine memory size\n" msgstr "%s: Speichergröße kann nicht bestimmt werden\n" #: .././libxfs/freebsd.c:49 .././libxfs/linux.c:76 #, c-format msgid "%s: %s possibly contains a mounted filesystem\n" msgstr "%s: %s enthält möglicherweise ein eingehängtes Dateisystem\n" #: .././libxfs/freebsd.c:60 .././libxfs/linux.c:104 #, c-format msgid "%s: %s contains a mounted filesystem\n" msgstr "%s: %s enthält ein eingehängtes Dateisystem\n" #: .././libxfs/freebsd.c:75 #, c-format msgid "%s: %s contains a possibly writable, mounted filesystem\n" msgstr "" "%s: %s enthält ein möglicherweise beschreibbares eingehängtes Dateisystem\n" #: .././libxfs/freebsd.c:89 .././libxfs/linux.c:100 #, c-format msgid "%s: %s contains a mounted and writable filesystem\n" msgstr "%s: %s enthält ein eingehängtes und beschreibbares Dateisystem\n" #: .././libxfs/freebsd.c:129 #, fuzzy, c-format msgid "%s: Not a device or file: \"%s\"\n" msgstr "%s: Kein Gerät oder Datei: »%s«n" #: .././libxfs/freebsd.c:135 #, c-format msgid "%s: DIOCGMEDIASIZE failed on \"%s\": %s\n" msgstr "%s: DIOCGMEDIASIZE fehlgeschlagen in »%s«: %s\n" #: .././libxfs/freebsd.c:141 #, c-format msgid "%s: DIOCGSECTORSIZE failed on \"%s\": %s\n" msgstr "%s: DIOCGSECTORSIZE fehlgeschlagen in »%s«: %s\n" #: .././libxfs/init.c:97 .././libxfs/init.c:196 #, c-format msgid "%s: %s: device %lld is not open\n" msgstr "%s: %s: Gerät %lld ist nicht geöffnet\n" #: .././libxfs/init.c:133 #, c-format msgid "%s: cannot stat %s: %s\n" msgstr "%s: kann Status für »%s« nicht abfragen: %s\n" #: .././libxfs/init.c:158 #, c-format msgid "%s: device %lld is already open\n" msgstr "%s: Gerät %lld ist bereits geöffnet\n" #: .././libxfs/init.c:171 #, c-format msgid "%s: %s: too many open devices\n" msgstr "%s: %s: zu viele offene Geräte\n" #: .././libxfs/init.c:214 #, c-format msgid "%s: can't find a character device matching %s\n" msgstr "%s: zeichenorientiertes Gerät, das auf %s passt wird nicht gefunden\n" #: .././libxfs/init.c:220 #, c-format msgid "%s: can't find a block device matching %s\n" msgstr "%s: blockorientiertes Gerät, das auf %s passt wird nicht gefunden\n" #: .././libxfs/init.c:348 #, c-format msgid "%s: can't get size for data subvolume\n" msgstr "%s: Größe des Daten des Unterdatenträgers kann nicht erlangt werden\n" #: .././libxfs/init.c:353 #, c-format msgid "%s: can't get size for log subvolume\n" msgstr "" "%s: Größe des Protokolls für Unterdatenträger kann nicht erlangt werden\n" #: .././libxfs/init.c:358 #, c-format msgid "%s: can't get size for realtime subvolume\n" msgstr "%s: Größe des Echtzeit-Unterdatenträgers kann nicht erlangt werden\n" #: .././libxfs/init.c:453 #, c-format msgid "%s: filesystem has a realtime subvolume\n" msgstr "%s: Dateisystem hat einen Echtzeit-Unterdatenträger\n" #: .././libxfs/init.c:475 #, c-format msgid "%s: realtime init - %llu != %llu\n" msgstr "%s: Echtzeitinitialisierung - %llu != %llu\n" #: .././libxfs/init.c:483 #, c-format msgid "%s: realtime size check failed\n" msgstr "%s: Prüfen der Echtzeit-Größe fehlgeschlagen\n" #: .././libxfs/init.c:605 #, fuzzy, c-format msgid "%s: buftarg init failed\n" msgstr "%s: stat von %s fehlgeschlagen\n" #: .././libxfs/init.c:626 #, c-format msgid "%s: bad buftarg reinit, ddev\n" msgstr "" #: .././libxfs/init.c:633 #, c-format msgid "%s: bad buftarg reinit, ldev mismatch\n" msgstr "" #: .././libxfs/init.c:640 #, c-format msgid "%s: bad buftarg reinit, logdev\n" msgstr "" #: .././libxfs/init.c:647 #, c-format msgid "%s: bad buftarg reinit, rtdev\n" msgstr "" #: .././libxfs/init.c:741 #, c-format msgid "%s: size check failed\n" msgstr "%s: Prüfen der Größe fehlgeschlagen\n" #: .././libxfs/init.c:753 #, c-format msgid "%s: V1 inodes unsupported. Please try an older xfsprogs.\n" msgstr "" #: .././libxfs/init.c:762 #, c-format msgid "%s: V1 directories unsupported. Please try an older xfsprogs.\n" msgstr "" #: .././libxfs/init.c:770 #, c-format msgid "%s: Unsupported features detected. Please try a newer xfsprogs.\n" msgstr "" #: .././libxfs/init.c:790 #, c-format msgid "%s: data size check failed\n" msgstr "%s: Prüfen der Datengröße fehlgeschlagen\n" #: .././libxfs/init.c:804 #, c-format msgid "%s: log size checks failed\n" msgstr "%s: Prüfen der Protokollgröße fehlgeschlagen\n" #: .././libxfs/init.c:815 #, c-format msgid "%s: realtime device init failed\n" msgstr "%s: Initialisieren von Echtzeitgerät fehlgeschlagen\n" #: .././libxfs/init.c:822 #, fuzzy, c-format msgid "%s: perag init failed\n" msgstr "%s: Öffnen fehlgeschlagen\n" #: .././libxfs/kmem.c:15 #, c-format msgid "%s: zone init failed (%s, %d bytes): %s\n" msgstr "%s: Zoneninitialisierung fehlgeschlagen (%s, %d Bytes): %s\n" #: .././libxfs/kmem.c:32 #, c-format msgid "%s: zone alloc failed (%s, %d bytes): %s\n" msgstr "%s: zuweisen von Zone fehlgeschlagen(%s, %d Bytes): %s\n" #: .././libxfs/kmem.c:56 #, c-format msgid "%s: malloc failed (%d bytes): %s\n" msgstr "%s: malloc fehlgeschlagen (%d Bytes): %s\n" #: .././libxfs/kmem.c:77 #, c-format msgid "%s: realloc failed (%d bytes): %s\n" msgstr "%s: realloc fehlgeschlagen (%d Bytes): %s\n" #: .././libxfs/linux.c:137 #, fuzzy, c-format msgid "%s: %s - cannot set blocksize %d on block device %s: %s\n" msgstr "" "%s: %s - Blockgröße auf blockorientiertem Gerät %s kann nicht gesetzt\n" "werden: %s\n" #: .././libxfs/linux.c:205 #, c-format msgid "%s: can't determine device size\n" msgstr "%s: Größe des Gerätes kann nicht bestimmt werden\n" #: .././libxfs/linux.c:213 #, c-format msgid "%s: warning - cannot get sector size from block device %s: %s\n" msgstr "" "%s: Warnung - Sektorgröße des blockorientierten Gerätes %s kann nicht\n" "erlangt werden: %s\n" #: .././libxfs/rdwr.c:82 #, c-format msgid "%s: %s can't memalign %d bytes: %s\n" msgstr "%s: %s konnte nicht memalign %d Bytes: %s\n" #: .././libxfs/rdwr.c:92 #, c-format msgid "%s: %s seek to offset %llu failed: %s\n" msgstr "%s: %s auf Versatz %llu zu positionieren fehlgeschlagen: %s\n" #: .././libxfs/rdwr.c:102 #, c-format msgid "%s: %s write failed: %s\n" msgstr "%s: %s schreiben fehlgeschlagen: %s\n" #: .././libxfs/rdwr.c:106 #, c-format msgid "%s: %s not progressing?\n" msgstr "%s: %s nicht durchführen?\n" #: .././libxfs/rdwr.c:581 #, c-format msgid "%s: %s can't memalign %u bytes: %s\n" msgstr "%s: %s konnte nicht memalign %u Bytes: %s\n" #: .././libxfs/rdwr.c:614 #, fuzzy, c-format msgid "%s: %s can't malloc %u bytes: %s\n" msgstr "%s: %s konnte nicht memalign %u Bytes: %s\n" #: .././libxfs/rdwr.c:697 #, fuzzy, c-format msgid "%s: %s invalid map %p or nmaps %d\n" msgstr "%s: ungültiger Projektname: %s\n" #: .././libxfs/rdwr.c:704 #, c-format msgid "%s: %s map blkno 0x%llx doesn't match key 0x%llx\n" msgstr "" #: .././libxfs/rdwr.c:749 #, c-format msgid "Warning: recursive buffer locking at block % detected\n" msgstr "" #: .././libxfs/rdwr.c:921 #, c-format msgid "%s: read failed: %s\n" msgstr "%s: lesen fehlgeschlagen: %s\n" #: .././libxfs/rdwr.c:927 #, fuzzy, c-format msgid "%s: error - read only %d of %d bytes\n" msgstr "%s: Fehler - nur %d von %d Bytes wurden geschrieben\n" #: .././libxfs/rdwr.c:1089 #, c-format msgid "%s: pwrite failed: %s\n" msgstr "%s: pwrite fehlgeschlagen: %s\n" #: .././libxfs/rdwr.c:1095 #, fuzzy, c-format msgid "%s: error - pwrite only %d of %d bytes\n" msgstr "%s: Fehler - nur %d von %d Bytes wurden geschrieben\n" #: .././libxfs/rdwr.c:1130 #, fuzzy, c-format msgid "%s: write verifer failed on %s bno 0x%llx/0x%x\n" msgstr "%s: Lesen auf %s fehlgeschlagen: %s\n" #: .././libxfs/trans.c:69 #, fuzzy, c-format msgid "%s: lidp calloc failed (%d bytes): %s\n" msgstr "%s: malloc fehlgeschlagen (%d Bytes): %s\n" #: .././libxfs/trans.c:183 #, c-format msgid "%s: xact calloc failed (%d bytes): %s\n" msgstr "%s: xact calloc fehlgeschlagen (%d Bytes): %s\n" #: .././libxfs/trans.c:670 #, fuzzy, c-format msgid "%s: warning - imap_to_bp failed (%d)\n" msgstr "%s: Warnung - itobp fehlgeschlagen (%d)\n" #: .././libxfs/trans.c:678 #, c-format msgid "%s: warning - iflush_int failed (%d)\n" msgstr "%s: Warnung - iflush_int fehlgeschlagen (%d)\n" #: .././libxfs/trans.c:738 .././libxfs/trans.c:792 #, c-format msgid "%s: unrecognised log item type\n" msgstr "%s: nicht erkannter Protokoll-Element-Typ\n" #: .././libxfs/util.c:617 #, fuzzy, c-format msgid "%s: cannot duplicate transaction: %s\n" msgstr "%s: Warnungen können nicht gesetzt werden: %s\n" #: .././libxlog/util.c:67 #, fuzzy, c-format msgid "%s: cannot find log head/tail (xlog_find_tail=%d)\n" msgstr "" "zero_log: Kopf/Fuß des Protokolls kann nicht gefunden werden\n" "(xlog_find_tail=%d), wird trotzdem auf Null gesetzt\n" #: .././libxlog/util.c:75 #, fuzzy, c-format msgid "%s: head block % tail block %\n" msgstr "zero_log: Kopfblock %lld Fußblock %lld\n" #: .././libxlog/util.c:97 #, c-format msgid "" "* ERROR: mismatched uuid in log\n" "* SB : %s\n" "* log: %s\n" msgstr "" "* FEHLER: uuid stimmt im Protokoll nicht überein\n" "* SB : %s\n" "* Protokoll : %s\n" #: .././libxlog/util.c:110 #, c-format msgid "" "\n" "LOG REC AT LSN cycle %d block %d (0x%x, 0x%x)\n" msgstr "" "\n" "LOG REC AT LSN Zyklus %d Block %d (0x%x, 0x%x)\n" #: .././libxlog/util.c:118 #, c-format msgid "* ERROR: bad magic number in log header: 0x%x\n" msgstr "* FEHLER: falsche Magische Zahl in Protokoll-Kopf: 0x%x\n" #: .././libxlog/util.c:127 #, c-format msgid "* ERROR: log format incompatible (log=%d, ours=%d)\n" msgstr "* FEHLER: Protokollformat inkompatibel (Protokoll=%d, ours=%d)\n" #: .././libxlog/util.c:137 .././libxlog/util.c:149 msgid "Bad log" msgstr "Falsches Protokoll" #: .././logprint/log_copy.c:46 .././logprint/log_dump.c:45 #, c-format msgid "%s: read error (%lld): %s\n" msgstr "%s: Lesefehler (%lld): %s\n" #: .././logprint/log_copy.c:51 .././logprint/log_dump.c:50 #, c-format msgid "%s: physical end of log at %lld\n" msgstr "%s: physisches Ende des Protokolls bei %lld\n" #: .././logprint/log_copy.c:55 #, c-format msgid "%s: short read? (%lld)\n" msgstr "%s: kurzes Lesen? (%lld)\n" #: .././logprint/log_copy.c:62 #, c-format msgid "%s: write error (%lld): %s\n" msgstr "%s: Schreibfehler (%lld): %s\n" #: .././logprint/log_copy.c:67 #, c-format msgid "%s: short write? (%lld)\n" msgstr "%s: kurzes Schreiben? (%lld)\n" #: .././logprint/log_dump.c:58 #, c-format msgid "%6lld HEADER Cycle %d tail %d:%06d len %6d ops %d\n" msgstr "%6lld HEADER Zyklus %d Ende %d:%06d Länge %6d ops %d\n" #: .././logprint/log_dump.c:69 #, c-format msgid "[%05lld - %05lld] Cycle 0x%08x New Cycle 0x%08x\n" msgstr "[%05lld - %05lld] Zyklus 0x%08x Neuer Zyklus 0x%08x\n" #: .././logprint/log_misc.c:87 #, c-format msgid "Oper (%d): tid: %x len: %d clientid: %s " msgstr "Oper (%d): tid: %x len: %d clientid: %s " #: .././logprint/log_misc.c:92 #, c-format msgid "flags: " msgstr "Markierungen: " #: .././logprint/log_misc.c:186 #, c-format msgid " Not enough data to decode further\n" msgstr " Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_misc.c:190 #, fuzzy, c-format msgid " tid: %x num_items: %d\n" msgstr " Typ: %s tid: %x num_items: %d\n" #: .././logprint/log_misc.c:235 #, c-format msgid "" "#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d flags: 0x%x\n" msgstr "" "#regs: %d Start-blkno: %lld (0x%llx) Länge: %d bmap Größe: %d " "Markierungen: 0x%x\n" #: .././logprint/log_misc.c:241 #, c-format msgid "#regs: %d Not printing rest of data\n" msgstr "#regs: %d Rest der Daten wird nicht ausgegeben\n" #: .././logprint/log_misc.c:258 #, c-format msgid "SUPER BLOCK Buffer: " msgstr "SUPER-BLOCK-Puffer: " #: .././logprint/log_misc.c:260 .././logprint/log_misc.c:348 #: .././logprint/log_misc.c:378 #, c-format msgid "Out of space\n" msgstr "Außerhalb des Raums\n" #: .././logprint/log_misc.c:268 #, fuzzy, c-format msgid "icount: %llu ifree: %llu " msgstr "icount: %lld ifree: %lld " #: .././logprint/log_misc.c:273 #, fuzzy, c-format msgid "fdblks: %llu frext: %llu\n" msgstr "fdblks: %lld frext: %lld\n" #: .././logprint/log_misc.c:284 #, c-format msgid "AGI Buffer: XAGI " msgstr "AGI Buffer: XAGI " #: .././logprint/log_misc.c:295 #, c-format msgid "out of space\n" msgstr "Außerhalb des Raums\n" #: .././logprint/log_misc.c:298 #, c-format msgid "ver: %d " msgstr "ver: %d " #: .././logprint/log_misc.c:300 #, c-format msgid "seq#: %d len: %d cnt: %d root: %d\n" msgstr "seq#: %d Länge: %d cnt: %d Wurzel: %d\n" #: .././logprint/log_misc.c:305 #, c-format msgid "level: %d free#: 0x%x newino: 0x%x\n" msgstr "Stufe: %d free#: 0x%x newino: 0x%x\n" #: .././logprint/log_misc.c:315 #, c-format msgid "AGI unlinked data skipped " msgstr "AGI-Verweis gelöst, Daten übersprungen" #: .././logprint/log_misc.c:316 #, c-format msgid "(CONTINUE set, no space)\n" msgstr "(FORTFAHREN gesetzt, kein Raum)\n" #: .././logprint/log_misc.c:322 .././logprint/log_print_all.c:148 #, c-format msgid "bucket[%d - %d]: " msgstr "bucket[%d - %d]: " #: .././logprint/log_misc.c:338 #, c-format msgid "AGF Buffer: XAGF " msgstr "AGF Puffer: XAGF " #: .././logprint/log_misc.c:351 #, c-format msgid "ver: %d seq#: %d len: %d \n" msgstr "ver: %d seq#: %d Länge: %d \n" #: .././logprint/log_misc.c:355 #, c-format msgid "root BNO: %d CNT: %d\n" msgstr "Wurzel BNO: %d CNT: %d\n" #: .././logprint/log_misc.c:358 #, c-format msgid "level BNO: %d CNT: %d\n" msgstr "Stufe BNO: %d CNT: %d\n" #: .././logprint/log_misc.c:361 #, c-format msgid "1st: %d last: %d cnt: %d freeblks: %d longest: %d\n" msgstr "1.: %d letzter: %d cnt: %d freeblks: %d längster: %d\n" #: .././logprint/log_misc.c:375 #, c-format msgid "DQUOT Buffer: DQ " msgstr "DQUOT Puffer: DQ " #: .././logprint/log_misc.c:382 #, c-format msgid "ver: %d flags: 0x%x id: %d \n" msgstr "ver: %d Markierungen: 0x%x id: %d \n" #: .././logprint/log_misc.c:385 #, c-format msgid "blk limits hard: %llu soft: %llu\n" msgstr "blk harte Limits: %llu weiche: %llu\n" #: .././logprint/log_misc.c:390 #, c-format msgid "blk count: %llu warns: %d timer: %d\n" msgstr "blk Anzahl: %llu Warnungen: %d Zeitnehmer: %d\n" #: .././logprint/log_misc.c:394 #, c-format msgid "ino limits hard: %llu soft: %llu\n" msgstr "ino harte Limits: %llu weiche: %llu\n" #: .././logprint/log_misc.c:399 #, c-format msgid "ino count: %llu warns: %d timer: %d\n" msgstr "ino-Anzahl: %llu Warnungen: %d Zeitnehmer: %d\n" #: .././logprint/log_misc.c:405 #, c-format msgid "BUF DATA\n" msgstr "BUF DATEN\n" #: .././logprint/log_misc.c:441 #, c-format msgid "QOFF: #regs: %d flags: 0x%x\n" msgstr "QOFF: #regs: %d Markierungen: 0x%x\n" #: .././logprint/log_misc.c:444 #, c-format msgid "QOFF: Not enough data to decode further\n" msgstr "QOFF: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_misc.c:454 #, c-format msgid "INODE CORE\n" msgstr "INODE CORE\n" #: .././logprint/log_misc.c:455 #, c-format msgid "magic 0x%hx mode 0%ho version %d format %d\n" msgstr "magischer 0x%hx Modus 0%ho Version %d Format %d\n" #: .././logprint/log_misc.c:458 #, c-format msgid "nlink %hd uid %d gid %d\n" msgstr "nlink %hd uid %d gid %d\n" #: .././logprint/log_misc.c:460 #, c-format msgid "atime 0x%x mtime 0x%x ctime 0x%x\n" msgstr "atime 0x%x mtime 0x%x ctime 0x%x\n" #: .././logprint/log_misc.c:462 #, c-format msgid "size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n" msgstr "Größe 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n" #: .././logprint/log_misc.c:465 #, c-format msgid "naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n" msgstr "naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n" #: .././logprint/log_misc.c:468 #, c-format msgid "flags 0x%x gen 0x%x\n" msgstr "Markierungen 0x%x gen 0x%x\n" #: .././logprint/log_misc.c:471 .././logprint/log_print_all.c:276 #, fuzzy, c-format msgid "flags2 0x%llx cowextsize 0x%x\n" msgstr "Markierungen 0x%x gen 0x%x\n" #: .././logprint/log_misc.c:488 #, c-format msgid "SHORTFORM DIRECTORY size %d\n" msgstr "KURZFORM VERZEICHNIS-Größe %d\n" #: .././logprint/log_misc.c:494 #, c-format msgid "SHORTFORM DIRECTORY size %d count %d\n" msgstr "KURZFORM VERZEICHNIS-Größe %d Anzahl %d\n" #: .././logprint/log_misc.c:497 #, c-format msgid ".. ino 0x%llx\n" msgstr ".. ino 0x%llx\n" #: .././logprint/log_misc.c:505 #, c-format msgid "%s ino 0x%llx namelen %d\n" msgstr "%s ino 0x%llx namelen %d\n" #: .././logprint/log_misc.c:544 #, c-format msgid "INODE: " msgstr "INODE: " #: .././logprint/log_misc.c:545 #, c-format msgid "#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n" msgstr "#regs: %d ino: 0x%llx Markierungen: 0x%x dsize: %d\n" #: .././logprint/log_misc.c:548 #, c-format msgid " blkno: %lld len: %d boff: %d\n" msgstr " blkno: %lld Länge: %d boff: %d\n" #: .././logprint/log_misc.c:553 #, c-format msgid "INODE: #regs: %d Not printing rest of data\n" msgstr "INODE: #regs: %d Rest der Daten nicht ausgeben\n" #: .././logprint/log_misc.c:584 #, c-format msgid "DEV inode: no extra region\n" msgstr "DEV Inode: Keine Extraregion\n" #: .././logprint/log_misc.c:587 #, c-format msgid "UUID inode: no extra region\n" msgstr "UUID Inode: Keine Extraregion\n" #: .././logprint/log_misc.c:604 #, c-format msgid "EXTENTS inode data\n" msgstr "EXTENTS Inode Daten\n" #: .././logprint/log_misc.c:607 #, c-format msgid "BTREE inode data\n" msgstr "BTREE Inode Daten\n" #: .././logprint/log_misc.c:610 #, c-format msgid "LOCAL inode data\n" msgstr "LOCAL Inode Daten\n" #: .././logprint/log_misc.c:631 #, fuzzy, c-format msgid "EXTENTS attr data\n" msgstr "EXTENTS Inode Daten\n" #: .././logprint/log_misc.c:634 #, fuzzy, c-format msgid "BTREE attr data\n" msgstr "BTREE Inode Daten\n" #: .././logprint/log_misc.c:637 #, fuzzy, c-format msgid "LOCAL attr data\n" msgstr "LOCAL Inode Daten\n" #: .././logprint/log_misc.c:675 #, c-format msgid "#regs: %d id: 0x%x" msgstr "#regs: %d id: 0x%x" #: .././logprint/log_misc.c:676 #, c-format msgid " blkno: %lld len: %d boff: %d\n" msgstr " blkno: %lld Länge: %d boff: %d\n" #: .././logprint/log_misc.c:680 #, c-format msgid "DQUOT: #regs: %d Not printing rest of data\n" msgstr "DQUOT: #regs: %d Rest der Daten nicht ausgeben\n" #: .././logprint/log_misc.c:699 #, c-format msgid "DQUOT: magic 0x%hx flags 0%ho\n" msgstr "DQUOT: Magische 0x%hx Markierungen 0%ho\n" #: .././logprint/log_misc.c:725 #, c-format msgid "ICR: split header, not printing\n" msgstr "" #: .././logprint/log_misc.c:729 #, fuzzy, c-format msgid "" "ICR: #ag: %d agbno: 0x%x len: %d\n" " cnt: %d isize: %d gen: 0x%x\n" msgstr "" "BUF: #regs:%d Start blkno:0x%llx Länge:%d bmap-Größe:%d Markierungen:0x" "%x\n" #: .././logprint/log_misc.c:755 #, c-format msgid "%s: lseek to %lld failed: %s\n" msgstr "%s: lseek auf %lld fehlgeschlagen: %s\n" #: .././logprint/log_misc.c:801 #, c-format msgid "%s: xlog_print_record: malloc failed\n" msgstr "%s: xlog_print_record: malloc fehlgeschlagen\n" #: .././logprint/log_misc.c:810 #, c-format msgid "%s: xlog_print_record: read error\n" msgstr "%s: xlog_print_record: Lesefehler\n" #: .././logprint/log_misc.c:905 .././logprint/log_misc.c:1008 #, c-format msgid "Left over region from split log item\n" msgstr "Übrige Region des geteilten Protkollelements\n" #: .././logprint/log_misc.c:993 #, c-format msgid "Unmount filesystem\n" msgstr "Dateisystem aushängen\n" #: .././logprint/log_misc.c:1000 #, c-format msgid "%s: unknown log operation type (%x)\n" msgstr "%s: unbekannter Protokolloperationstyp (%x)\n" #: .././logprint/log_misc.c:1041 #, c-format msgid "Header 0x%x wanted 0x%x\n" msgstr "Kopfzeile 0x%x gesucht 0x%x\n" #: .././logprint/log_misc.c:1055 #, c-format msgid "cycle: %d\tversion: %d\t" msgstr "Zyklus: %d\tVersion: %d\t" #: .././logprint/log_misc.c:1061 #, c-format msgid "length of Log Record: %d\tprev offset: %d\t\tnum ops: %d\n" msgstr "Länge des Protokolldatensatzes: %d\tprev Versatz: %d\t\tnum ops: %d\n" #: .././logprint/log_misc.c:1067 .././logprint/log_misc.c:1109 #, c-format msgid "cycle num overwrites: " msgstr "Zyklus Nummer Überschreibungen: " #: .././logprint/log_misc.c:1076 #, c-format msgid "uuid: %s format: " msgstr "uuid: %s Format: " #: .././logprint/log_misc.c:1079 #, c-format msgid "unknown\n" msgstr "unbekannt\n" #: .././logprint/log_misc.c:1082 #, c-format msgid "little endian linux\n" msgstr "kleines Endian-Linux\n" #: .././logprint/log_misc.c:1085 #, c-format msgid "big endian linux\n" msgstr "großes Endian-Linux\n" #: .././logprint/log_misc.c:1088 #, c-format msgid "big endian irix\n" msgstr "großes Endian-Irix\n" #: .././logprint/log_misc.c:1094 #, c-format msgid "h_size: %d\n" msgstr "h_size: %d\n" #: .././logprint/log_misc.c:1106 #, c-format msgid "extended-header: cycle: %d\n" msgstr "extended-header: Zyklus: %d\n" #: .././logprint/log_misc.c:1122 #, c-format msgid "* ERROR: found data after zeroed blocks block=%-21lld *\n" msgstr "* FEHLER: Daten nach genullten Blöcken gefunden Block=%-21lld *\n" #: .././logprint/log_misc.c:1133 #, c-format msgid "* ERROR: header cycle=%-11d block=%-21lld *\n" msgstr "* FEHLER: Kopfzeile Zyklus=%-11d Block=%-21lld *\n" #: .././logprint/log_misc.c:1144 #, c-format msgid "* ERROR: data block=%-21lld *\n" msgstr "* FEHLER: Datenblock=%-21lld *\n" #: .././logprint/log_misc.c:1155 #, c-format msgid "" "* ERROR: for header block=%lld\n" "* not enough hdrs for data length, required num = %d, hdr num = %d\n" msgstr "" "* ERROR: Für Kopfzeilenblock=%lld\n" "* nicht genügend hdrs für Datenlänge, benötigt num = %d, hdr num = " "%d\n" #: .././logprint/log_misc.c:1161 msgid "Not enough headers for data length." msgstr "Nicht genügend Kopfzeilen für Datenlänge." #: .././logprint/log_misc.c:1171 #, c-format msgid "%s: xlog_print: malloc failed for ext hdrs\n" msgstr "%s: xlog_print: malloc fehlgeschlagen für ext hdrs\n" #: .././logprint/log_misc.c:1219 .././logprint/log_misc.c:1295 #: .././logprint/log_misc.c:1366 .././logprint/log_misc.c:1403 #, c-format msgid "%s: physical end of log\n" msgstr "%s: Physisches Ende des Protokolls\n" #: .././logprint/log_misc.c:1225 .././logprint/log_misc.c:1300 #: .././logprint/log_misc.c:1418 #, c-format msgid "BLKNO: %lld\n" msgstr "BLKNO: %lld\n" #: .././logprint/log_misc.c:1283 #, c-format msgid "%s: problem finding oldest LR\n" msgstr "%s: Problem, das älteste LR zu finden\n" #: .././logprint/log_misc.c:1309 #, c-format msgid "%s: after %d zeroed blocks\n" msgstr "%s: Nach %d genullten Blöcken\n" #: .././logprint/log_misc.c:1378 msgid "illegal value" msgstr "unerlaubter Wert" #: .././logprint/log_misc.c:1384 #, c-format msgid "%s: skipped %d cleared blocks in range: %lld - %lld\n" msgstr "%s: %d geleerte Blöcke übersprungen in Bereich: %lld - %lld\n" #: .././logprint/log_misc.c:1389 #, c-format msgid "%s: totally cleared log\n" msgstr "%s: Gesamtes geleertes Protokoll\n" #: .././logprint/log_misc.c:1394 #, c-format msgid "%s: skipped %d zeroed blocks in range: %lld - %lld\n" msgstr "%s: %d genullte Blöcke übersprungen in Bereich: %lld - %lld\n" #: .././logprint/log_misc.c:1399 #, c-format msgid "%s: totally zeroed log\n" msgstr "%s: Gesamtes genulltes Protokoll\n" #: .././logprint/log_misc.c:1415 msgid "xlog_find_head: bad read" msgstr "xlog_find_head: Falsch gelesen" #: .././logprint/log_misc.c:1467 #, c-format msgid "%s: logical end of log\n" msgstr "%s: Logisches Ende des Protokolls\n" #: .././logprint/log_print_all.c:96 #, c-format msgid "" "BUF: #regs:%d start blkno:0x%llx len:%d bmap size:%d flags:0x%x\n" msgstr "" "BUF: #regs:%d Start blkno:0x%llx Länge:%d bmap-Größe:%d Markierungen:0x" "%x\n" #: .././logprint/log_print_all.c:106 #, c-format msgid "\tSUPER Block Buffer:\n" msgstr "\tSUPER Block-Puffer:\n" #: .././logprint/log_print_all.c:109 #, fuzzy, c-format msgid " icount:%llu ifree:%llu " msgstr "icount: %lld ifree: %lld " #: .././logprint/log_print_all.c:114 #, fuzzy, c-format msgid "fdblks:%llu frext:%llu\n" msgstr "fdblks: %lld frext: %lld\n" #: .././logprint/log_print_all.c:119 #, c-format msgid "\t\tsunit:%u swidth:%u\n" msgstr "\t\tsunit:%u swidth:%u\n" #: .././logprint/log_print_all.c:125 #, c-format msgid "\tAGI Buffer: (XAGI)\n" msgstr "\tAGI-Puffer: (XAGI)\n" #: .././logprint/log_print_all.c:128 #, c-format msgid "\t\tver:%d " msgstr "\t\tver:%d " #: .././logprint/log_print_all.c:130 #, c-format msgid "seq#:%d len:%d cnt:%d root:%d\n" msgstr "seq#:%d Länge:%d cnt:%d Wurzel:%d\n" #: .././logprint/log_print_all.c:135 #, c-format msgid "\t\tlevel:%d free#:0x%x newino:0x%x\n" msgstr "\t\tStufe:%d free#:0x%x newino:0x%x\n" #: .././logprint/log_print_all.c:159 #, c-format msgid "\tAGF Buffer: (XAGF)\n" msgstr "\tAGF-Puffer: (XAGF)\n" #: .././logprint/log_print_all.c:162 #, c-format msgid "\t\tver:%d seq#:%d len:%d \n" msgstr "\t\tver:%d seq#:%d Länge:%d \n" #: .././logprint/log_print_all.c:166 #, c-format msgid "\t\troot BNO:%d CNT:%d\n" msgstr "\t\tWurzel-BNO:%d CNT:%d\n" #: .././logprint/log_print_all.c:169 #, c-format msgid "\t\tlevel BNO:%d CNT:%d\n" msgstr "\t\tStufe BNO:%d CNT:%d\n" #: .././logprint/log_print_all.c:172 #, c-format msgid "\t\t1st:%d last:%d cnt:%d freeblks:%d longest:%d\n" msgstr "\t\t1.:%d letzter:%d cnt:%d freeblks:%d längster:%d\n" #: .././logprint/log_print_all.c:181 #, c-format msgid "\tDQUOT Buffer:\n" msgstr "\tDQUOT-Puffer:\n" #: .././logprint/log_print_all.c:184 #, c-format msgid "\t\tUIDs 0x%lx-0x%lx\n" msgstr "\t\tUIDs 0x%lx-0x%lx\n" #: .././logprint/log_print_all.c:189 #, c-format msgid "\tBUF DATA\n" msgstr "\tBUF-DATEN\n" #: .././logprint/log_print_all.c:211 #, c-format msgid "\tQUOTAOFF: #regs:%d type:%s\n" msgstr "\tQUOTAOFF: #regs:%d Typ:%s\n" #: .././logprint/log_print_all.c:226 #, c-format msgid "\tDQUOT: #regs:%d blkno:%lld boffset:%u id: %d\n" msgstr "\tDQUOT: #regs:%d blkno:%lld boffset:%u id: %d\n" #: .././logprint/log_print_all.c:230 #, c-format msgid "\t\tmagic 0x%x\tversion 0x%x\tID 0x%x (%d)\t\n" msgstr "\t\tmagische 0x%x\tVersion 0x%x\tID 0x%x (%d)\t\n" #: .././logprint/log_print_all.c:235 #, c-format msgid "\t\tblk_hard 0x%x\tblk_soft 0x%x\tino_hard 0x%x\tino_soft 0x%x\n" msgstr "\t\tblk_hard 0x%x\tblk_soft 0x%x\tino_hard 0x%x\tino_soft 0x%x\n" #: .././logprint/log_print_all.c:241 #, c-format msgid "\t\tbcount 0x%x (%d) icount 0x%x (%d)\n" msgstr "\t\tbcount 0x%x (%d) icount 0x%x (%d)\n" #: .././logprint/log_print_all.c:246 #, c-format msgid "\t\tbtimer 0x%x itimer 0x%x \n" msgstr "\t\tbtimer 0x%x itimer 0x%x \n" #: .././logprint/log_print_all.c:255 #, c-format msgid "\tCORE inode:\n" msgstr "\tCORE-Inode:\n" #: .././logprint/log_print_all.c:258 #, fuzzy, c-format msgid "\t\tmagic:%c%c mode:0x%x ver:%d format:%d\n" msgstr "\t\tmagische:%c%c Modus:0x%x ver:%d Format:%d onlink:%d\n" #: .././logprint/log_print_all.c:261 #, fuzzy, c-format msgid "\t\tuid:%d gid:%d nlink:%d projid:0x%04x%04x\n" msgstr "\t\tuid:%d gid:%d nlink:%d projid:%d\n" #: .././logprint/log_print_all.c:264 #, c-format msgid "\t\tatime:%d mtime:%d ctime:%d\n" msgstr "\t\tatime:%d mtime:%d ctime:%d\n" #: .././logprint/log_print_all.c:266 #, c-format msgid "\t\tflushiter:%d\n" msgstr "\t\tflushiter:%d\n" #: .././logprint/log_print_all.c:267 #, c-format msgid "\t\tsize:0x%llx nblks:0x%llx exsize:%d nextents:%d anextents:%d\n" msgstr "\t\tsize:0x%llx nblks:0x%llx exsize:%d nextents:%d anextents:%d\n" #: .././logprint/log_print_all.c:271 #, c-format msgid "\t\tforkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x gen:%d\n" msgstr "\t\tforkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x gen:%d\n" #: .././logprint/log_print_all.c:295 #, c-format msgid "\tINODE: #regs:%d ino:0x%llx flags:0x%x dsize:%d\n" msgstr "\tINODE: #regs:%d ino:0x%llx Markierungen:0x%x dsize:%d\n" #: .././logprint/log_print_all.c:311 #, c-format msgid "\t\tDATA FORK EXTENTS inode data:\n" msgstr "\t\tDATA FORK EXTENTS Inode-Daten:\n" #: .././logprint/log_print_all.c:318 #, c-format msgid "\t\tDATA FORK BTREE inode data:\n" msgstr "\t\tDATA FORK BTREE Inode-Daten:\n" #: .././logprint/log_print_all.c:325 #, c-format msgid "\t\tDATA FORK LOCAL inode data:\n" msgstr "\t\tDATA FORK LOCAL Inode-Daten:\n" #: .././logprint/log_print_all.c:332 #, c-format msgid "\t\tDEV inode: no extra region\n" msgstr "\t\tDEV-Inode: Keine Extraregion\n" #: .././logprint/log_print_all.c:336 #, c-format msgid "\t\tUUID inode: no extra region\n" msgstr "\t\tUUID-Inode: Keine Extraregion\n" #: .././logprint/log_print_all.c:351 #, c-format msgid "\t\tATTR FORK EXTENTS inode data:\n" msgstr "\t\tATTR FORK EXTENTS Inode-Daten:\n" #: .././logprint/log_print_all.c:359 #, c-format msgid "\t\tATTR FORK BTREE inode data:\n" msgstr "\t\tATTR FORK BTREE Inode-Daten:\n" #: .././logprint/log_print_all.c:367 #, c-format msgid "\t\tATTR FORK LOCAL inode data:\n" msgstr "\t\tATTR FORK LOCAL Inode-Daten:\n" #: .././logprint/log_print_all.c:388 #, fuzzy, c-format msgid "" "\tICR: #ag: %d agbno: 0x%x len: %d\n" "\t cnt: %d isize: %d gen: 0x%x\n" msgstr "" "BUF: #regs:%d Start blkno:0x%llx Länge:%d bmap-Größe:%d Markierungen:0x" "%x\n" #: .././logprint/log_print_all.c:440 #, c-format msgid "xlog_recover_print_logitem: illegal type\n" msgstr "xlog_recover_print_logitem: Illegaler Typ\n" #: .././logprint/log_print_all.c:492 #, c-format msgid "%s: illegal type" msgstr "%s: Illegaler Typ" #: .././logprint/log_print_all.c:500 #, c-format msgid ": cnt:%d total:%d " msgstr ": cnt:%d gesamt:%d " #: .././logprint/log_print_all.c:502 #, c-format msgid "a:0x%lx len:%d " msgstr "a:0x%lx Länge:%d " #: .././logprint/log_print_trans.c:27 #, fuzzy, c-format msgid "TRANS: tid:0x%x #items:%d trans:0x%x q:0x%lx\n" msgstr "TRANS: tid:0x%x Typ:%s #items:%d trans:0x%x q:0x%lx\n" #: .././logprint/log_print_trans.c:53 #, c-format msgid "%s: failed to find head and tail, error: %d\n" msgstr "%s: Kopf und Ende zu finden fehlgeschlagen, Fehler: %d\n" #: .././logprint/log_print_trans.c:58 #, c-format msgid " log tail: %lld head: %lld state: %s\n" msgstr " Protokollende: %lld Kopf: %lld Status: %s\n" #: .././logprint/log_print_trans.c:64 #, c-format msgid " override tail: %d\n" msgstr " Ende überschreiben: %d\n" #: .././logprint/log_print_trans.c:84 #, c-format msgid "" "Superblock has unknown incompatible log features (0x%x) enabled.\n" "Output may be incomplete or inaccurate. It is recommended that you\n" "upgrade your xfsprogs installation to match the filesystem features.\n" msgstr "" #: .././logprint/log_print_trans.c:92 #, c-format msgid "%s: failed in xfs_do_recovery_pass, error: %d\n" msgstr "%s: In xfs_do_recovery_pass fehlgeschlagen, Fehler: %d\n" #: .././logprint/log_redo.c:71 #, c-format msgid "%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n" msgstr "" "%s: Falsche Größe des efi-Formats: %u; erwartet %u oder %u; nextents = %u\n" #: .././logprint/log_redo.c:94 .././logprint/log_redo.c:110 #, c-format msgid "%s: xlog_print_trans_efi: malloc failed\n" msgstr "%s: xlog_print_trans_efi: malloc fehlgeschlagen\n" #: .././logprint/log_redo.c:104 #, fuzzy, c-format msgid "EFI: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_redo.c:118 #, fuzzy, c-format msgid "EFI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:122 #, fuzzy, c-format msgid "EFI free extent data skipped (CONTINUE set, no space)\n" msgstr "(FORTFAHREN gesetzt, kein Raum)\n" #: .././logprint/log_redo.c:161 #, c-format msgid "%s: xlog_recover_print_efi: malloc failed\n" msgstr "%s: xlog_recover_print_efi: malloc fehlgeschlagen\n" #: .././logprint/log_redo.c:170 #, fuzzy, c-format msgid "\tEFI: #regs:%d\tnum_extents:%d id:0x%llx\n" msgstr "\tEFI: #regs:%d num_extents:%d id:0x%llx\n" #: .././logprint/log_redo.c:202 #, fuzzy, c-format msgid "EFD: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:210 #, c-format msgid "EFD: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_redo.c:228 #, fuzzy, c-format msgid "\tEFD: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "\tEFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:249 #, fuzzy, c-format msgid "%s: bad size of RUI format: %u; expected %u; nextents = %u\n" msgstr "" "%s: Falsche Größe des efi-Formats: %u; erwartet %u oder %u; nextents = %u\n" #: .././logprint/log_redo.c:276 .././logprint/log_redo.c:295 #: .././logprint/log_redo.c:424 .././logprint/log_redo.c:443 #: .././logprint/log_redo.c:567 .././logprint/log_redo.c:586 #, fuzzy, c-format msgid "%s: %s: malloc failed\n" msgstr "malloc fehlgeschlagen: %s\n" #: .././logprint/log_redo.c:288 #, fuzzy, c-format msgid "RUI: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_redo.c:304 #, fuzzy, c-format msgid "RUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:308 #, fuzzy, c-format msgid "RUI extent data skipped (CONTINUE set, no space)\n" msgstr "(FORTFAHREN gesetzt, kein Raum)\n" #: .././logprint/log_redo.c:359 #, fuzzy, c-format msgid "RUD: #regs: %d\t id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:367 #, fuzzy, c-format msgid "RUD: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_redo.c:401 #, fuzzy, c-format msgid "%s: bad size of CUI format: %u; expected %u; nextents = %u\n" msgstr "" "%s: Falsche Größe des efi-Formats: %u; erwartet %u oder %u; nextents = %u\n" #: .././logprint/log_redo.c:436 #, fuzzy, c-format msgid "CUI: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_redo.c:452 #, fuzzy, c-format msgid "CUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:456 #, fuzzy, c-format msgid "CUI extent data skipped (CONTINUE set, no space)\n" msgstr "(FORTFAHREN gesetzt, kein Raum)\n" #: .././logprint/log_redo.c:502 #, fuzzy, c-format msgid "CUD: #regs: %d\t id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:510 #, fuzzy, c-format msgid "CUD: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_redo.c:544 #, fuzzy, c-format msgid "%s: bad size of BUI format: %u; expected %u; nextents = %u\n" msgstr "" "%s: Falsche Größe des efi-Formats: %u; erwartet %u oder %u; nextents = %u\n" #: .././logprint/log_redo.c:579 #, fuzzy, c-format msgid "BUI: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/log_redo.c:595 #, fuzzy, c-format msgid "BUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:599 #, fuzzy, c-format msgid "BUI extent data skipped (CONTINUE set, no space)\n" msgstr "(FORTFAHREN gesetzt, kein Raum)\n" #: .././logprint/log_redo.c:646 #, fuzzy, c-format msgid "BUD: #regs: %d\t id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:654 #, fuzzy, c-format msgid "BUD: Not enough data to decode further\n" msgstr "EFD: Nicht genug Daten, um weiter zu entschlüsseln\n" #: .././logprint/logprint.c:45 #, fuzzy, c-format msgid "" "Usage: %s [options...] \n" "\n" "Options:\n" " -c\t try to continue if error found in log\n" " -C copy the log from the filesystem to filename\n" " -d\t dump the log in log-record format\n" " -e\t exit when an error is found in the log\n" " -f\t specified device is actually a file\n" " -l filename of external log\n" " -n\t don't try and interpret log data\n" " -o\t print buffer data in hex\n" " -s block # to start printing\n" " -v print \"overwrite\" data\n" " -t\t print out transactional view\n" "\t-b in transactional view, extract buffer info\n" "\t-i in transactional view, extract inode info\n" "\t-q in transactional view, extract quota info\n" " -D print only data; no decoding\n" " -V print version information\n" msgstr "" "Aufruf: %s [Optionen ...] \n" "\n" "Optionen:\n" " -c\t versuchen fortzufahren, wenn Fehler im Protokoll\n" " entdeckt wurde\n" " -C das Protokoll vom Dateisystem nach Dateiname kopieren\n" " -d\t Auszug des Protokolls im log-record-Format\n" " -f\t angegebenes Gerät ist derzeit eine Datei\n" " -l Dateiname des externen Protokolls\n" " -n\t Protokolldaten nicht ausprobieren und interpretieren\n" " -o\t Pufferdaten hexadezimal ausgeben\n" " -s Block #, um Ausgabe zu starten\n" " -v »overwrite«-Daten ausgeben\n" " -t\t Transaktionsansicht ausgeben\n" "\t-b in Transaktionsansicht, Pufferinformationen extrahieren\n" "\t-i in Transaktionsansicht, Inodeinformationen extrahieren\n" "\t-q in Transaktionsansicht, Quotainformationen extrahieren\n" " -D Daten nur ausgeben, nicht entschlüsseln\n" " -V Versionsinformationen ausgeben\n" #: .././logprint/logprint.c:79 #, c-format msgid " Can't open device %s: %s\n" msgstr " Gerät %s kann nicht geöffnet werden: %s\n" #: .././logprint/logprint.c:85 #, c-format msgid " read of XFS superblock failed\n" msgstr " Lesen des XFS-Superblocks fehlgeschlagen!\n" #: .././logprint/logprint.c:105 #, c-format msgid "" " external log device not specified\n" "\n" msgstr "" " externes Protokollgerät nicht angegeben\n" "\n" #: .././logprint/logprint.c:121 #, c-format msgid "Can't open file %s: %s\n" msgstr "Datei %s kann nicht geöffnet werden: %s\n" #: .././logprint/logprint.c:222 #, c-format msgid "xfs_logprint:\n" msgstr "xfs_logprint:\n" #: .././logprint/logprint.c:231 #, c-format msgid " data device: 0x%llx\n" msgstr " Datengerät: 0x%llx\n" #: .././logprint/logprint.c:234 #, c-format msgid " log file: \"%s\" " msgstr " Protokolldatei: »%s« " #: .././logprint/logprint.c:236 #, c-format msgid " log device: 0x%llx " msgstr " Protokollgerät: 0x%llx " #: .././logprint/logprint.c:239 #, c-format msgid "" "daddr: %lld length: %lld\n" "\n" msgstr "" "daddr: %lld Länge: %lld\n" "\n" #: .././mkfs/proto.c:79 #, c-format msgid "%s: failed to open %s: %s\n" msgstr "%s: Öffnen von %s fehlgeschlagen: %s\n" #: .././mkfs/proto.c:86 .././mkfs/proto.c:309 #, c-format msgid "%s: read failed on %s: %s\n" msgstr "%s: Lesen auf %s fehlgeschlagen: %s\n" #: .././mkfs/proto.c:91 #, c-format msgid "%s: proto file %s premature EOF\n" msgstr "%s: proto-Datei %s vorzeitiges EOF\n" #: .././mkfs/proto.c:125 msgid "cannot reserve space" msgstr "Speicher kann nicht reserviert werden" #: .././mkfs/proto.c:180 #, c-format msgid "%s: premature EOF in prototype file\n" msgstr "%s: verfrühtes EOF in Prototyp-Datei\n" #: .././mkfs/proto.c:200 msgid "error reserving space for a file" msgstr "Fehler beim Reservieren von Speicher für eine Datei" #: .././mkfs/proto.c:267 msgid "error allocating space for a file" msgstr "Fehler beim Allokieren von Speicher für eine Datei" #: .././mkfs/proto.c:271 #, c-format msgid "%s: cannot allocate space for file\n" msgstr "%s: Speicher für Datei kann nicht alloziert werden\n" #: .././mkfs/proto.c:336 msgid "directory createname error" msgstr "Verzeichnis-Namenserstellungs-Fehler" #: .././mkfs/proto.c:350 msgid "directory create error" msgstr "Verzeichnis-Erstellungsfehler" #: .././mkfs/proto.c:415 .././mkfs/proto.c:427 .././mkfs/proto.c:438 #: .././mkfs/proto.c:445 #, c-format msgid "%s: bad format string %s\n" msgstr "%s: schlechte Format-Zeichenkette %s\n" #: .././mkfs/proto.c:466 .././mkfs/proto.c:513 .././mkfs/proto.c:528 #: .././mkfs/proto.c:540 .././mkfs/proto.c:552 .././mkfs/proto.c:563 msgid "Inode allocation failed" msgstr "Inode-Allokation fehlgeschlagen" #: .././mkfs/proto.c:481 #, fuzzy, c-format msgid "%s: Bad value %s for proto file %s\n" msgstr "falscher Wert für Fehlersuche %s\n" #: .././mkfs/proto.c:490 msgid "Inode pre-allocation failed" msgstr "Inode-Vorallokation fehlgeschlagen" #: .././mkfs/proto.c:500 msgid "Pre-allocated file creation failed" msgstr "Erzeugung der vorher zugeteiler Datei fehlgeschlagen" #: .././mkfs/proto.c:582 msgid "Directory creation failed" msgstr "Erstellung des Verzeichnisses fehlgeschlagen" #: .././mkfs/proto.c:603 #, fuzzy msgid "Unknown format" msgstr "Unbekanntes Inodeformat.\n" #: .././mkfs/proto.c:608 msgid "Error encountered creating file from prototype file" msgstr "Fehler beim Erstellen einer Datei aus der Prototyp-Datei gefunden" #: .././mkfs/proto.c:660 msgid "Realtime bitmap inode allocation failed" msgstr "Zuweisung des Echtzeit-Bitmap-Inodes fehlgeschlagen" #: .././mkfs/proto.c:677 msgid "Realtime summary inode allocation failed" msgstr "Allokation des Echtzeit-Zusammenfassungs-Inodes fehlgeschlagen" #: .././mkfs/proto.c:704 msgid "Allocation of the realtime bitmap failed" msgstr "Zuweisung des Echtzeit-Bitmaps fehlgeschlagen" #: .././mkfs/proto.c:717 msgid "Completion of the realtime bitmap failed" msgstr "Vervollständigung des Echtzeit-Bitmaps fehlgeschlagen" #: .././mkfs/proto.c:740 msgid "Allocation of the realtime summary failed" msgstr "Allokation der Echtzeit-Zusammenfassung fehlgeschlagen" #: .././mkfs/proto.c:752 msgid "Completion of the realtime summary failed" msgstr "Vervollständigung der Echtzeit-Zusammenfassung fehlgeschlagen" #: .././mkfs/proto.c:770 msgid "Error initializing the realtime space" msgstr "Fehler beim Initialisieren des Echtzeit-Raumes" #: .././mkfs/proto.c:775 msgid "Error completing the realtime space" msgstr "Fehler beim vervollständigen des Echtzeit-Raumes" #: .././mkfs/xfs_mkfs.c:752 #, c-format msgid "both data sunit and data swidth options must be specified\n" msgstr "sunit- und swidth-Optionen müssen beide angegeben werden\n" #: .././mkfs/xfs_mkfs.c:760 #, c-format msgid "both data su and data sw options must be specified\n" msgstr "su- und sw-Optionen müssen beide angegeben werden\n" #: .././mkfs/xfs_mkfs.c:767 #, c-format msgid "data su must be a multiple of the sector size (%d)\n" msgstr "su-Daten müssen ein Vielfaches der Sektorgröße (%d) sein\n" #: .././mkfs/xfs_mkfs.c:778 #, c-format msgid "" "data stripe width (%d) must be a multiple of the data stripe unit (%d)\n" msgstr "" "Datenstreifenbreite (%d) muss ein Vielfaches der Datenstreifeneinheit (%d)\n" "sein\n" #: .././mkfs/xfs_mkfs.c:791 .././mkfs/xfs_mkfs.c:797 #, c-format msgid "log stripe unit (%d) must be a multiple of the block size (%d)\n" msgstr "" "Protokoll-Stripe-Einheit (%d) muss ein Vielfaches der Blockgröße (%d) sein\n" #: .././mkfs/xfs_mkfs.c:817 #, fuzzy, c-format msgid "if -%s file then -%s name and -%s size are required\n" msgstr "wenn -d Datei, dann sind -d Name und -d Größe erforderlich\n" #: .././mkfs/xfs_mkfs.c:823 #, fuzzy, c-format msgid "No device name specified\n" msgstr "" " externes Protokollgerät nicht angegeben\n" "\n" #: .././mkfs/xfs_mkfs.c:835 #, fuzzy, c-format msgid "Error accessing specified device %s: %s\n" msgstr " Gerät %s kann nicht geöffnet werden: %s\n" #: .././mkfs/xfs_mkfs.c:843 #, c-format msgid "%s: Use the -f option to force overwrite.\n" msgstr "%s: Benutzen Sie die -f-Option um das Überschreiben zu erzwingen.\n" #: .././mkfs/xfs_mkfs.c:864 #, c-format msgid "specified \"-%s file\" on a block device %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:872 #, fuzzy, c-format msgid "specified device %s not a file or block device\n" msgstr "erwartete Stufe %d hat %d in btbno-Block %d/%d\n" #: .././mkfs/xfs_mkfs.c:903 #, c-format msgid "log size %lld is not a multiple of the log stripe unit %d\n" msgstr "Protokollgröße %lld ist kein Vielfaches der Datenstreifeneinheit %d)\n" #: .././mkfs/xfs_mkfs.c:931 #, c-format msgid "Due to stripe alignment, the internal log size (%lld) is too large.\n" msgstr "" "Aufgrund der Streifenausrichtung ist die interne Protokollgröße (%lld) zu " "groß\n" #: .././mkfs/xfs_mkfs.c:933 #, c-format msgid "Must fit within an allocation group.\n" msgstr "Muss in eine Allokationsgruppe passen.\n" #: .././mkfs/xfs_mkfs.c:944 #, c-format msgid "log size %lld blocks too small, minimum size is %d blocks\n" msgstr "Protokollgröße %lld Blöcke zu klein, Mindestgröße ist %d Blöcke\n" #: .././mkfs/xfs_mkfs.c:950 #, c-format msgid "log size %lld blocks too large, maximum size is %lld blocks\n" msgstr "Protokollgröße %lld Blöcke zu groß, maximale Größe ist %lld Blöcke\n" #: .././mkfs/xfs_mkfs.c:956 #, c-format msgid "log size %lld bytes too large, maximum size is %lld bytes\n" msgstr "Protokollgröße %lld Bytes zu groß, maximale Größe ist %lld Bytes\n" #: .././mkfs/xfs_mkfs.c:993 #, fuzzy, c-format msgid "agsize (%lld blocks) too small, need at least %lld blocks\n" msgstr "agsize (%lldb) zu klein, es werden mindestens %lld Blöcke benötigt\n" #: .././mkfs/xfs_mkfs.c:1001 #, fuzzy, c-format msgid "agsize (%lld blocks) too big, maximum is %lld blocks\n" msgstr "agsize (%lldb) zu groß, maximal %lld Blöcke\n" #: .././mkfs/xfs_mkfs.c:1009 #, fuzzy, c-format msgid "agsize (%lld blocks) too big, data area is %lld blocks\n" msgstr "agsize (%lldb) zu groß, Datenbereich hat %lld Blöcke\n" #: .././mkfs/xfs_mkfs.c:1016 #, c-format msgid "too many allocation groups for size = %lld\n" msgstr "zu viele Allokations-Gruppen für Größe = %lld\n" #: .././mkfs/xfs_mkfs.c:1018 #, c-format msgid "need at most %lld allocation groups\n" msgstr "es werden höchstens %lld Allokations-Gruppen benötigt\n" #: .././mkfs/xfs_mkfs.c:1026 #, c-format msgid "too few allocation groups for size = %lld\n" msgstr "zu wenige Allokations-Gruppen für Größe = %lld\n" #: .././mkfs/xfs_mkfs.c:1028 #, c-format msgid "need at least %lld allocation groups\n" msgstr "es werden mindestens %lld Allokations-Gruppen benötigt\n" #: .././mkfs/xfs_mkfs.c:1041 #, c-format msgid "last AG size %lld blocks too small, minimum size is %lld blocks\n" msgstr "letzte AG-Größe %lld Blöcke zu klein, Mindestgröße ist %lld Blöcke\n" #: .././mkfs/xfs_mkfs.c:1052 #, c-format msgid "%lld allocation groups is too many, maximum is %lld\n" msgstr "%lld Allokations-Gruppen sind zu viel, Maximum ist %lld\n" #: .././mkfs/xfs_mkfs.c:1082 #, c-format msgid "error reading existing superblock -- failed to memalign buffer\n" msgstr "" "Fehler beim Lesen des bestehenden Superblocks -- memalign des Puffers\n" "fehlgeschlagen\n" #: .././mkfs/xfs_mkfs.c:1097 #, fuzzy, c-format msgid "error reading existing superblock: %s\n" msgstr "Fehler beim Lesen des primären Superblocks\n" #: .././mkfs/xfs_mkfs.c:1267 #, fuzzy, c-format msgid "Illegal value %s for -%c %s option. %s\n" msgstr "Unerlaubter Wert %s für -%s-Option\n" #: .././mkfs/xfs_mkfs.c:1342 #, c-format msgid "" "Option -%c %s has undefined minval/maxval.Can't verify value range. This is " "a bug.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1368 #, fuzzy msgid "value is too small" msgstr "\tIst das Ziel »%s« zu klein?\n" #: .././mkfs/xfs_mkfs.c:1370 #, fuzzy msgid "value is too large" msgstr "Blockgröße %llu zu groß\n" #: .././mkfs/xfs_mkfs.c:1372 msgid "value must be a power of 2" msgstr "" #: .././mkfs/xfs_mkfs.c:1932 #, c-format msgid "extra arguments\n" msgstr "Extra-Argumente\n" #: .././mkfs/xfs_mkfs.c:1949 #, c-format msgid "illegal block size %d\n" msgstr "unerlaubte Blockgröße %d\n" #: .././mkfs/xfs_mkfs.c:1954 #, c-format msgid "Minimum block size for CRC enabled filesystems is %d bytes.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1959 #, c-format msgid "cannot disable ftype with crcs enabled\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2013 #, c-format msgid "specified blocksize %d is less than device physical sector size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2016 #, fuzzy, c-format msgid "switching to logical sector size %d\n" msgstr "unerlaubte Sektorgröße %d\n" #: .././mkfs/xfs_mkfs.c:2034 #, c-format msgid "illegal sector size %d\n" msgstr "unerlaubte Sektorgröße %d\n" #: .././mkfs/xfs_mkfs.c:2037 #, fuzzy, c-format msgid "block size %d cannot be smaller than logical sector size %d\n" msgstr "Protokollgröße %lld ist kein Vielfaches der Datenstreifeneinheit %d)\n" #: .././mkfs/xfs_mkfs.c:2042 #, fuzzy, c-format msgid "illegal sector size %d; hw sector is %d\n" msgstr "unerlaubte Sektorgröße %d\n" #: .././mkfs/xfs_mkfs.c:2048 #, c-format msgid "illegal log sector size %d\n" msgstr "unerlaubte Protokoll-Bereichs-Größe %d\n" #: .././mkfs/xfs_mkfs.c:2064 .././mkfs/xfs_mkfs.c:2194 #, c-format msgid "Minimum inode size for CRCs is %d bytes\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2072 #, c-format msgid "Inodes always aligned for CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2079 #, c-format msgid "Lazy superblock counted always enabled for CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2086 #, c-format msgid "V2 logs always enabled for CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2093 #, c-format msgid "V2 attribute format always enabled on CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2101 #, c-format msgid "32 bit Project IDs always enabled on CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2116 #, c-format msgid "finobt not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2123 #, c-format msgid "sparse inodes not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2130 #, c-format msgid "rmapbt not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2137 #, c-format msgid "reflink not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2146 #, c-format msgid "rmapbt not supported with realtime devices\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2154 #, c-format msgid "illegal directory block size %d\n" msgstr "unerlaubte Verzeichnis-Block-Größe %d\n" #: .././mkfs/xfs_mkfs.c:2173 #, c-format msgid "illegal data length %lld, not a multiple of %d\n" msgstr "unerlaubte Datenlänge %lld, kein Vielfaches von %d\n" #: .././mkfs/xfs_mkfs.c:2179 #, c-format msgid "warning: data length %lld not a multiple of %d, truncated to %lld\n" msgstr "" "Warnung: Datenlänge %lld ist kein Vielfaches von %d, wurde auf %lld gekürzt\n" #: .././mkfs/xfs_mkfs.c:2205 #, c-format msgid "illegal log length %lld, not a multiple of %d\n" msgstr "unerlaubte Protokolllänge %lld, kein Vielfaches von %d\n" #: .././mkfs/xfs_mkfs.c:2212 #, c-format msgid "warning: log length %lld not a multiple of %d, truncated to %lld\n" msgstr "" "Warnung: Protokolllänge %lld ist kein Vielfaches von %d, wurde auf\n" "%lld gekürzt\n" #: .././mkfs/xfs_mkfs.c:2222 #, c-format msgid "illegal rt length %lld, not a multiple of %d\n" msgstr "unerlaubte rt-Länge %lld, kein Vielfaches von %d\n" #: .././mkfs/xfs_mkfs.c:2229 #, c-format msgid "warning: rt length %lld not a multiple of %d, truncated to %lld\n" msgstr "" "Warnung: rt-Länge %lld ist kein Vielfaches von %d, wurde auf %lld gekürzt\n" #: .././mkfs/xfs_mkfs.c:2242 #, c-format msgid "illegal rt extent size %lld, not a multiple of %d\n" msgstr "unerlaubte rt-Erweiterungs-Länge %lld, kein Vielfaches von %d\n" #: .././mkfs/xfs_mkfs.c:2285 #, c-format msgid "illegal inode size %d\n" msgstr "unerlaubte Inode-Größe %d\n" #: .././mkfs/xfs_mkfs.c:2290 #, c-format msgid "allowable inode size with %d byte blocks is %d\n" msgstr "zulässige Inode-Größe mit %d Byte-Blocks ist %d\n" #: .././mkfs/xfs_mkfs.c:2294 #, c-format msgid "allowable inode size with %d byte blocks is between %d and %d\n" msgstr "zulässige Inode-Größe mit %d Byte-Blocks liegt zwischen %d und %d\n" #: .././mkfs/xfs_mkfs.c:2302 #, c-format msgid "log stripe unit specified, using v2 logs\n" msgstr "logische Stripe-Einheit angegeben, v2-Protokolle werden benutzt\n" #: .././mkfs/xfs_mkfs.c:2317 #, c-format msgid "no device name given in argument list\n" msgstr "in der Argumenten-Liste ist kein Gerätename angegeben\n" #: .././mkfs/xfs_mkfs.c:2353 msgid "internal log" msgstr "Internes Protokoll" #: .././mkfs/xfs_mkfs.c:2355 msgid "volume log" msgstr "Datenträger-Protokoll" #: .././mkfs/xfs_mkfs.c:2357 #, c-format msgid "no log subvolume or internal log\n" msgstr "kein Unter-Datenträger-Protokoll oder internes Protokoll\n" #: .././mkfs/xfs_mkfs.c:2364 msgid "volume rt" msgstr "Datenträger rt" #: .././mkfs/xfs_mkfs.c:2369 #, c-format msgid "" "size %s specified for data subvolume is too large, maximum is %lld blocks\n" msgstr "" "für den Unter-Datenträger angegebene Größe %s ist zu groß, Maximum ist %lld\n" "Blöcke\n" #: .././mkfs/xfs_mkfs.c:2376 #, c-format msgid "can't get size of data subvolume\n" msgstr "Datenträgergröße kann nicht ermittelt werden\n" #: .././mkfs/xfs_mkfs.c:2381 #, c-format msgid "size %lld of data subvolume is too small, minimum %d blocks\n" msgstr "" "für den Unter-Datenträger angegebene Größe %lld ist zu klein, Minimum\n" "ist %d Blöcke\n" #: .././mkfs/xfs_mkfs.c:2388 #, c-format msgid "can't have both external and internal logs\n" msgstr "man kann nicht beides, externe und interne Protokolle, haben\n" #: .././mkfs/xfs_mkfs.c:2392 #, c-format msgid "data and log sector sizes must be equal for internal logs\n" msgstr "" "Daten- und Protokollbereichs-Größe müssen für interne Protokolle gleich " "sein\n" #: .././mkfs/xfs_mkfs.c:2398 #, c-format msgid "" "Warning: the data subvolume sector size %u is less than the sector size \n" "reported by the device (%u).\n" msgstr "" "Warnung: Die Datenträger-Sektorengröße %u ist kleiner als die Sektorengröße\n" "die vom Gerät (%u) vermeldet wurde.\n" #: .././mkfs/xfs_mkfs.c:2404 #, c-format msgid "" "Warning: the log subvolume sector size %u is less than the sector size\n" "reported by the device (%u).\n" msgstr "" "Warnung: Die Datenträger-Protokoll-Sektorengröße %u ist kleiner als die\n" "Sektorengröße die vom Gerät (%u) vermeldet wurde.\n" #: .././mkfs/xfs_mkfs.c:2410 #, c-format msgid "" "Warning: the realtime subvolume sector size %u is less than the sector size\n" "reported by the device (%u).\n" msgstr "" "Warnung: Die Datenträger-Echtzeit-Sektorengröße %u ist kleiner als die\n" "Sektorengröße die vom Gerät (%u) vermeldet wurde.\n" #: .././mkfs/xfs_mkfs.c:2417 #, c-format msgid "" "size %s specified for rt subvolume is too large, maximum is %lld blocks\n" msgstr "" "für den rt-Unter-Datenträger angegebene Größe %s ist zu groß, Maximum ist\n" "%lld Blöcke\n" #: .././mkfs/xfs_mkfs.c:2425 #, c-format msgid "size specified for non-existent rt subvolume\n" msgstr "Größe für nicht existierenden rt-Unter-Datenträger angegeben\n" #: .././mkfs/xfs_mkfs.c:2440 #, c-format msgid "" "%s: Specified data stripe unit %d is not the same as the volume stripe unit " "%d\n" msgstr "" "%s: Angegebene Daten-Stripe-Einheit %d ist nicht die gleiche wie die\n" "Datenträger-Stripe-Einheit %d\n" #: .././mkfs/xfs_mkfs.c:2447 #, c-format msgid "" "%s: Specified data stripe width %d is not the same as the volume stripe " "width %d\n" msgstr "" "%s: Angegebene Daten-Stripe-Breite %d ist nicht die gleiche wie die\n" "Datenträger-Stripe-Breite %d\n" #: .././mkfs/xfs_mkfs.c:2465 #, c-format msgid "agsize (%lld) not a multiple of fs blk size (%d)\n" msgstr "agsize (%lld) kein Vielfaches der »fs blk«-Größe (%d)\n" #: .././mkfs/xfs_mkfs.c:2515 #, c-format msgid "agsize rounded to %lld, swidth = %d\n" msgstr "agsize gerundet auf %lld, swidth = %d\n" #: .././mkfs/xfs_mkfs.c:2547 #, c-format msgid "" "Warning: AG size is a multiple of stripe width. This can cause performance\n" "problems by aligning all AGs on the same disk. To avoid this, run mkfs " "with\n" "an AG size that is one stripe unit smaller, for example %llu.\n" msgstr "" "Warnung: AG-Größe ist ein Vielfaches der Stripe-Breite. Dies kann zu\n" "Performance-Problem führen bei Ausrichtung aller AGs auf die gleiche\n" "Platte. Um dies zu vermeiden, führen Sie mkfs mit einer AG-Größe aus, die\n" "ein Stripe kleiner ist, zum Beispiel %llu.\n" #: .././mkfs/xfs_mkfs.c:2572 #, c-format msgid "" "%s: Stripe unit(%d) or stripe width(%d) is not a multiple of the block size" "(%d)\n" msgstr "" "%s: Stripe-Einheit (%d) oder Stripe-Breite (%d) ist kein Vielfaches der\n" "Blockgröße (%d)\n" #: .././mkfs/xfs_mkfs.c:2613 #, c-format msgid "log stripe unit (%d bytes) is too large (maximum is 256KiB)\n" msgstr "Protokoll-Stripe-Einheit (%d Bytes) ist zu groß (Maximum ist 256KiB)\n" #: .././mkfs/xfs_mkfs.c:2616 #, c-format msgid "log stripe unit adjusted to 32KiB\n" msgstr "Protokoll-Stripe-Einheit angepasst auf 32KiB\n" #: .././mkfs/xfs_mkfs.c:2632 #, c-format msgid "" "size %s specified for log subvolume is too large, maximum is %lld blocks\n" msgstr "" "für den Protokoll-Unter-Datenträger angegebene Größe %s ist zu groß, " "Maximum\n" "ist %lld Blöcke\n" #: .././mkfs/xfs_mkfs.c:2639 #, c-format msgid "size specified for non-existent log subvolume\n" msgstr "Größe für nicht existierenden Protokoll-Unter-Datenträger angegeben\n" #: .././mkfs/xfs_mkfs.c:2642 #, c-format msgid "size %lld too large for internal log\n" msgstr "Größe %lld zu groß für internes Protokoll\n" #: .././mkfs/xfs_mkfs.c:2720 #, c-format msgid "internal log size %lld too large, must fit in allocation group\n" msgstr "" "interne Protokollgröße %lld zu groß, muss in die Allokationsgruppe\n" "passen\n" #: .././mkfs/xfs_mkfs.c:2728 #, c-format msgid "log ag number %d too large, must be less than %lld\n" msgstr "Protokoll-»ag«-Nummer %d zu groß, muss kleiner als %lld sein\n" #: .././mkfs/xfs_mkfs.c:2758 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" msgstr "" "Metadaten =%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u\n" "Daten =%-22s bsize=%-6u Blöcke=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "Benennung =Version %-14u bsize=%-6u ascii-ci=%d\n" "Protokoll =%-22s bsize=%-6d Blöcke=%lld, Version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "Echtzeit =%-22s extsz=%-6d Blöcke=%lld, rtextents=%lld\n" #: .././mkfs/xfs_mkfs.c:2876 #, c-format msgid "%s: Growing the data section failed\n" msgstr "%s: Wachsen des Datenbereiches fehlgeschlagen\n" #: .././mkfs/xfs_mkfs.c:2906 #, c-format msgid "%s: filesystem failed to initialize\n" msgstr "%s: Initialisierung des Dateisystems fehlgeschlagen\n" #: .././mkfs/xfs_mkfs.c:3319 #, c-format msgid "%s: root inode created in AG %u, not AG 0\n" msgstr "%s: Wurzel-Inode in AG %u erstellt, nicht AG 0\n" #: .././mkfs/xfs_mkfs.c:3385 #, c-format msgid "Cannot specify both -%c %s and -%c %s\n" msgstr "Beides kann nicht angegeben werden -%c %s und -%c %s\n" #: .././mkfs/xfs_mkfs.c:3396 #, c-format msgid "Illegal value %s for -%s option\n" msgstr "Unerlaubter Wert %s für -%s-Option\n" #: .././mkfs/xfs_mkfs.c:3413 #, c-format msgid "-%c %s option requires a value\n" msgstr "»-%c %s«-Option benötigt einen Wert\n" #: .././mkfs/xfs_mkfs.c:3426 .././repair/xfs_repair.c:168 #, c-format msgid "option respecified\n" msgstr "Option wieder angegeben\n" #: .././mkfs/xfs_mkfs.c:3435 .././repair/xfs_repair.c:175 #, c-format msgid "unknown option -%c %s\n" msgstr "unbekannte Option -%c %s\n" #: .././mkfs/xfs_mkfs.c:3461 #, c-format msgid "Blocksize must be provided prior to using 'b' suffix.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3470 #, c-format msgid "Sectorsize must be specified prior to using 's' suffix.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3505 #, fuzzy, c-format msgid "" "Usage: %s\n" "/* blocksize */\t\t[-b log=n|size=num]\n" "/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n" "/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num|noalign),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* force overwrite */\t[-f]\n" "/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n" "\t\t\t projid32bit=0|1,sparse=0|1]\n" "/* no discard */\t[-K]\n" "/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* label */\t\t[-L label (maximum 12 characters)]\n" "/* naming */\t\t[-n log=n|size=num,version=2|ci,ftype=0|1]\n" "/* no-op info only */\t[-N]\n" "/* prototype file */\t[-p fname]\n" "/* quiet */\t\t[-q]\n" "/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* sectorsize */\t[-s log=n|size=num]\n" "/* version */\t\t[-V]\n" "\t\t\tdevicename\n" " is required unless -d name=xxx is given.\n" " is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " is xxx (512 byte blocks).\n" msgstr "" "Aufruf: %s\n" "/* Blockgröße */\t\t[-b log=n|size=num]\n" "/* Unter-Datenträger */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* Inode-Größe */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2]\n" "/* Protokoll-Datenträger */\t[-l agnum=n,internal,size=num,\n" "\t\t\t logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* Aufschrift */\t\t[-L label (maximal 12 Zeichen)]\n" "/* Benennung */\t\t[-n log=n|size=num,version=2|ci]\n" "/* Prototyp-Datei */\t[-p fname]\n" "/* ohne Ausgabe */\t\t[-q]\n" "/* Echtzeit-Unter-Datenträger */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* Sektorengröße */\t[-s log=n|size=num]\n" "/* Version */\t\t[-V]\n" "\t\t\tdevicename\n" " wird benötigt, außer wenn -d name=xxx angegeben ist.\n" " is xxx (Bytes), xxxs (Sektoren), xxxb (fs Blöcke), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " ist xxx (512 Byte-Blöcke).\n" #: .././quota/edit.c:36 #, c-format msgid "" "\n" " modify quota limits for the specified user\n" "\n" " Example:\n" " 'limit bsoft=100m bhard=110m tanya\n" "\n" " Changes the soft and/or hard block limits, inode limits and/or realtime\n" " block limits that are currently being used for the specified user, group,\n" " or project. The filesystem identified by the current path is modified.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota limits\n" " -p -- modify project quota limits\n" " -u -- modify user quota limits\n" " The block limit values can be specified with a units suffix - accepted\n" " units are: k (kilobytes), m (megabytes), g (gigabytes), and t (terabytes).\n" " The user/group/project can be specified either by name or by number.\n" "\n" msgstr "" "\n" " Quota-Beschränkungen für den angegebenen Anwender ändern\n" "\n" " Beispiel:\n" " 'limit bsoft=100m bhard=110m tanya\n" "\n" "Ändert die Soft-/Hard-Block-Quotas, Inode-Quotas und/oder\n" "Echtzeit-Block-Quotas, die derzeit für den angegebenen Anwender, die\n" "Gruppe oder das Projekt benutzt werden. Das durch den Pfad erkannte\n" "Dateisystem wird geändert.\n" " -d -- setzt die Standardwerte, die benutzt werden, wenn eine Datei neu\n" " erstellt wurde\n" " -g -- ändert Gruppen-Quota-Beschränkungen\n" " -p -- ändert Projekt-Quota-Beschränkungen\n" " -u -- ändert Anwender-Quota-Beschränkungen\n" " Die -block-Quota-Werte können mit einem einheitlichen Suffix\n" " angegeben werden - akzeptierte Einheiten sind: k (Kilobyte),\n" " m (Megabyte), g (Gigabyte) und t (Terabyte). Gruppe, Anwender, Projekt\n" " kann entweder durch Name oder Nummer angegeben werden.\n" "\n" #: .././quota/edit.c:59 #, c-format msgid "" "\n" " modify quota enforcement timeout for the current filesystem\n" "\n" " Example:\n" " 'timer -i 3days'\n" " (soft inode limit timer is changed to 3 days)\n" "\n" " Changes the timeout value associated with the block limits, inode limits\n" " and/or realtime block limits for all users, groups, or projects on the\n" " current filesystem.\n" " As soon as a user consumes the amount of space or number of inodes set as\n" " the soft limit, a timer is started. If the timer expires and the user is\n" " still over the soft limit, the soft limit is enforced as the hard limit.\n" " The default timeout is 7 days.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota timer\n" " -p -- modify project quota timer\n" " -u -- modify user quota timer\n" " -b -- modify the blocks-used timer\n" " -i -- modify the inodes-used timer\n" " -r -- modify the blocks-used timer for the (optional) realtime subvolume\n" " The timeout value is specified as a number of seconds, by default.\n" " However, a suffix may be used to alternatively specify minutes (m),\n" " hours (h), days (d), or weeks (w) - either the full word or the first\n" " letter of the word can be used.\n" "\n" msgstr "" "\n" " Zeitüberschreitung des Erzwingens von Quota-Größen für das derzeitige\n" " Dateisystem ändern\n" "\n" " Beispiel:\n" " 'timer -i 3days'\n" " (weiche Inode-Zeitbeschränkung wird auf drei Tage geändert)\n" "\n" " Ändert den Wert der Zeitbeschränkung, der sich auf Block-, Inode und/oder\n" " Echtzeit-Blockbeschränkungen für alle Nutzer, Gruppen oder Projekte auf " "dem\n" " derzeitigen Dateisystem bezieht.\n" " Sobald ein Anwender einen Anteil am Speicher oder den Inodes belegt, der\n" " als weiche Beschränkung gesetzt ist, wird ein Zeitnehmer gestartet. Wenn\n" " der Zeitnehmer abläuft und der Anwender ist immer noch über der weichen\n" " Beschränkung, wird die weiche Beschränkung als harte Beschränkung\n" " erzwungen.\n" " Die Standard-Zeitbeschränkung beträgt sieben Tage.\n" " -d -- setzt die Standardwerte, wird benutzt, wenn zum ersten Mal eine " "Datei\n" " erstellt wird\n" " -g -- ändert Gruppen-Quota-Zeitnehmer\n" " -p -- ändert Projekt-Quota-Zeitnehmer\n" " -u -- ändert Anwender-Quota-Zeitnehmer\n" " -b -- ändert den für Blöcke benutzten Zeitnehmer\n" " -i -- ändert den für Inodes benutzten Zeitnehmer\n" " -r -- ändert den für Blöcke benutzten Zeitnehmer für den (optionalen)\n" " Echtzeit-Unterdatenträger\n" " Der Zeitüberschreitungswert ist standardmäßig als eine Anzahl von Sekunden\n" " angegeben. Allerdings kann eine Erweiterung angegeben werden um alternativ\n" " Minuten (m), Stunden (h), Tage (d) oder Wochen (w) anzugeben -sowohl das\n" " ganze Wort als auch der erste Buchstabe können benutzt werden.\n" "\n" #: .././quota/edit.c:91 #, c-format msgid "" "\n" " modify the number of quota warnings sent to the specified user\n" "\n" " Example:\n" " 'warn 2 jimmy'\n" " (tell the quota system that two warnings have been sent to user jimmy)\n" "\n" " Changes the warning count associated with the block limits, inode limits\n" " and/or realtime block limits for the specified user, group, or project.\n" " When a user has been warned the maximum number of times allowed, the soft\n" " limit is enforced as the hard limit. It is intended as an alternative to\n" " the timeout system, where the system administrator updates a count of the\n" " number of warnings issued to people, and they are penalised if the " "warnings\n" " are ignored.\n" " -d -- set maximum warning count, which triggers soft limit enforcement\n" " -g -- set group quota warning count\n" " -p -- set project quota warning count\n" " -u -- set user quota warning count\n" " -b -- set the blocks-used warning count\n" " -i -- set the inodes-used warning count\n" " -r -- set the blocks-used warn count for the (optional) realtime subvolume\n" " The user/group/project can be specified either by name or by number.\n" "\n" msgstr "" "\n" " Anzahl der Quota-Warnungen ändern, die zum angegebenen Anwender\n" " gesandt werden\n" "\n" " Beispiel:\n" " 'warn 2 Hans'\n" " (teilt dem Quota-System mit, dass zwei Warnungen an den Anwender Hans\n" " gesandt wurden)\n" " Ändert die Anzahl der Warnungen, die sich auf Block-, Inode und/oder\n" " Echtzeit-Blockbeschränkungen für den angegebenen Nutzer, die Gruppe oder\n" " das Projekt auf dem derzeitigen Dateisystem beziehen.\n" " Wenn ein Anwender die maximale Anzahl von Warnungen erhalten hat, wird die\n" " weiche Beschränkung zu einer harten Beschränkung. Es ist als Alternative\n" " zum Zeitbeschränkungs-System gedacht, bei dem der Systemadministrator die\n" " Anzahl der Warnungen aktualisiert, den Leuten ausgegeben werden und sie\n" " werden bestraft, wenn die Warnungen ignoriert werden.\n" " -d -- maximale Anzahl der Warnungen setzen, die weiche Beschränkungen\n" " auslösen.\n" " -g -- Anzahl der Warnungen für Gruppen-Quotas setzen\n" " -p -- Anzahl der Warnungen für Projekt-Quotas setzen\n" " -u -- Anzahl der Warnungen für Anwender-Quotas setzen\n" " -b -- Anzahl der Warnungen, die von Böcken benutzt werden, setzen\n" " -i -- Anzahl der Warnungen, die von Inodes benutzt werden, setzen\n" " -r -- Anzahl der Warnungen, die von Böcken benutzt werden, für einen\n" " (optionalen) Echtzeit-Unter-Datenträger setzen\n" " Nutzer/Gruppe/Projekt können entweder durch Name oder durch Nummer\n" " angegeben werden\n" "\n" #: .././quota/edit.c:145 #, c-format msgid "%s: cannot set limits: %s\n" msgstr "%s: Beschränkungen können nicht gesetzt werden: %s\n" #: .././quota/edit.c:166 .././quota/edit.c:584 #, c-format msgid "%s: invalid user name: %s\n" msgstr "%s: ungültiger Anwendername: %s\n" #: .././quota/edit.c:189 .././quota/edit.c:601 #, c-format msgid "%s: invalid group name: %s\n" msgstr "%s: ungültiger Gruppenname: %s\n" #: .././quota/edit.c:212 .././quota/edit.c:618 #, c-format msgid "%s: invalid project name: %s\n" msgstr "%s: ungültiger Projektname: %s\n" #: .././quota/edit.c:237 #, fuzzy, c-format msgid "%s: Error: could not parse size %s.\n" msgstr "%s: %s kann nicht geöffnet werden: %s\n" #: .././quota/edit.c:243 #, c-format msgid "%s: Warning: `%s' in quota blocks is 0 (unlimited).\n" msgstr "%s: Warnung: »%s« in Quota-Blöcken ist 0 (unbegrenzt).\n" #: .././quota/edit.c:332 #, c-format msgid "%s: unrecognised argument %s\n" msgstr "%s: nicht erkanntes Argument %s\n" #: .././quota/edit.c:339 #, c-format msgid "%s: cannot find any valid arguments\n" msgstr "%s: es wurden keine gültigen Argumente gefunden\n" #: .././quota/edit.c:457 #, c-format msgid "%s: fopen on %s failed: %s\n" msgstr "%s: fopen von %s fehlgeschlagen: %s\n" #: .././quota/edit.c:489 #, c-format msgid "%s: cannot set timer: %s\n" msgstr "%s: Zeitnehmer kann nicht eingestellt werden: %s\n" #: .././quota/edit.c:568 #, c-format msgid "%s: cannot set warnings: %s\n" msgstr "%s: Warnungen können nicht gesetzt werden: %s\n" #: .././quota/edit.c:709 #, fuzzy msgid "[-g|-p|-u] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" msgstr "[-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" #: .././quota/edit.c:710 msgid "modify quota limits" msgstr "Quota-Beschränkungen ändern" #: .././quota/edit.c:718 .././quota/report.c:33 .././quota/report.c:768 #, fuzzy msgid "[-g|-p|-u] [-f file]" msgstr "[-gpu] [-f Datei]" #: .././quota/edit.c:719 msgid "restore quota limits from a backup file" msgstr "Quota-Beschränkungen aus einer Sicherungsdatei wiederherstellen" #: .././quota/edit.c:726 #, fuzzy msgid "[-bir] [-g|-p|-u] value" msgstr "[-bir] [-gpu] Ert -d|id|name" #: .././quota/edit.c:727 #, fuzzy msgid "set quota enforcement timeouts" msgstr "ausgeben/setzen von Zeitbeschränkungen zum Erzwingen von Quotas" #: .././quota/edit.c:735 #, fuzzy msgid "[-bir] [-g|-p|-u] value -d|id|name" msgstr "[-bir] [-gpu] Ert -d|id|name" #: .././quota/edit.c:736 msgid "get/set enforcement warning counter" msgstr "ausgeben/setzen des Warnungs-Zählers zum Erzwingen" #: .././quota/free.c:30 #, c-format msgid "" "\n" " reports the number of free disk blocks and inodes\n" "\n" " This command reports the number of total, used, and available disk blocks.\n" " It can optionally report the same set of numbers for inodes and realtime\n" " disk blocks, and will report on all known XFS filesystem mount points and\n" " project quota paths by default (see 'print' command for a list).\n" " -b -- report the block count values\n" " -i -- report the inode count values\n" " -r -- report the realtime block count values\n" " -h -- report in a human-readable format\n" " -N -- suppress the header from the output\n" "\n" msgstr "" "\n" " meldet die Anzahl freier Blöcke und Inodes\n" "\n" " Dieser Befehl meldet die Anzahl von allen, den benutzten und den\n" " verfügbaren Plattenblöcken. Er kann wahlweise den gleichen Satz von\n" " Inode-Nummern und Echtzeit-Plattenblöcken melden sowie alle bekannten\n" " XFS-Dateisystem-Einhängepunkte und Standard-Projekt-Quota-Pfade\n" " (»print«-Befehl gibt eine Liste aus).\n" " -b -- Werte für die Block-Anzahl melden\n" " -i -- Werte für die Inode-Anzahl melden\n" " -r -- Werte für die Echtzeit-Block-Anzahl melden\n" " -h -- in einem lesbaren Format ausgeben\n" " -N -- in der Ausgabe die Kopfdaten unterdrücken\n" "\n" #: .././quota/free.c:171 #, c-format msgid "%s: project quota flag not set on %s\n" msgstr "%s: Projekt-Quota-Markierung ist nicht auf %s gesetzt\n" #: .././quota/free.c:180 #, c-format msgid "%s: project ID %u (%s) doesn't match ID %u (%s)\n" msgstr "%s: Projekt-ID %u (%s) entspricht nicht ID %u (%s)\n" #: .././quota/free.c:247 #, c-format msgid "Filesystem " msgstr "Dateisystem" #: .././quota/free.c:247 #, c-format msgid "Filesystem " msgstr "Dateisystem" #: .././quota/free.c:250 #, c-format msgid " Size Used Avail Use%%" msgstr " Größe Benutzt Verfügbar Benutzung%%" #: .././quota/free.c:251 #, c-format msgid " 1K-blocks Used Available Use%%" msgstr " 1K-Blöcke Benutzt Verfügbar Benutzung%%" #: .././quota/free.c:254 #, c-format msgid " Inodes Used Free Use%%" msgstr " Inodes Benutzt Frei Use%%" #: .././quota/free.c:255 #, c-format msgid " Inodes IUsed IFree IUse%%" msgstr " Inodes IUsed IFree IUse%%" #: .././quota/free.c:256 #, c-format msgid " Pathname\n" msgstr " Pfadname\n" #: .././quota/free.c:388 #, fuzzy msgid "[-bir] [-hN] [-f file]" msgstr "[-bir] [-hn] [-f Datei]" #: .././quota/free.c:389 msgid "show free and used counts for blocks and inodes" msgstr "Anzahl freier und benutzter Blöcke und Inodes anzeigen" #: .././quota/init.c:49 #, fuzzy, c-format msgid "Usage: %s [-V] [-x] [-f] [-p prog] [-c cmd]... [-d project]... [path]\n" msgstr "Aufruf: %s [-p Programm] [-c Befehl]... [-d Projekt]... [Pfad]\n" #: .././quota/init.c:130 #, fuzzy, c-format msgid "%s: command is for XFS filesystems only\n" msgstr "Fremde Datei aktiv, der %s-Befehl ist nur für das XFS-Dateisystem\n" #: .././quota/init.c:137 #, c-format msgid "%s: foreign filesystem. Invoke xfs_quota with -f to enable.\n" msgstr "" #: .././quota/path.c:39 #, fuzzy, c-format msgid "%s%sFilesystem Pathname\n" msgstr "%sDateisystem Pfadname\n" #: .././quota/path.c:40 msgid " " msgstr " " #: .././quota/path.c:41 #, fuzzy msgid " " msgstr " " #: .././quota/path.c:44 #, c-format msgid "%c%03d%c " msgstr "%c%03d%c " #: .././quota/path.c:47 #, c-format msgid "%-19s %s" msgstr "%-19s %s" #: .././quota/path.c:50 #, c-format msgid " (project %u" msgstr " (Projekt %u" #: .././quota/path.c:52 #, c-format msgid ", %s" msgstr ", %s" #: .././quota/path.c:117 #, c-format msgid "No paths are available\n" msgstr "Es sind keine Pfade verfügbar\n" #: .././quota/path.c:145 msgid "set current path, or show the list of paths" msgstr "aktuellen Pfad setzen oder Pfadliste anzeigen" #: .././quota/path.c:153 msgid "list known mount points and projects" msgstr "bekannte Einhängepunkte und Projekte auflisten" #: .././quota/project.c:45 #, c-format msgid "" "\n" " list projects or setup a project tree for tree quota management\n" "\n" " Example:\n" " 'project -c logfiles'\n" " (match project 'logfiles' to a directory, and setup the directory tree)\n" "\n" " Without arguments, report all projects found in the /etc/projects file.\n" " The project quota mechanism in XFS can be used to implement a form of\n" " directory tree quota, where a specified directory and all of the files\n" " and subdirectories below it (i.e. a tree) can be restricted to using a\n" " subset of the available space in the filesystem.\n" "\n" " A managed tree must be setup initially using the -c option with a project.\n" " The specified project name or identifier is matched to one or more trees\n" " defined in /etc/projects, and these trees are then recursively descended\n" " to mark the affected inodes as being part of that tree - which sets inode\n" " flags and the project identifier on every file.\n" " Once this has been done, new files created in the tree will automatically\n" " be accounted to the tree based on their project identifier. An attempt to\n" " create a hard link to a file in the tree will only succeed if the project\n" " identifier matches the project identifier for the tree. The xfs_io " "utility\n" " can be used to set the project ID for an arbitrary file, but this can only\n" " be done by a privileged user.\n" "\n" " A previously setup tree can be cleared from project quota control through\n" " use of the -C option, which will recursively descend the tree, clearing\n" " the affected inodes from project quota control.\n" "\n" " The -c option can be used to check whether a tree is setup, it reports\n" " nothing if the tree is correct, otherwise it reports the paths of inodes\n" " which do not have the project ID of the rest of the tree, or if the inode\n" " flag is not set.\n" "\n" " The -p option can be used to manually specify project path without\n" " need to create /etc/projects file. This option can be used multiple times\n" " to specify multiple paths. When using this option only one projid/name can\n" " be specified at command line. Note that /etc/projects is also used if " "exists.\n" "\n" " The -d option allows to descend at most levels of " "directories\n" " below the command line arguments. -d 0 means only apply the actions\n" " to the top level of the projects. -d -1 means no recursion limit " "(default).\n" "\n" " The /etc/projid and /etc/projects file formats are simple, and described\n" " on the xfs_quota man page.\n" "\n" msgstr "" "\n" " Projekte auflisten oder einen Projektbaum für eine\n" " Baum-Quota-Verwaltung einrichten\n" "\n" " Beispiel:\n" " 'project -c Protokolldateien'\n" " (ordnet das Projekt »Protokolldateien« einem Verzeichnis zu und richtet\n" " den Verzeichnis-Baum ein)\n" "\n" " Ohne Argumente werden alle Projekte ausgegeben, die in der Datei\n" " /etc/projects gefunden werden.\n" " Der Projekt-Quota-Mechanismus von XFS kann benutzt werden um eine\n" " Form von Verzeichnis-Baum-Quotas umzusetzen, bei der ein angegebenes\n" " Verzeichnis und alle Dateien und Unterverzeichnisse unterhalb (z.B. ein \n" " Baum) darauf beschränkt werden können, eine Teilmenge des verfügbaren\n" " Speichers des Dateisystems zu benutzen\n" "\n" " Ein verwalteter Baum muss zuerst unter Benutzung der Option -c mit\n" " einem Projekt eingerichtet werden. Der angebegenen Projektname oder\n" " Bezeichner passt zu einem oder mehreren in /etc/projects definierten\n" " Bäumen und in diese Bäume wird rekursiv abgestiegen um die betroffenen\n" " Inodes durch Setzen von Inode-Kennzeichnungen und dem\n" " Projekt-Bezeichner für jede Datei als Teil des Baumes zu markieren\n" " Wenn dies erledigt ist, werden neu im Baum erstellte Dateien\n" " automatisch auf dem Baum ausgewiesen, der auf ihrem Projekt-Bezeichner\n" " basiert. Ein Versuch einen harten Verweis zu einer Datei im Baum zu\n" " erstellen hat nur Erfolg, wenn der Projekt-Bezeichner mit dem\n" " Projekt-Bezeichner im Baum übereinstimmt. Das »xfs-io«-Programm kann\n" " benutzt werden um eine Projekt-ID für eine beliebige Datei zu setzen,\n" " aber dies kann nur durch einen berechtigen Anwender getan werden.\n" "\n" " Ein vorheriger Einrichtungs-Baum kann mit der Option -C aus der\n" " Projekt-Quota-Kontrolle entfernt werden, die rekursiv den Baum\n" " hinabsteigt und die betroffenen Inodes von der\n" " Projekt-Quota-Kontrolle befreit.\n" "\n" " Die »-c«-Option kann benutzt werden um prüfen, ob ein Baum eingerichtet\n" " ist. Sie gibt nichts aus, wenn der Baum korrekt ist. Andernfalls gibt\n" " sie den Pfad der Inodes an, die nicht die Projekt-ID des restlichen\n" " Baumes hat oder ob die Inode-Kennzeichnung nicht gesetzt ist.\n" "\n" "Die -Option -p kann benutzt werden, um manuell den Projektpfad\n" "anzugeben, ohne dass es nötig ist, die Datei /etc/projects zu erstellen.\n" "Diese Option kann mehrmals benutzt werden, um mehrere Pfade zu erstellen.\n" "Wenn diese Option benutzt wird kann nur eine projid/Name auf der\n" "Befehlszeile angegeben werden. Beachten Sie, dass außerden /etc/projects\n" "benutzt wird, wenn es existiert.\n" "\n" "Die -Option -d erlaub es, die meisten >Tiefe>-Stufen der\n" "Verzeichnisse unterhalb der Befehlszeilenargumente hinabzusteigen.\n" "-d 0 bedeutet, dass nur die Aktionen der obersten Stufe des Projekts\n" "abgefragt werden. d -1 bedeutet keine Rekursionsbeschränkung (Vorgabe).\n" "\n" " Die Formate der Dateien /etc/projid und /etc/projects sind einfach. Sie\n" " werden auf der »xfs_quota«-Handbuchseite beschrieben.\n" "\n" #: .././quota/project.c:108 .././quota/project.c:153 .././quota/project.c:200 #, c-format msgid "%s: cannot stat file %s\n" msgstr "%s: kann Status für »%s« nicht abfragen\n" #: .././quota/project.c:112 .././quota/project.c:157 .././quota/project.c:204 #, c-format msgid "%s: skipping special file %s\n" msgstr "%s: Spezialdatei %s wird übersprungen\n" #: .././quota/project.c:126 #, c-format msgid "%s - project identifier is not set (inode=%u, tree=%u)\n" msgstr "%s - Projekt-Bezeichner ist nicht gesetzt (Inode=%u, Baum=%u)\n" #: .././quota/project.c:130 #, c-format msgid "%s - project inheritance flag is not set\n" msgstr "%s - Projekt-Vererbungs-Markierung ist nicht gesetzt\n" #: .././quota/project.c:178 #, c-format msgid "%s: cannot clear project on %s: %s\n" msgstr "%s: Projekt auf %s kann nicht bereinigt werden: %s\n" #: .././quota/project.c:225 #, c-format msgid "%s: cannot set project on %s: %s\n" msgstr "%s: Projekt auf %s kann nicht gesetzt werden: %s\n" #: .././quota/project.c:240 #, c-format msgid "Checking project %s (path %s)...\n" msgstr "Projekt %s wird geprüft (Pfad %s)...\n" #: .././quota/project.c:244 #, c-format msgid "Setting up project %s (path %s)...\n" msgstr "Projekt-Pfad %s wird eingerichtet (Pfad %s)...\n" #: .././quota/project.c:248 #, c-format msgid "Clearing project %s (path %s)...\n" msgstr "Projekt-Pfad %s wird bereinigt (Pfad %s)...\n" #: .././quota/project.c:271 #, c-format msgid "" "Processed %d (%s and cmdline) paths for project %s with recursion depth %s " "(%d).\n" msgstr "" "Es wurden %d (%s und Befehlszeile) Pfade für Projekt %s mit\n" "Rekursionstiefe %s (%d) verarbeitet.\n" #: .././quota/project.c:274 msgid "infinite" msgstr "unendlich" #: .././quota/project.c:274 msgid "limited" msgstr "beschränkt" #: .././quota/project.c:319 #, c-format msgid "projects file \"%s\" doesn't exist\n" msgstr "Projektdatei »%s« existiert nicht\n" #: .././quota/project.c:326 #, c-format msgid "" "%s: only one projid/name can be specified when using -p , %d found.\n" msgstr "" "%s: Nur ein projid/Name kann angegeben werden, wenn -p benutzt\n" "wird, %d gefunden.\n" #: .././quota/project.c:336 #, fuzzy, c-format msgid "%s - no such project in %s or invalid project number\n" msgstr "%s - kein derartiges Projekt in %s\n" #: .././quota/project.c:353 msgid "[-c|-s|-C|-d |-p ] project ..." msgstr "[-c|-s|-C|-d |-p ] Projekt ..." #: .././quota/project.c:356 msgid "check, setup or clear project quota trees" msgstr "Projekt-Quota-Bäume prüfen, einrichten oder bereinigen " #: .././quota/quot.c:56 #, c-format msgid "" "\n" " display a summary of filesystem ownership\n" "\n" " -a -- summarise for all local XFS filesystem mount points\n" " -c -- display three columns giving file size in kilobytes, number of files\n" " of that size, and cumulative total of kilobytes in that size or\n" " smaller file. The last row is used as an overflow bucket and is the\n" " total of all files greater than 500 kilobytes.\n" " -v -- display three columns containing the number of kilobytes not\n" " accessed in the last 30, 60, and 90 days.\n" " -g -- display group summary\n" " -p -- display project summary\n" " -u -- display user summary\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n" msgstr "" "\n" " zeigt eine Übersicht des Eigentums am Dateisystem\n" "\n" " -a -- Summe für alle lokalen XFS-Einhängepunkte bilden\n" " -c -- zeigt drei Spalten mit Dateigröße in Kilobyte, Anzahl der Dateien\n" " mit dieser Größe und zusammengezählter Gesamtzahl von Kilobytes\n" " von Dateien mit dieser Größe oder kleinerer Dateien. Die letzte\n" " Reihe wird als Überlauf benutzt und besteht aus der Gesamtheit\n" " aller Dateien mit mehr als 500 Kilobyte.\n" " -v -- zeigt drei Spalten, die die Anzahl der Kilobytes enthalten, auf\n" " die in den letzten 30, 60 und 90 Tagen nicht zugegriffen wurde.\n" " -g -- Gruppen-Zusammenfassung anzeigen\n" " -p -- Projekt-Zusammenfassung anzeigen\n" " -u -- Benutzer-Zusammenfassung anzeigen\n" " -b -- Anzahl benutzter Blöcke anzeigen\n" " -i -- Anzahl benutzter Inodes anzeigen\n" " -r -- Anzahl benutzter Echtzeit-Blöcke anzeigen\n" " -n -- Übersetzung von Bezeichnern zu Namen überspringen, nur IDs\n" " ausgeben\n" " -N -- einleitende Kopfzeilen unterdrücken\n" " -f -- Ausgabe in eine Datei umleiten\n" " Der (optionale) Benutzer/Gruppe/Projekt an entweder durch Name oder\n" " Nummer (z.B. uid/gid/projid) angegeben werden.\n" "\n" #: .././quota/quot.c:221 #, c-format msgid "%s (%s) %s:\n" msgstr "%s (%s) %s:\n" #: .././quota/quot.c:297 #, c-format msgid "%s (%s):\n" msgstr "%s (%s):\n" #: .././quota/quot.c:302 .././quota/quot.c:306 #, c-format msgid "%d\t%llu\t%llu\n" msgstr "%d\t%llu\t%llu\n" #: .././quota/quot.c:425 #, fuzzy msgid "[-bir] [-g|-p|-u] [-acv] [-f file]" msgstr "[-bir] [-gpu] [-acv] [-f Datei]" #: .././quota/quot.c:426 msgid "summarize filesystem ownership" msgstr "Übersicht des Eigentums am Dateisystem" #: .././quota/quota.c:33 #, c-format msgid "" "\n" " display usage and quota information\n" "\n" " -g -- display group quota information\n" " -p -- display project quota information\n" " -u -- display user quota information\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -v -- increase verbosity in reporting (also dumps zero values)\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n" msgstr "" "\n" " zeige Benutzungs- und Quota-Information\n" "\n" " -g -- zeige Gruppen-Quota-Information\n" " -p -- zeige Projekt-Quota-Information\n" " -u -- zeige Benutzer-Quota-Information\n" " -b -- Anzahl benutzter Blöcke anzeigen\n" " -i -- Anzahl benutzter Inodes anzeigen\n" " -r -- Anzahl benutzter Echtzeit-Blöcke anzeigen\n" " -h -- in für Menschen lesbarem Format ausgeben\n" " -n -- Übersetzung von Bezeichnern zu Namen überspringen, nur IDs\n" " ausgeben\n" " -N -- einleitende Kopfzeilen unterdrücken\n" " -v -- Ausführlichkeit der Ausgabe der Meldungen erhöhen (außerdem\n" " Nullwerte ausgeben)\n" " -f -- Ausgabe in eine Datei umleiten\n" " Der (optionale) Benutzer/Gruppe/Projekt an entweder durch Name oder\n" " Nummer (z.B. uid/gid/projid) angegeben werden.\n" "\n" #: .././quota/quota.c:86 #, c-format msgid "" "Disk quotas for %s %s (%u)\n" "Filesystem%s" msgstr "" "Platten-Quotas für %s %s (%u)\n" "Dateisystem%s" #: .././quota/quota.c:91 #, c-format msgid " Blocks Quota Limit Warn/Time " msgstr " Blöcke Quota Begrenzung Warnung/Zeit" #: .././quota/quota.c:92 #, c-format msgid " Blocks Quota Limit Warn/Time " msgstr " Blöcke Quota Begrenzung Warnung/Zeit " #: .././quota/quota.c:95 #, c-format msgid " Files Quota Limit Warn/Time " msgstr " Dateien Quota Begrenzung Warnung/Zeit" #: .././quota/quota.c:96 #, c-format msgid " Files Quota Limit Warn/Time " msgstr " Dateien Quota Begrenzung Warnung/Zeit " #: .././quota/quota.c:99 #, c-format msgid "Realtime Quota Limit Warn/Time " msgstr "Echtzeit Quota Begrenzung Warnung/Zeit" #: .././quota/quota.c:100 #, c-format msgid " Realtime Quota Limit Warn/Time " msgstr " Echtzeit Quota Begrenzung Warnung/Zeit " #: .././quota/quota.c:236 #, c-format msgid "%s: cannot find user %s\n" msgstr "%s: Benutzer %s kann nicht gefunden werden\n" #: .././quota/quota.c:286 #, c-format msgid "%s: cannot find group %s\n" msgstr "%s: Gruppe %s kann nicht gefunden werden\n" #: .././quota/quota.c:347 #, c-format msgid "%s: must specify a project name/ID\n" msgstr "%s: ein Projektname/ID muss angegeben werden\n" #: .././quota/quota.c:360 #, c-format msgid "%s: cannot find project %s\n" msgstr "%s: Projekt %s kann nicht gefunden werden\n" #: .././quota/quota.c:470 #, fuzzy msgid "[-bir] [-g|-p|-u] [-hnNv] [-f file] [id|name]..." msgstr "[-bir] [-gpu] [-hnNv] [-f Datei] [id|name]..." #: .././quota/quota.c:471 msgid "show usage and limits" msgstr "zeige Aufruf und Beschränkungen" #: .././quota/report.c:34 .././quota/report.c:769 msgid "dump quota information for backup utilities" msgstr "Auszug der Quota-Information für Sicherungsprogramm anzeigen" #: .././quota/report.c:36 #, c-format msgid "" "\n" " create a backup file which contains quota limits information\n" " -g -- dump out group quota limits\n" " -p -- dump out project quota limits\n" " -u -- dump out user quota limits (default)\n" " -f -- write the dump out to the specified file\n" "\n" msgstr "" "\n" " eine Sicherungsdatei erzeugen, die Quota-Begrenzung-Informationen\n" " enthält\n" " -g -- Auszug von Gruppen-Quota-Begrenzungen\n" " -p -- Auszug von Projekt-Quota-Begrenzungen\n" " -u -- Auszug von Benutzer-Quota-Begrenzungen (Standard)\n" " -f -- den Auszug in eine angegebene Datei schreiben\n" "\n" #: .././quota/report.c:48 #, fuzzy msgid "[-bir] [-gpu] [-ahntlLNU] [-f file]" msgstr "[-bir] [-gpu] [-ahntLNU] [-f Datei]" #: .././quota/report.c:49 .././quota/report.c:779 msgid "report filesystem quota information" msgstr "Quota-Information des Dateisystems ausgeben" #: .././quota/report.c:51 #, fuzzy, c-format msgid "" "\n" " report used space and inodes, and quota limits, for a filesystem\n" " Example:\n" " 'report -igh'\n" " (reports inode usage for all groups, in an easy-to-read format)\n" " This command is the equivalent of the traditional repquota command, which\n" " prints a summary of the disk usage and quotas for the current filesystem,\n" " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -L -- lower ID bound to report on\n" " -U -- upper ID bound to report on\n" " -l -- look up names for IDs in lower-upper range\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" " -u -- report user usage and quota information\n" " -b -- report blocks-used information only\n" " -i -- report inodes-used information only\n" " -r -- report realtime-blocks-used information only\n" "\n" msgstr "" "\n" " benutzten Speicher und Inodes und Quota-Beschränkungen für ein\n" " Dateisystem ausgeben\n" " Beispiel:\n" " 'report -igh'\n" " (gibt Inode-Nutzung für alle Gruppen in einfach lesbarem Format aus)\n" " Dieser Befehl entspricht dem traditionellen repquota-Befehl, der eine\n" " Zusammenfassung der Plattenbelegung und Quotas für das derzeitige\n" " Dateisystem oder alle Dateisysteme ausgibt.\n" " -a -- alle eingehängten Dateisysteme mit eingeschaltetem Quota\n" " anzeigen\n" " -h -- Anzeige in einem für Menschen lesbaren Format\n" " -n -- Übersetzung von Bezeichnern zu Namen überspringen, nur IDs\n" " ausgeben\n" " -N -- die Kopfzeilen in der Ausgabe unterdrücken\n" " -t -- kurzes Ausgabeformat, Zeilen, die nur Null enthalten, unterdrücken\n" " -L -- zeigt untere an den Bericht gebundene ID\n" " -U -- zeigt obere an den Bericht gebundene ID\n" " -g -- zeigt Gruppen-Nutzung und Quota-Information\n" " -p -- zeigt Projekt-Nutzung und Quota-Information\n" " -u -- zeigt Benutzer--Nutzung und Quota-Information\n" " -b -- zeigt nur Information über benutzte Blöcke\n" " -i -- zeigt nur Information über benutzte Inodes\n" " -r -- zeigt nur Information über benutzte Echtzeit-Blöcke\n" "\n" #: .././quota/report.c:273 #, c-format msgid "%s quota on %s (%s)\n" msgstr "%s Quota auf %s (%s)\n" #: .././quota/report.c:298 .././quota/report.c:306 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr " Benutzt Weich Hart Warnung/Gnadenfrist" #: .././quota/report.c:299 .././quota/report.c:307 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr " Benutzt Weich Hart Warnung/Gnadenfrist" #: .././quota/report.c:302 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr " Benutzt Weich Hart Warnung/Gnadenfrist" #: .././quota/report.c:303 #, c-format msgid " Used Soft Hard Warn/ Grace " msgstr " Benutzt Weich Hart Warnung/Gnadenfrist" #: .././quota/report.c:778 msgid "[-bir] [-gpu] [-ahnt] [-f file]" msgstr "[-bir] [-gpu] [-ahnt] [-f Datei]" #: .././quota/state.c:33 #, c-format msgid "" "\n" " turn filesystem quota off, both accounting and enforcement\n" "\n" " Example:\n" " 'off -uv' (switch off user quota on the current filesystem)\n" " This command is the equivalent of the traditional quotaoff command,\n" " which disables quota completely on a mounted filesystem.\n" " Note that there is no 'on' command - for XFS filesystems (with the\n" " exception of the root filesystem on IRIX) quota can only be enabled\n" " at mount time, through the use of one of the quota mount options.\n" "\n" " The state command is useful for displaying the current state. Using\n" " the -v (verbose) option with the 'off' command will display the quota\n" " state for the affected filesystem once the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " Dateisystem-Quota ausschalten, sowohl Kontenführung als auch\n" " Vollstreckung\n" "\n" " Beispiel:\n" " 'off -uv' (schaltet Benutzer-Quota auf dem derzeitigen Dateisystem aus)\n" " Dieser Befehl entspricht dem traditionellen quotaoff-Befehl, der\n" " das Quota auf eingehängten Dateisystemen gänzlich abschaltet\n" " Merken sie sich, dass es keinen »an«-Befehl gibt - für XFS-Dateisysteme\n" " (mit Ausnahme des Wurzel-Dateisystems auf IRIX) kann Quota\n" " zur Einhängezeit durch Benutzung einer der\n" " Einhänge-Quota-Optionen eingeschaltet werden\n" "\n" " Der Status-Befehl ist nützlich zur Anzeige des gegenwärtigen Status.\n" " Die Benutzung der »-v«-Option (detailliert) mit dem »off«-Befehl gibt\n" " den Quota-Status für das betroffene Dateisystem aus, bis der\n" " Arbeitsvorgang komplett ist. Der betroffene Quota-Typ ist\n" " -g (Gruppen), -p (Projekte) oder -u (Benutzer) und Standard ist\n" " Benutzer-Quota (mehrere Typen können angegeben werden).\n" "\n" #: .././quota/state.c:56 #, c-format msgid "" "\n" " query the state of quota on the current filesystem\n" "\n" " This is a verbose status command, reporting whether or not accounting\n" " and/or enforcement are enabled for a filesystem, which inodes are in\n" " use as the quota state inodes, and how many extents and blocks are\n" " presently being used to hold that information.\n" " The quota type is specified via -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " den Status der Quota auf dem aktuellen Dateisystem abfragen\n" "\n" " Dies ist ein detailreicher Status-Befehl, der ausgibt, ob Kontierung\n" " und Vollstreckung für ein Dateisystem, dessen Inodes als\n" " Quota-Status-Inode in Gebrauch sind, eingeschaltet ist oder nicht\n" " und wie viele Erweiterungen und Blöcke derzeit benutzt werden, um diese\n" " Information aufzubewahren.\n" " Der Quota-Typ ist angegeben mittels -g (Gruppen), -p (Projekte)\n" " oder -u (Benutzer) und Standard ist Benutzer-Quota (mehrere\n" " Typen können angegeben werden).\n" "\n" #: .././quota/state.c:72 #, c-format msgid "" "\n" " enable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and has quota accounting enabled, but not\n" " quota enforcement, enforcement can be enabled with this command.\n" " With the -v (verbose) option, the status of the filesystem will be\n" " reported after the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " schaltet Quota-Erzwingung auf einem Dateisystem ein\n" "\n" " Wenn ein Dateisystem eingehängt und Quota eingeschaltet ist, aber keine \n" " Quota-Erzwingung, kann die Erzwingung mit diesem Befehl eingeschaltet\n" " werden. Mit der »-v«-Option (detailliert) wird der Status des\n" " Dateisystems nach Abschluss der Arbeitsgangs angezeigt.\n" " Der betroffene Quota-Typ ist -g (Gruppen), -p (Projekte) oder\n" " -u (Benutzer) und Standard ist Benutzer-Quota (mehrere Typen können\n" " angegeben werden).\n" #: .././quota/state.c:88 #, c-format msgid "" "\n" " disable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and is currently enforcing quota, this\n" " provides a mechanism to switch off the enforcement, but continue to\n" " perform used space (and used inodes) accounting.\n" " The affected quota type is -g (groups), -p (projects) or -u (users).\n" "\n" msgstr "" "\n" " schaltet Quota-Erzwingung auf einem Dateisystem aus\n" "\n" " Wenn ein Dateisystem eingehängt ist und derzeit Quota erzwingt,\n" " stellt dies einen Mechanismus zur Verfügung um die Erzwingung\n" " auszuschalten aber mit der Kontierung von benutztem Speicher (und\n" " benutzter Inodes) fortzufahren.\n" " Der betroffene Quota-Typ ist -g (Gruppen), -p (Projekte) oder\n" " -u (Benutzer).\n" "\n" #: .././quota/state.c:102 #, c-format msgid "" "\n" " remove any space being used by the quota subsystem\n" "\n" " Once quota has been switched 'off' on a filesystem, the space that\n" " was allocated to holding quota metadata can be freed via this command.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " durch das Quota-Untersystem benutzten Speicher freigeben\n" "\n" " Wenn das Quota auf einem Dateisystem ausgeschaltet wurde, kann der\n" " Speicher, der für die Quota-Metadaten zugeteilt wurde mit diesem Befehl\n" " freigegeben werden. Der betroffene Quota-Typ ist -g (Gruppen),\n" " -p (Projekte) oder -u (Benutzer) und Standard ist Benutzer-Quotaierung\n" " (mehrere Typen können angegeben werden)..\n" "\n" #: .././quota/state.c:121 #, c-format msgid "%s quota state on %s (%s)\n" msgstr "%s Quota-Status auf %s (%s)\n" #: .././quota/state.c:123 #, c-format msgid " Accounting: %s\n" msgstr "Kontierung: %s\n" #: .././quota/state.c:123 .././quota/state.c:124 msgid "ON" msgstr "AN" #: .././quota/state.c:123 .././quota/state.c:124 msgid "OFF" msgstr "AUS" #: .././quota/state.c:124 #, c-format msgid " Enforcement: %s\n" msgstr " Vollstreckung: %s\n" #: .././quota/state.c:126 #, c-format msgid " Inode: #%llu (%llu blocks, %lu extents)\n" msgstr " Inode: #%llu (%llu Blöcke, %lu Erweiterungen)\n" #: .././quota/state.c:131 #, c-format msgid " Inode: N/A\n" msgstr "" #: .././quota/state.c:140 #, c-format msgid "%s grace time: %s\n" msgstr "%s Gnadenfrist: %s\n" #: .././quota/state.c:212 #, c-format msgid "%s quota are not enabled on %s\n" msgstr "%s Quota ist auf %s nicht eingeschaltet\n" #: .././quota/state.c:584 .././quota/state.c:601 .././quota/state.c:609 #: .././quota/state.c:617 msgid "[-gpu] [-v]" msgstr "[-gpu] [-v]" #: .././quota/state.c:585 msgid "permanently switch quota off for a path" msgstr "Quota für den Pfad dauerhaft ausschalten" #: .././quota/state.c:592 msgid "[-gpu] [-a] [-v] [-f file]" msgstr "[-gpu] [-a] [-v] [-f Datei]" #: .././quota/state.c:593 msgid "get overall quota state information" msgstr "umfassende Quota-Information erhalten" #: .././quota/state.c:602 msgid "enable quota enforcement" msgstr "Quota-Erzwingung einschalten" #: .././quota/state.c:610 msgid "disable quota enforcement" msgstr "Quota-Erzwingung ausschalten" #: .././quota/state.c:618 msgid "remove quota extents from a filesystem" msgstr "Quota-Erweiterungen aus einem Dateisystem entfernen" #: .././quota/util.c:70 #, c-format msgid "[-none-]" msgstr "[-keins-]" #: .././quota/util.c:70 #, c-format msgid "[--none--]" msgstr "[--keins--]" #: .././quota/util.c:73 #, c-format msgid "[------]" msgstr "[------]" #: .././quota/util.c:73 #, c-format msgid "[--------]" msgstr "[--------]" #: .././quota/util.c:77 .././quota/util.c:80 msgid "day" msgstr "Tag" #: .././quota/util.c:77 .././quota/util.c:80 msgid "days" msgstr "Tage" #: .././quota/util.c:205 msgid "Blocks" msgstr "Blöcke" #: .././quota/util.c:205 msgid "Inodes" msgstr "Inodes" #: .././quota/util.c:205 msgid "Realtime Blocks" msgstr "Echtzeit-Blöcke" #: .././quota/util.c:220 msgid "User" msgstr "Benutzer" #: .././quota/util.c:220 msgid "Group" msgstr "Gruppe" #: .././quota/util.c:220 msgid "Project" msgstr "Projekt" #: .././quota/util.c:428 #, c-format msgid "%s: open on %s failed: %s\n" msgstr "%s: Öffnen auf %s fehlgeschlagen: %s\n" #: .././quota/util.c:434 #, c-format msgid "%s: fdopen on %s failed: %s\n" msgstr "%s: fdopen auf %s fehlgeschlagen: %s\n" #: .././repair/agheader.c:40 #, c-format msgid "bad magic # 0x%x for agf %d\n" msgstr "flasche magische # 0x%x für agf %d\n" #: .././repair/agheader.c:49 #, c-format msgid "bad version # %d for agf %d\n" msgstr "falsche Version # %d für agf %d\n" #: .././repair/agheader.c:58 #, c-format msgid "bad sequence # %d for agf %d\n" msgstr "falsche Sequenz # %d für agf %d\n" #: .././repair/agheader.c:68 #, c-format msgid "bad length %d for agf %d, should be %d\n" msgstr "falsche Länge %d für agf %d, könnte %d sein\n" #: .././repair/agheader.c:81 #, fuzzy, c-format msgid "bad length %d for agf %d, should be %\n" msgstr "falsche Länge %d für agf %d, könnte %llu sein\n" #: .././repair/agheader.c:95 #, fuzzy, c-format msgid "flfirst %d in agf %d too large (max = %zu)\n" msgstr "flfirst %d in agf %d zu groß (Maximum = %d)\n" #: .././repair/agheader.c:103 #, fuzzy, c-format msgid "fllast %d in agf %d too large (max = %zu)\n" msgstr "fllast %d in agf %d zu groß (Maximum = %d)\n" #: .././repair/agheader.c:120 #, fuzzy, c-format msgid "bad uuid %s for agf %d\n" msgstr "flasche magische # 0x%x für agf %d\n" #: .././repair/agheader.c:139 #, c-format msgid "bad magic # 0x%x for agi %d\n" msgstr "falsche magische # 0x%x für agi %d\n" #: .././repair/agheader.c:148 #, c-format msgid "bad version # %d for agi %d\n" msgstr "falsche Version # %d für agi %d\n" #: .././repair/agheader.c:157 #, c-format msgid "bad sequence # %d for agi %d\n" msgstr "falsche Sequenz # %d für agi %d\n" #: .././repair/agheader.c:167 #, c-format msgid "bad length # %d for agi %d, should be %d\n" msgstr "falsche Länge %d für agi %d, könnte %d sein\n" #: .././repair/agheader.c:180 #, fuzzy, c-format msgid "bad length # %d for agi %d, should be %\n" msgstr "falsche Länge %d für agi %d, könnte %llu sein\n" #: .././repair/agheader.c:199 #, fuzzy, c-format msgid "bad uuid %s for agi %d\n" msgstr "falsche magische # 0x%x für agi %d\n" #: .././repair/agheader.c:305 #, c-format msgid "zeroing unused portion of %s superblock (AG #%u)\n" msgstr "ungenutzten Anteil des »%s«-Superblocks nullen (AG #%u)\n" #: .././repair/agheader.c:306 .././repair/agheader.c:324 msgid "primary" msgstr "primär" #: .././repair/agheader.c:306 .././repair/agheader.c:324 msgid "secondary" msgstr "sekundär" #: .././repair/agheader.c:323 #, c-format msgid "would zero unused portion of %s superblock (AG #%u)\n" msgstr "" "ungenutzter Anteil des »%s«-Superblocks sollte genullt werden (AG #%u)\n" #: .././repair/agheader.c:341 #, c-format msgid "bad flags field in superblock %d\n" msgstr "falsches Kennzeichnungsfeld im Superblock %d\n" #: .././repair/agheader.c:364 #, c-format msgid "non-null user quota inode field in superblock %d\n" msgstr "Benutzer-Quota-Inode-Feld im Superblock %d nicht Null\n" #: .././repair/agheader.c:379 #, c-format msgid "non-null group quota inode field in superblock %d\n" msgstr "Gruppen-Quota-Inode-Feld im Superblock %d nicht Null\n" #: .././repair/agheader.c:400 #, fuzzy, c-format msgid "non-null project quota inode field in superblock %d\n" msgstr "Gruppen-Quota-Inode-Feld im Superblock %d nicht Null\n" #: .././repair/agheader.c:412 #, c-format msgid "non-null quota flags in superblock %d\n" msgstr "Quota-Markierungen im Superblock %d nicht Null\n" #: .././repair/agheader.c:430 #, c-format msgid "bad inode alignment field in superblock %d\n" msgstr "falsches Inode-Ausrichtungs-Feld im Superblock %d\n" #: .././repair/agheader.c:443 #, c-format msgid "bad stripe unit/width fields in superblock %d\n" msgstr "falsche Stripe-Einheit/Breite Felder in Superblock %d\n" #: .././repair/agheader.c:461 #, c-format msgid "bad log/data device sector size fields in superblock %d\n" msgstr "falsche Protokoll/Daten-Gerät-Sektorenfeldgröße im Superblock %d\n" #: .././repair/agheader.c:492 #, c-format msgid "bad on-disk superblock %d - %s\n" msgstr "falscher on-disk-Superblock %d - %s\n" #: .././repair/agheader.c:499 #, c-format msgid "primary/secondary superblock %d conflict - %s\n" msgstr "primäre/sekundärer Superblock-%d-Konflikt - %s\n" #: .././repair/attr_repair.c:70 #, c-format msgid "bad range claimed [%d, %d) in da block\n" msgstr "falscher Bereich beansprucht [%d, %d) in da-Block\n" #: .././repair/attr_repair.c:77 #, c-format msgid "byte range end [%d %d) in da block larger than blocksize %d\n" msgstr "Byte-Bereichsende [%d, %d) in da-Block größer als Blockgröße %d\n" #: .././repair/attr_repair.c:84 #, c-format msgid "multiply claimed byte %d in da block\n" msgstr "mehrfach beanspruchtes Byte %d in da-Block\n" #: .././repair/attr_repair.c:164 msgid "No memory for ACL check!\n" msgstr "" #: .././repair/attr_repair.c:172 msgid "" "entry contains illegal value in attribute named SGI_ACL_FILE or " "SGI_ACL_DEFAULT\n" msgstr "" "Eintrag enthält unerlaubten Wert im Attribut mit Namen SGI_ACL_FILE\n" "oder SGI_ACL_DEFAULT\n" #: .././repair/attr_repair.c:198 msgid "entry contains illegal value in attribute named SGI_MAC_LABEL\n" msgstr "Eintrag enthält unerlaubten Wert im Attribut mit Namen SGI_MAC_LABEL\n" #: .././repair/attr_repair.c:204 msgid "entry contains illegal value in attribute named SGI_CAP_FILE\n" msgstr "Eintrag enthält unerlaubten Wert im Attribut mit Namen SGI_CAP_FILE\n" #: .././repair/attr_repair.c:244 #, fuzzy, c-format msgid "there are no attributes in the fork for inode %\n" msgstr "es sind keine Attribute im Unterelement für Inode %llu\n" #: .././repair/attr_repair.c:252 #, fuzzy, c-format msgid "would junk the attribute fork since count is 0 for inode %\n" msgstr "Attributs-Fork würde weggeworfen seit Anzahl für Inode %llu 0 ist\n" #: .././repair/attr_repair.c:272 msgid "zero length name entry in attribute fork," msgstr "Namenseintrag mit Länge Null in Attribut-Abspaltung," #: .././repair/attr_repair.c:275 .././repair/attr_repair.c:295 #, fuzzy, c-format msgid " truncating attributes for inode % to %d\n" msgstr "Attribute für Inode %llu auf %d kürzen\n" #: .././repair/attr_repair.c:280 .././repair/attr_repair.c:301 #, fuzzy, c-format msgid " would truncate attributes for inode % to %d\n" msgstr "Attribute für Inode %llu könnten auf %d gekürzt werden\n" #: .././repair/attr_repair.c:292 msgid "name or value attribute lengths are too large,\n" msgstr "Name oder Länge des Attributswerts sind zu lang,\n" #: .././repair/attr_repair.c:314 msgid "entry contains illegal character in shortform attribute name\n" msgstr "" "Eintrag enthält unerlaubtes Zeichen in der Kurzform des Attributsnamens\n" #: .././repair/attr_repair.c:320 msgid "entry has INCOMPLETE flag on in shortform attribute\n" msgstr "Eintrag hat INCOMPLETE-Markierung in der Attributs-Kurzform\n" #: .././repair/attr_repair.c:338 #, fuzzy, c-format msgid "removing attribute entry %d for inode %\n" msgstr "Attributseintrag %d für Inode %llu wird entfernt\n" #: .././repair/attr_repair.c:350 #, fuzzy, c-format msgid "would remove attribute entry %d for inode %\n" msgstr "Attributs-Eintrag %d für Inode %llu könnte entfernt werden\n" #: .././repair/attr_repair.c:365 #, fuzzy, c-format msgid "" "would have corrected attribute entry count in inode % from %d to %d\n" msgstr "" "Anzahl der Attributs-Einträge könnte in Inode %llu von %d auf %d\n" "korrigiert worden sein\n" #: .././repair/attr_repair.c:369 #, fuzzy, c-format msgid "corrected attribute entry count in inode %, was %d, now %d\n" msgstr "" "Korrigierte Anzahl der Attributs-Einträge in Inode %llu war %d,\n" "ist nun %d\n" #: .././repair/attr_repair.c:380 #, fuzzy, c-format msgid "" "would have corrected attribute totsize in inode % from %d to %d\n" msgstr "" "Anzahl der Attributs-Gesamtgröße könnte in Inode %llu von %d auf %d\n" "korrigiert worden sein\n" #: .././repair/attr_repair.c:385 #, fuzzy, c-format msgid "corrected attribute entry totsize in inode %, was %d, now %d\n" msgstr "" "Korrigierte Gesamtgröße der Attributs-Einträge in Inode %llu war %d,\n" "ist nun %d\n" #: .././repair/attr_repair.c:419 #, fuzzy, c-format msgid "remote block for attributes of inode % is missing\n" msgstr "entfernt liegender Block für Attribute des Inodes %llu fehlt\n" #: .././repair/attr_repair.c:428 #, fuzzy, c-format msgid "can't read remote block for attributes of inode %\n" msgstr "" "entfernt liegender Block für Attribute des Inodes %llu kann nicht\n" "gelesen werden\n" #: .././repair/attr_repair.c:435 #, fuzzy, c-format msgid "Corrupt remote block for attributes of inode %\n" msgstr "" "entfernt liegender Block für Attribute des Inodes %llu kann nicht\n" "gelesen werden\n" #: .././repair/attr_repair.c:476 #, fuzzy, c-format msgid "" "attribute entry %d in attr block %u, inode % has bad name (namelen = " "%d)\n" msgstr "" "Attributs-Eintrag #%d in »attr«-Block %u, Inode %llu hat ungültigen\n" "Namen (namelen = %d)\n" #: .././repair/attr_repair.c:493 #, fuzzy, c-format msgid "" "bad hashvalue for attribute entry %d in attr block %u, inode %\n" msgstr "" "falscher Hash-Wert für Attributs-Eintrag %d in »attr«-Block %u,\n" "Inode %llu\n" #: .././repair/attr_repair.c:503 #, fuzzy, c-format msgid "" "bad security value for attribute entry %d in attr block %u, inode %\n" msgstr "" "falscher Sicherheitswert für Attributs-Eintrag %d in »attr«-Block %u in\n" "Inode %llu\n" #: .././repair/attr_repair.c:536 #, fuzzy, c-format msgid "" "inconsistent remote attribute entry %d in attr block %u, ino %\n" msgstr "" "Unvollständiger entfernt liegender Attributs-Eintrag %d in\n" "»attr«-Block %u, ino %llu\n" #: .././repair/attr_repair.c:546 #, fuzzy, c-format msgid "cannot malloc enough for remotevalue attribute for inode %\n" msgstr "malloc nicht ausreichend für remotevalue-Attribut für Inode %llu\n" #: .././repair/attr_repair.c:548 msgid "SKIPPING this remote attribute\n" msgstr "ÜBERSPRINGE dieses entfernt liegende Attribut\n" #: .././repair/attr_repair.c:554 #, fuzzy, c-format msgid "remote attribute get failed for entry %d, inode %\n" msgstr "" "das Abholen des entfernt liegenden Attributs scheiterte für Eintrag %d,\n" "Inode %llu\n" #: .././repair/attr_repair.c:561 #, fuzzy, c-format msgid "remote attribute value check failed for entry %d, inode %\n" msgstr "" "das Prüfen des entfernt liegenden Attributs-Wertes scheiterte für\n" "Eintrag %d, Inode %llu\n" #: .././repair/attr_repair.c:600 #, fuzzy, c-format msgid "bad attribute count %d in attr block %u, inode %\n" msgstr "falsche Attributs-Anzahl %d in »attr«-Block %u, Inode %llu\n" #: .././repair/attr_repair.c:615 #, fuzzy, c-format msgid "bad attribute nameidx %d in attr block %u, inode %\n" msgstr "falsches Attribut nameidx %d in »attr«-Block %u, Inode %llu\n" #: .././repair/attr_repair.c:624 #, fuzzy, c-format msgid "attribute entry #%d in attr block %u, inode % is INCOMPLETE\n" msgstr "" "Attributs-Eintrag #%d in »attr«-Block %u, Inode %llu ist UNVOLLSTÄNDIG\n" #: .././repair/attr_repair.c:635 #, fuzzy, c-format msgid "" "attribute entry %d in attr block %u, inode % claims already used " "space\n" msgstr "" "Attributs-Eintrag #%d in »attr«-Block %u, Inode %llu erhebt Anspruch auf\n" "benutzten Speicher\n" #: .././repair/attr_repair.c:658 #, fuzzy, c-format msgid "" "attribute entry %d in attr block %u, inode % claims used space\n" msgstr "" "Attributs-Eintrag %d in »attr«-Block %u, Inode %llu erhebt Anspruch auf\n" "benutzten Speicher\n" #: .././repair/attr_repair.c:682 #, fuzzy, c-format msgid "" "- resetting first used heap value from %d to %d in block %u of attribute " "fork of inode %\n" msgstr "" "- zuerst benutzter Heap-Wert wird von %d auf %d zurückgesetzt in Block %u\n" "des Attributs-Forks von Inode %llu\n" #: .././repair/attr_repair.c:690 #, fuzzy, c-format msgid "" "- would reset first used value from %d to %d in block %u of attribute fork " "of inode %\n" msgstr "" "- zuerst genutzter Wert könnte von %d auf %d zurückgesetzt werden im\n" "Block %u des Attribut-Unterelements von Inode %llu\n" #: .././repair/attr_repair.c:700 #, fuzzy, c-format msgid "" "- resetting usedbytes cnt from %d to %d in block %u of attribute fork of " "inode %\n" msgstr "" "- usedbytes cnt wird von %d auf %d zurückgesetzt in Block %u des\n" "Attributs-Forks von Inode %llu\n" #: .././repair/attr_repair.c:708 #, fuzzy, c-format msgid "" "- would reset usedbytes cnt from %d to %d in block %u of attribute fork of " "%\n" msgstr "" "- usedbytes cnt würde von %d auf %d zurückgesetzt in Block %u des\n" "Attributs-Forks von Inode %llu\n" #: .././repair/attr_repair.c:770 #, fuzzy, c-format msgid "can't map block %u for attribute fork for inode %\n" msgstr "" "Block %u kann nicht für Erstellung eines Unterelements des Inodes %llu\n" "kartiert werden\n" #: .././repair/attr_repair.c:780 #, fuzzy, c-format msgid "" "can't read file block %u (fsbno %) for attribute fork of inode " "%\n" msgstr "" "Datei-Block %u (fsbno %llu) für Erstellung des Subattributs des Inodes\n" "%llu kann nicht gelesen werden\n" #: .././repair/attr_repair.c:792 #, fuzzy, c-format msgid "bad attribute leaf magic %#x for inode %\n" msgstr "falsches Attributsblatt magische %#x für Inode %llu\n" #: .././repair/attr_repair.c:823 #, fuzzy, c-format msgid "" "bad sibling back pointer for block %u in attribute fork for inode %\n" msgstr "" "falscher Geschwister-Rückwärtszeiger für Block %u in Attributs-Fork für\n" "Inode %llu\n" #: .././repair/attr_repair.c:858 #, fuzzy, c-format msgid "bad hash path in attribute fork for inode %\n" msgstr "schlechter Hash-Pfad in Subattribut für Inode %llu\n" #: .././repair/attr_repair.c:940 #, c-format msgid "expected owner inode %, got %llu, attr block %\n" msgstr "" #: .././repair/attr_repair.c:947 #, c-format msgid "expected block %, got %llu, inode %attr block\n" msgstr "" #: .././repair/attr_repair.c:954 #, c-format msgid "wrong FS UUID, inode % attr block %\n" msgstr "" #: .././repair/attr_repair.c:996 #, fuzzy, c-format msgid "block 0 of inode % attribute fork is missing\n" msgstr "Block 0 des Subattributs von Inode %llu fehlt\n" #: .././repair/attr_repair.c:1003 #, fuzzy, c-format msgid "agno of attribute fork of inode % out of regular partition\n" msgstr "" "agno des Subattributs des Inodes %llu außerhalb der regulären Partition\n" #: .././repair/attr_repair.c:1011 #, fuzzy, c-format msgid "can't read block 0 of inode % attribute fork\n" msgstr "Block 0 des Subattributs von Inode %llu kann nicht gelesen werden\n" #: .././repair/attr_repair.c:1035 #, fuzzy, c-format msgid "" "clearing forw/back pointers in block 0 for attributes in inode %\n" msgstr "" "Vorwärts-/Rückwärtszeiger im Block 0 für Attribute des Inodes %llu wird\n" "bereinigt\n" #: .././repair/attr_repair.c:1044 #, fuzzy, c-format msgid "" "would clear forw/back pointers in block 0 for attributes in inode %\n" msgstr "" "Vorwärts-/Rückwärtszeiger im Block 0 für Attribute des Inodes %llu\n" "könnte bereinigt werden\n" #: .././repair/attr_repair.c:1080 #, fuzzy, c-format msgid "bad attribute leaf magic # %#x for dir ino %\n" msgstr "falsches Attributsblatt magische # %#x für dir ino %llu\n" #: .././repair/attr_repair.c:1110 #, c-format msgid "Too many ACL entries, count %d\n" msgstr "" #: .././repair/attr_repair.c:1119 msgid "cannot malloc enough for ACL attribute\n" msgstr "nicht genug malloc für ACL-Attribut möglich\n" #: .././repair/attr_repair.c:1120 msgid "SKIPPING this ACL\n" msgstr "ÜBERSPRINGE dieses ACL\n" #: .././repair/attr_repair.c:1170 .././repair/dinode.c:2065 #, fuzzy, c-format msgid "illegal attribute format %d, ino %\n" msgstr "unerlaubtes Attributs-Format %d, ino %llu\n" #: .././repair/avl.c:1011 .././repair/avl64.c:1032 #, c-format msgid "avl_insert: Warning! duplicate range [%llu,%llu]\n" msgstr "avl_insert: Warnung! Doppelter Bereich [%llu,%llu]\n" #: .././repair/avl.c:1206 .././repair/avl64.c:1227 #, c-format msgid "Command [fpdir] : " msgstr "Befehl [fpdir] : " #: .././repair/avl.c:1215 .././repair/avl64.c:1236 #, c-format msgid "end of range ? " msgstr "Ende des Bereichs? " #: .././repair/avl.c:1226 .././repair/avl64.c:1247 #, c-format msgid "Cannot find %d\n" msgstr "%d kann nicht gefunden werden\n" #: .././repair/avl.c:1239 .././repair/avl64.c:1260 #, c-format msgid "size of range ? " msgstr "Größe des Bereichs? " #: .././repair/avl.c:1250 .././repair/avl64.c:1271 #, c-format msgid "End of range ? " msgstr "Ende des Bereichs? " #: .././repair/avl.c:1254 .././repair/avl64.c:1275 #, c-format msgid "checklen 0/1 ? " msgstr "checklen 0/1? " #: .././repair/avl.c:1261 .././repair/avl64.c:1282 #, c-format msgid "Found something\n" msgstr "Etwas gefunden\n" #: .././repair/bmap.c:53 #, c-format msgid "" "Number of extents requested in blkmap_alloc (%d) overflows 32 bits.\n" "If this is not a corruption, then you will need a 64 bit system\n" "to repair this filesystem.\n" msgstr "" #: .././repair/bmap.c:66 #, fuzzy, c-format msgid "malloc failed in blkmap_alloc (%zu bytes)\n" msgstr "»malloc« in »blkent_alloc« fehlgeschlagen (%u Bytes)\n" #: .././repair/bmap.c:189 #, fuzzy, c-format msgid "blkmap_getn malloc failed (% bytes)\n" msgstr "»blkmap_getn realloc« fehlgeschlagen (%u Bytes)\n" #: .././repair/bmap.c:296 #, c-format msgid "" "Number of extents requested in blkmap_grow (%d) overflows 32 bits.\n" "You need a 64 bit system to repair this filesystem.\n" msgstr "" #: .././repair/bmap.c:304 #, c-format msgid "" "Number of extents requested in blkmap_grow (%d) overflowed the\n" "maximum number of supported extents (%d).\n" msgstr "" #: .././repair/bmap.c:312 #, fuzzy msgid "realloc failed in blkmap_grow\n" msgstr "»realloc« in »blkent_grow« fehlgeschlagen (%u Bytes)\n" #: .././repair/da_util.c:88 .././repair/prefetch.c:238 msgid "couldn't malloc dir2 buffer list\n" msgstr "malloc dir2 Pufferliste konnte nicht ausgeführt werden\n" #: .././repair/da_util.c:105 #, fuzzy msgid "attribute" msgstr "attr" #: .././repair/da_util.c:164 .././repair/da_util.c:585 #, fuzzy, c-format msgid "can't read %s block %u for inode %\n" msgstr "Block %u für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #: .././repair/da_util.c:177 #, fuzzy, c-format msgid "found non-root LEAFN node in inode % bno = %u\n" msgstr "Nicht-Wurzel-LEAFN-Knoten gefunden in Inode %llu bno = %u\n" #: .././repair/da_util.c:188 #, fuzzy, c-format msgid "bad %s magic number 0x%x in inode % bno = %u\n" msgstr "falsche magische Nummer 0x%x in Inode %llu bno = %u\n" #: .././repair/da_util.c:199 #, fuzzy, c-format msgid "corrupt %s tree block %u for inode %\n" msgstr "kaputter Block %u in Verzeichnis-Inode %llu\n" #: .././repair/da_util.c:207 #, fuzzy, c-format msgid "bad %s record count in inode %, count = %d, max = %d\n" msgstr "falsche Datensatz-Anzahl in Inode %llu, Anzahl = %d max = %d\n" #: .././repair/da_util.c:221 #, fuzzy, c-format msgid "bad header depth for directory inode %\n" msgstr "falsche Kopfzeilentiefe für Verzeichnis-Inode %llu\n" #: .././repair/da_util.c:232 #, fuzzy, c-format msgid "bad %s btree for inode %\n" msgstr "falsches Attributs-Unterelement btree für Inode %llu\n" #: .././repair/da_util.c:282 #, c-format msgid "release_da_cursor_int got unexpected non-null bp, dabno = %u\n" msgstr "release_da_cursor_int hat unerwartetes Nicht-Null bp, dabno = %u\n" #: .././repair/da_util.c:360 #, fuzzy, c-format msgid "%s block used/count inconsistency - %d/%hu\n" msgstr "Verzeichnis-Block benutzt/Anzahl unvollständig - %d / %hu\n" #: .././repair/da_util.c:370 #, fuzzy, c-format msgid "%s block hashvalue inconsistency, expected > %u / saw %u\n" msgstr "" "Verzeichnis-/Attributsblock Hash-Wert-Unstimmigkeit, erwartet > %u /\n" "gesehen %u\n" #: .././repair/da_util.c:378 #, fuzzy, c-format msgid "bad %s forward block pointer, expected 0, saw %u\n" msgstr "falscher Verzeichnis-/Attribut-Block-Zeiger, erwartet 0, gesehen %u\n" #: .././repair/da_util.c:383 #, fuzzy, c-format msgid "bad %s block in inode %\n" msgstr "falscher Verzeichnisblock in Inode %llu\n" #: .././repair/da_util.c:413 #, fuzzy, c-format msgid "" "correcting bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "falscher hashval in non-leaf dir-Block wird koorigiert\n" "\tin (Stufe %d) in Inode %llu.\n" #: .././repair/da_util.c:421 #, fuzzy, c-format msgid "" "would correct bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "falscher hashval in non-leaf dir-Block würde koorigiert\n" "\tin (Stufe %d) in Inode %llu.\n" #: .././repair/da_util.c:574 #, fuzzy, c-format msgid "can't get map info for %s block %u of inode %\n" msgstr "" "Karten-Info für Block %u des Verzeichnis-Inodes %llu kann nicht bezogen\n" "werden\n" #: .././repair/da_util.c:602 #, fuzzy, c-format msgid "bad magic number %x in %s block %u for inode %\n" msgstr "falsche Magische Nummer %x in Block %u für Verzeichnis-Inode %llu\n" #: .././repair/da_util.c:609 #, fuzzy, c-format msgid "bad back pointer in %s block %u for inode %\n" msgstr "falscher Rückwärts-Zeiger in Block %u für Verzeichnis-Inode %llu\n" #: .././repair/da_util.c:615 #, fuzzy, c-format msgid "entry count %d too large in %s block %u for inode %\n" msgstr "Eintragsanzahl %d in Block %u für Verzeichnis-Inode %llu zu groß\n" #: .././repair/da_util.c:622 #, fuzzy, c-format msgid "bad level %d in %s block %u for inode %\n" msgstr "falsche Stufe %d in Block %u für Verzeichnis-Inode %llu\n" #: .././repair/da_util.c:686 #, fuzzy, c-format msgid "" "correcting bad hashval in interior %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "falscher hashval in interior dir-Block wird koorigiert\n" "\tin (Stufe %d) in Inode %llu.\n" #: .././repair/da_util.c:694 #, fuzzy, c-format msgid "" "would correct bad hashval in interior %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "falscher hashval in interior dir-Block würde koorigiert\n" "\tin (Stufe %d) in Inode %llu.\n" #: .././repair/dino_chunks.c:57 #, fuzzy, c-format msgid "cannot read agbno (%u/%u), disk block %\n" msgstr "agbno (%u/%u) kann nicht gelesen werden, Plattenblock %lld\n" #: .././repair/dino_chunks.c:150 #, c-format msgid "uncertain inode block %d/%d already known\n" msgstr "unsicherer Inode-Block %d/%d bereits bekannt\n" #: .././repair/dino_chunks.c:166 .././repair/dino_chunks.c:438 #: .././repair/dino_chunks.c:497 #, c-format msgid "inode block %d/%d multiply claimed, (state %d)\n" msgstr "Inode-Block %d/%d mehrfach beansprucht, (Status %d)\n" #: .././repair/dino_chunks.c:173 .././repair/dino_chunks.c:502 #, c-format msgid "inode block %d/%d bad state, (state %d)\n" msgstr "Inode-Block %d/%d Status schlecht, (Status %d)\n" #: .././repair/dino_chunks.c:445 #, fuzzy, c-format msgid "uncertain inode block overlap, agbno = %d, ino = %\n" msgstr "unsichere Inode-Block-Überschneidung, agbno = %d, ino = %llu\n" #: .././repair/dino_chunks.c:484 #, fuzzy, c-format msgid "uncertain inode block % already known\n" msgstr "unsicherer Inode-Block %llu bereits bekannt\n" #: .././repair/dino_chunks.c:578 #, c-format msgid "bad state in block map %d\n" msgstr "falscher Status in Block-Kartierung %d\n" #: .././repair/dino_chunks.c:583 #, fuzzy, c-format msgid "inode block % multiply claimed, state was %d\n" msgstr "Inode-Block %llu mehrfach beansprucht, Status war %d\n" #: .././repair/dino_chunks.c:654 #, fuzzy, c-format msgid "failed to allocate %zd bytes of memory\n" msgstr "%d Bytes Speicher zu allozieren fehlgeschlagen\n" #: .././repair/dino_chunks.c:678 #, fuzzy, c-format msgid "cannot read inode %, disk block %, cnt %d\n" msgstr "Inode %llu kann nicht gelesen werden, Plattenblock %lld, cnt %d\n" #: .././repair/dino_chunks.c:834 #, fuzzy, c-format msgid "imap claims in-use inode % is free, " msgstr "von imap in Benutzung beanspruchter Inode %llu ist frei, " #: .././repair/dino_chunks.c:839 msgid "correcting imap\n" msgstr "imap wird korrigiert\n" #: .././repair/dino_chunks.c:841 msgid "would correct imap\n" msgstr "imap könnte korrigiert werden\n" #: .././repair/dino_chunks.c:896 #, fuzzy, c-format msgid "cleared root inode %\n" msgstr "bereinigter Wurzel-Inode %llu\n" #: .././repair/dino_chunks.c:900 #, fuzzy, c-format msgid "would clear root inode %\n" msgstr "könnte Wurzel-Inode %llu bereinigen\n" #: .././repair/dino_chunks.c:908 #, fuzzy, c-format msgid "cleared realtime bitmap inode %\n" msgstr "geleerter Echtzeit-Bitmap-Inode %llu\n" #: .././repair/dino_chunks.c:912 #, fuzzy, c-format msgid "would clear realtime bitmap inode %\n" msgstr "würde Echtzeit-Bitmap-Inode %llu leeren\n" #: .././repair/dino_chunks.c:920 #, fuzzy, c-format msgid "cleared realtime summary inode %\n" msgstr "bereinigter Echtzeit-Zusammenfassungs-Inode %llu\n" #: .././repair/dino_chunks.c:924 #, fuzzy, c-format msgid "would clear realtime summary inode %\n" msgstr "könnte Echtzeit-Zusammenfassungs-Inode %llu bereinigen\n" #: .././repair/dino_chunks.c:928 #, fuzzy, c-format msgid "cleared inode %\n" msgstr "bereinigter Inode %llu\n" #: .././repair/dino_chunks.c:931 #, fuzzy, c-format msgid "would have cleared inode %\n" msgstr "Inode %llu könnte bereinigt worden sein\n" #: .././repair/dino_chunks.c:1122 .././repair/dino_chunks.c:1157 #: .././repair/dino_chunks.c:1271 msgid "found inodes not in the inode allocation tree\n" msgstr "Inodes wurden nicht im Inode-Allokierungs-Baum gefunden\n" #: .././repair/dinode.c:54 msgid "real-time" msgstr "Echtzeit" #: .././repair/dinode.c:55 msgid "regular" msgstr "regelmäßig" #: .././repair/dinode.c:78 #, fuzzy, c-format msgid "clearing inode % attributes\n" msgstr "Attribute des Inodes %llu werden bereinigt\n" #: .././repair/dinode.c:81 #, fuzzy, c-format msgid "would have cleared inode % attributes\n" msgstr "Attribute des Inodes %llu könnten bereinigt worden sein\n" #: .././repair/dinode.c:444 #, fuzzy, c-format msgid "" "inode % - bad rt extent start block number %, offset " "%\n" msgstr "" "Inode %llu - falsche »rt«-Erweiterungs-Startblock-Nummer %llu,\n" "Versatz %llu\n" #: .././repair/dinode.c:452 #, fuzzy, c-format msgid "" "inode % - bad rt extent last block number %, offset " "%\n" msgstr "" "Inode %llu - falsche »rt«-Erweiterungs-Endblock-Nummer %llu,Versatz %llu\n" #: .././repair/dinode.c:460 #, fuzzy, c-format msgid "" "inode % - bad rt extent overflows - start %, end %, " "offset %\n" msgstr "" "Inode %llu - falsche »rt«-Erweiterungs-Überläufe - Start %llu,\n" "Ende %llu, Versatz %llu\n" #: .././repair/dinode.c:477 #, fuzzy, c-format msgid "malformed rt inode extent [% %] (fs rtext size = %u)\n" msgstr "" "missgebildete »rt«-Inode-Erweiterung [%llu %llu] (fs rtext Größe = %u)\n" #: .././repair/dinode.c:498 #, fuzzy, c-format msgid "" "data fork in rt ino % claims dup rt extent,off - %, start - " "%, count %\n" msgstr "" "Daten-Unterelement in rt ino %llu beansprucht »dup rt«-Erweiterung,aus - " "%llu, Start - %llu, Anzahl %llu\n" #: .././repair/dinode.c:517 #, fuzzy, c-format msgid "bad state in rt block map %\n" msgstr "falscher Status in »rt«-Block-Karte %llu\n" #: .././repair/dinode.c:523 #, fuzzy, c-format msgid "" "data fork in rt inode % found metadata block % in rt bmap\n" msgstr "" "Daten-Unterelement in rt ino %llu fand Metadaten-Block %llu in rt bmap\n" #: .././repair/dinode.c:531 #, fuzzy, c-format msgid "data fork in rt inode % claims used rt block %\n" msgstr "" "Daten-Unterelement in »rt«-Inode %llu beansprucht benutzten\n" "»rt«-Block %llu\n" #: .././repair/dinode.c:537 #, fuzzy, c-format msgid "illegal state %d in rt block map %\n" msgstr "unerlaubter Status %d in »rt«-Block-Karte %llu\n" #: .././repair/dinode.c:600 #, fuzzy, c-format msgid "" "bmap rec out of order, inode % entry %d [o s c] [% % " "%], %d [% % %]\n" msgstr "" "bmap rec außer Betrieb, Inode %llu Eintrag %d [o s c] [%llu %llu %llu], %d " "[%llu %llu %llu]\n" #: .././repair/dinode.c:616 #, fuzzy, c-format msgid "" "zero length extent (off = %, fsbno = %) in ino %\n" msgstr "Länge-Null-Erweiterung (off = %llu, fsbno = %llu) in ino %llu\n" #: .././repair/dinode.c:647 #, fuzzy, c-format msgid "" "inode % - bad extent starting block number %, offset " "%\n" msgstr "Inode %llu - falsche erweiterte Startblock-Nummer %llu, Versatz %llu\n" #: .././repair/dinode.c:655 #, fuzzy, c-format msgid "" "inode % - bad extent last block number %, offset %\n" msgstr "Inode %llu - falsche erweiterte Endblock-Nummer %llu, Versatz %llu\n" #: .././repair/dinode.c:663 #, fuzzy, c-format msgid "" "inode % - bad extent overflows - start %, end %, " "offset %\n" msgstr "" "Inode %llu - falsche Erweiterungs-Überläufe - Start %llu, Ende %llu,\n" "Versatz %llu\n" #: .././repair/dinode.c:675 #, c-format msgid "" "inode % - extent exceeds max offset - start %, count " "%, physical block %\n" msgstr "" #: .././repair/dinode.c:696 #, c-format msgid "" "Fatal error: inode % - blkmap_set_ext(): %s\n" "\t%s fork, off - %, start - %, cnt %\n" msgstr "" #: .././repair/dinode.c:729 #, fuzzy, c-format msgid "" "%s fork in ino % claims dup extent, off - %, start - " "%, cnt %\n" msgstr "" "%s Unterelement in ino %llu beansprucht »dup«-Erweiterung, aus - %llu,\n" "Start - %llu, cnt %llu\n" #: .././repair/dinode.c:748 #, fuzzy, c-format msgid "%s fork in ino % claims free block %\n" msgstr "%s Unterelement in ino %llu beansprucht freien Block %llu\n" #: .././repair/dinode.c:757 #, fuzzy, c-format msgid "bad state in block map %\n" msgstr "falscher Status in Block-Karte %llu\n" #: .././repair/dinode.c:762 msgid "rmap claims metadata use!\n" msgstr "" #: .././repair/dinode.c:768 #, fuzzy, c-format msgid "%s fork in inode % claims metadata block %\n" msgstr "%s Unterelement in Inode %llu beansprucht Metadatenblock %llu\n" #: .././repair/dinode.c:779 #, fuzzy, c-format msgid "%s fork in %s inode % claims used block %\n" msgstr "%s Unterelement in %s Inode %llu beansprucht benutzten Block %llu\n" #: .././repair/dinode.c:785 #, fuzzy, c-format msgid "illegal state %d in block map %\n" msgstr "unerlaubter Status %d im Block-Karte %llu\n" #: .././repair/dinode.c:793 msgid "couldn't add reverse mapping\n" msgstr "" #: .././repair/dinode.c:805 #, fuzzy, c-format msgid "correcting nextents for inode %\n" msgstr "nextents für Inode %llu werden korrigiert, waren %d - gezählt %llu\n" #: .././repair/dinode.c:897 #, fuzzy, c-format msgid "cannot read inode (%u/%u), disk block %\n" msgstr "Inode (%u/%u) kann nicht gelesen werden, Plattenblock %lld\n" #: .././repair/dinode.c:965 #, fuzzy, c-format msgid "bad level %d in inode % bmap btree root block\n" msgstr "falsche Stufe %d im Inode-%llu-»bmap btree«-Wurzelblock\n" #: .././repair/dinode.c:971 #, fuzzy, c-format msgid "bad numrecs 0 in inode % bmap btree root block\n" msgstr "falsche numrecs 0 im Inode-%llu-»bmap btree«-Wurzelblock\n" #: .././repair/dinode.c:980 #, fuzzy, c-format msgid "" "indicated size of %s btree root (%d bytes) greater than space in inode " "% %s fork\n" msgstr "" "angegebene Größe der »%s-btree«-Wurzel (%d Bytes) größer als Platz in Inode " "%llu %s Unterelement\n" #: .././repair/dinode.c:1001 #, fuzzy, c-format msgid "bad bmap btree ptr 0x% in ino %\n" msgstr "falscher bmap btree ptr 0x%llx in ino %llu\n" #: .././repair/dinode.c:1021 #, fuzzy, c-format msgid "" "correcting key in bmbt root (was %, now %) in inode " "% %s fork\n" msgstr "" "Schlüssel in »bmbt«-Wurzel wird korrigiert (war %llu, nun %llu) in Inode\n" "%llu %s Unterelement\n" #: .././repair/dinode.c:1033 #, fuzzy, c-format msgid "" "bad key in bmbt root (is %, would reset to %) in inode " "% %s fork\n" msgstr "" "falscher Schlüssel in »bmbt«-Wurzel (ist %llu, könnte zu %llu\n" "zurückgesetzt werden) in Inode %llu %s Unterelement\n" #: .././repair/dinode.c:1049 #, fuzzy, c-format msgid "out of order bmbt root key % in inode % %s fork\n" msgstr "" "»bmbt«-Wurzel-Schlüssel %llu außer Betrieb in Inode %llu\n" "%s Unterelement\n" #: .././repair/dinode.c:1066 #, fuzzy, c-format msgid "" "extent count for ino % %s fork too low (%) for file format\n" msgstr "Umfanganzahl für ino %lld %s-Fork zu niedrig (%d) für Dateiformat\n" #: .././repair/dinode.c:1077 #, fuzzy, c-format msgid "bad fwd (right) sibling pointer (saw % should be NULLFSBLOCK)\n" msgstr "" "falscher fwd (rechts) Geschwisterzeiger (%llu gesehen könnte NULLFSBLOCK\n" "sein)\n" #: .././repair/dinode.c:1080 #, fuzzy, c-format msgid "\tin inode % (%s fork) bmap btree block %\n" msgstr "\tin Inode %u (%s-Unterelement) bmap btree Block %llu\n" #: .././repair/dinode.c:1162 #, fuzzy, c-format msgid "local inode % data fork is too large (size = %lld, max = %d)\n" msgstr "" "lokales Inode-%llu-Daten-Unterelement ist zu groß (Größe = %lld, max = %d)\n" #: .././repair/dinode.c:1170 #, fuzzy, c-format msgid "local inode % attr fork too large (size %d, max = %d)\n" msgstr "" "lokales Inode-%llu-attr-Unterelement ist zu groß (Größe = %d, max = %d)\n" #: .././repair/dinode.c:1177 #, fuzzy, c-format msgid "local inode % attr too small (size = %d, min size = %zd)\n" msgstr "" "lokales Inode-%llu-attr-Unterelement ist zu klein (Größe = %d, min = %d)\n" #: .././repair/dinode.c:1201 #, fuzzy, c-format msgid "" "mismatch between format (%d) and size (%) in symlink ino %\n" msgstr "" "Ungleichheit zwischen Format (%d) und Größe (%lld) in symbolischer\n" "Verknüpfung ino %llu\n" #: .././repair/dinode.c:1208 #, fuzzy, c-format msgid "" "mismatch between format (%d) and size (%) in symlink inode " "%\n" msgstr "" "Ungleichheit zwischen Format (%d) und Größe (%lld) in symbolischer\n" "Verknüpfung Inode %llu\n" #: .././repair/dinode.c:1223 #, fuzzy, c-format msgid "bad number of extents (%d) in symlink % data fork\n" msgstr "" "falsche Anzahl von Ausweitungen (%d) in symbolischem Verweis %llu\n" "des Datenunterelements\n" #: .././repair/dinode.c:1235 #, fuzzy, c-format msgid "bad extent #%d offset (%) in symlink % data fork\n" msgstr "" "falscher Umfang #%d Versatz (%llu) in symbolischem Verweis %llu\n" "des Datenunterelements\n" #: .././repair/dinode.c:1241 #, fuzzy, c-format msgid "bad extent #%d count (%) in symlink % data fork\n" msgstr "" "falsche Umfang #%d Anzahl (%llu) in symbolischem Verweis %llu des\n" "Datenunterelements\n" #: .././repair/dinode.c:1299 #, fuzzy, c-format msgid "cannot read inode %, file block %d, NULL disk block\n" msgstr "" "Inode %llu kann nicht gelesen werden, Dateiblock %d, Plattenblock %llu\n" #: .././repair/dinode.c:1321 #, fuzzy, c-format msgid "cannot read inode %, file block %d, disk block %\n" msgstr "" "Inode %llu kann nicht gelesen werden, Dateiblock %d, Plattenblock %llu\n" #: .././repair/dinode.c:1327 #, c-format msgid "" "Bad symlink buffer CRC, block %, inode %.\n" "Correcting CRC, but symlink may be bad.\n" msgstr "" #: .././repair/dinode.c:1340 #, fuzzy, c-format msgid "bad symlink header ino %, file block %d, disk block %\n" msgstr "" "Inode %llu kann nicht gelesen werden, Dateiblock %d, Plattenblock %llu\n" #: .././repair/dinode.c:1383 #, fuzzy, c-format msgid "symlink in inode % too long (%llu chars)\n" msgstr "symbolischer Verweis in Inode %llu zu lang (%lld Zeichen)\n" #: .././repair/dinode.c:1415 #, fuzzy, c-format msgid "found illegal null character in symlink inode %\n" msgstr "" "unerlaubtes Null-Zeichen gefunden in symbolischem Verweis zu Inode %llu\n" #: .././repair/dinode.c:1440 #, fuzzy, c-format msgid "inode % has bad inode type (IFMNT)\n" msgstr "Inode %llu hat falschen Inode-Typ (IFMNT)\n" #: .././repair/dinode.c:1451 #, fuzzy, c-format msgid "size of character device inode % != 0 (% bytes)\n" msgstr "" "Größe des Inodes %llu des zeichenorientierten Gerätes !=0 (%lld Bytes)\n" #: .././repair/dinode.c:1456 #, fuzzy, c-format msgid "size of block device inode % != 0 (% bytes)\n" msgstr "Größe des Inodes %llu des blockorientierten Gerätes !=0 (%lld Bytes)\n" #: .././repair/dinode.c:1461 #, fuzzy, c-format msgid "size of socket inode % != 0 (% bytes)\n" msgstr "Größe des Socket-Inodes %llu !=0 (%lld Bytes)\n" #: .././repair/dinode.c:1466 #, fuzzy, c-format msgid "size of fifo inode % != 0 (% bytes)\n" msgstr "Größe des fifo-Inodes %llu !=0 (%lld Bytes)\n" #: .././repair/dinode.c:1470 #, c-format msgid "Internal error - process_misc_ino_types, illegal type %d\n" msgstr "Interner Fehler - process_misc_ino_types, unerlaubter Typ %d\n" #: .././repair/dinode.c:1497 #, fuzzy, c-format msgid "size of character device inode % != 0 (% blocks)\n" msgstr "" "Größe des Inodes %llu des zeichenorientierten Gerätes !=0 (%llu Bytes)\n" #: .././repair/dinode.c:1502 #, fuzzy, c-format msgid "size of block device inode % != 0 (% blocks)\n" msgstr "Größe des Inodes %llu des blockorientierten Gerätes !=0 (%llu Bytes)\n" #: .././repair/dinode.c:1507 #, fuzzy, c-format msgid "size of socket inode % != 0 (% blocks)\n" msgstr "Größe des Socket-Inodes %llu !=0 (%llu Bytes)\n" #: .././repair/dinode.c:1512 #, fuzzy, c-format msgid "size of fifo inode % != 0 (% blocks)\n" msgstr "Größe des fifo-Inodes %llu !=0 (%llu Bytes)\n" #: .././repair/dinode.c:1590 #, fuzzy, c-format msgid "root inode % has bad type 0x%x\n" msgstr "Wurzel-Inode %llu hat falschen Typ 0x%x\n" #: .././repair/dinode.c:1594 msgid "resetting to directory\n" msgstr "Verzeichnis wird zurückgesetzt\n" #: .././repair/dinode.c:1598 msgid "would reset to directory\n" msgstr "Verzeichnis könnte zurückgesetzt werden\n" #: .././repair/dinode.c:1604 #, fuzzy, c-format msgid "user quota inode % has bad type 0x%x\n" msgstr "Benutzer-Quota-Inode %llu hat falschen Typ 0x%x\n" #: .././repair/dinode.c:1613 #, fuzzy, c-format msgid "group quota inode % has bad type 0x%x\n" msgstr "Gruppen-Quota-Inode %llu hat falschen Typ 0x%x\n" #: .././repair/dinode.c:1622 #, fuzzy, c-format msgid "project quota inode % has bad type 0x%x\n" msgstr "Gruppen-Quota-Inode %llu hat falschen Typ 0x%x\n" #: .././repair/dinode.c:1632 #, fuzzy, c-format msgid "realtime summary inode % has bad type 0x%x, " msgstr "Echtzeit-Summen-Inode %llu hat falschen Typ 0x%x, " #: .././repair/dinode.c:1635 .././repair/dinode.c:1656 msgid "resetting to regular file\n" msgstr "es wird auf normale Datei zurückgesetzt\n" #: .././repair/dinode.c:1639 .././repair/dinode.c:1660 msgid "would reset to regular file\n" msgstr "es könnte auf normale Datei zurückgesetzt werden\n" #: .././repair/dinode.c:1644 #, fuzzy, c-format msgid "bad # of extents (%u) for realtime summary inode %\n" msgstr "falsche # des Umfangs (%u) für Echtzeit-Summen-Inode %llu\n" #: .././repair/dinode.c:1653 #, fuzzy, c-format msgid "realtime bitmap inode % has bad type 0x%x, " msgstr "Echtzeit-Bitmap-Inode %llu hat falschen Typ 0x%x, " #: .././repair/dinode.c:1665 #, fuzzy, c-format msgid "bad # of extents (%u) for realtime bitmap inode %\n" msgstr "falsche # von Extents (%u) für Echtzeit-Bitmap-Inode %llu\n" #: .././repair/dinode.c:1700 #, fuzzy, c-format msgid "" "mismatch between format (%d) and size (%) in directory ino " "%\n" msgstr "" "Unterschied zwischen Format (%d) und Größe (%lld) im Verzeichnis ino %llu\n" #: .././repair/dinode.c:1706 #, fuzzy, c-format msgid "directory inode % has bad size %\n" msgstr "Verzeichnis-Inode %llu hat falsche Größe %lld\n" #: .././repair/dinode.c:1714 #, fuzzy, c-format msgid "bad data fork in symlink %\n" msgstr "falsches Daten-Unterelement in symbolischem Verweis %llu\n" #: .././repair/dinode.c:1735 #, fuzzy, c-format msgid "found inode % claiming to be a real-time file\n" msgstr "gefundener Inode %llu beansprucht, eine Echtzeit-Datei zu sein\n" #: .././repair/dinode.c:1744 #, fuzzy, c-format msgid "" "realtime bitmap inode % has bad size % (should be " "%)\n" msgstr "Echtzeit-Bitmap-Inode %llu hat falsche Größe %lld (sollte %lld sein)\n" #: .././repair/dinode.c:1755 #, fuzzy, c-format msgid "" "realtime summary inode % has bad size % (should be %d)\n" msgstr "Echtzeit-Summen-Inode %llu hat falsche Größe %lld (könnte %d sein)\n" #: .././repair/dinode.c:1783 #, fuzzy, c-format msgid "bad attr fork offset %d in dev inode %, should be %d\n" msgstr "" "falscher attr-Unterelement-Versatz %d in dev-Inode %llu, könnte %d sein\n" #: .././repair/dinode.c:1795 #, fuzzy, c-format msgid "bad attr fork offset %d in inode %, max=%d\n" msgstr "falscher attr-Unterelement-Versatz %d in Inode %llu, maximal=%d\n" #: .././repair/dinode.c:1802 #, c-format msgid "unexpected inode format %d\n" msgstr "unerwartetes Inode-Format %d\n" #: .././repair/dinode.c:1823 #, fuzzy, c-format msgid "correcting nblocks for inode %, was %llu - counted %\n" msgstr "nblocks für Inode %llu werden korrigiert, war %llu - gezählt %llu\n" #: .././repair/dinode.c:1830 #, fuzzy, c-format msgid "bad nblocks %llu for inode %, would reset to %\n" msgstr "" "falsche nblocks %llu für Inode %llu, könnte auf %llu zurückgesetzt werden\n" #: .././repair/dinode.c:1838 #, fuzzy, c-format msgid "too many data fork extents (%) in inode %\n" msgstr "zu großes Daten-Unterelement-Ausmaß (%llu) in Inode %llu\n" #: .././repair/dinode.c:1845 #, fuzzy, c-format msgid "correcting nextents for inode %, was %d - counted %\n" msgstr "nextents für Inode %llu werden korrigiert, waren %d - gezählt %llu\n" #: .././repair/dinode.c:1853 #, fuzzy, c-format msgid "bad nextents %d for inode %, would reset to %\n" msgstr "" "falsche nextents %d für Inode %llu, könnten auf %llu zurückgesetzt\n" "werden\n" #: .././repair/dinode.c:1861 #, fuzzy, c-format msgid "too many attr fork extents (%) in inode %\n" msgstr "zu großes Daten-Unterelement-Ausmaß (%llu) in Inode %llu\n" #: .././repair/dinode.c:1868 #, fuzzy, c-format msgid "correcting anextents for inode %, was %d - counted %\n" msgstr "anextents für Inode %llu werden korrigiert, waren %d - gezählt %llu\n" #: .././repair/dinode.c:1875 #, fuzzy, c-format msgid "bad anextents %d for inode %, would reset to %\n" msgstr "" "falsche anextents %d für Inode %llu, könnten auf %llu zurückgesetzt\n" "werden\n" #: .././repair/dinode.c:1887 #, c-format msgid "nblocks (%) smaller than nextents for inode %\n" msgstr "" #: .././repair/dinode.c:1952 .././repair/dinode.c:1990 #, fuzzy, c-format msgid "unknown format %d, ino % (mode = %d)\n" msgstr "unbekanntes Format %d, ino %llu (Modus = %d)\n" #: .././repair/dinode.c:1957 #, fuzzy, c-format msgid "bad data fork in inode %\n" msgstr "falsches Daten-Unterelement in Inode %llu\n" #: .././repair/dinode.c:2028 #, fuzzy, c-format msgid "bad attribute format %d in inode %, " msgstr "falsches Attribut-Format %d in Inode %llu, " #: .././repair/dinode.c:2031 msgid "resetting value\n" msgstr "Wert wird zurückgesetzt\n" #: .././repair/dinode.c:2035 msgid "would reset value\n" msgstr "Wert könnte zurückgesetzt werden\n" #: .././repair/dinode.c:2080 #, fuzzy, c-format msgid "bad attribute fork in inode %" msgstr "falsches Attribut-Unterelement in Inode %llu" #: .././repair/dinode.c:2084 msgid ", clearing attr fork\n" msgstr ", bereinige attr-Unterelement\n" #: .././repair/dinode.c:2093 msgid ", would clear attr fork\n" msgstr ", könnte attr-Unterelement bereinigen\n" #: .././repair/dinode.c:2121 #, fuzzy, c-format msgid "illegal attribute fmt %d, ino %\n" msgstr "unerlaubtes Attribut fmt %d, ino %llu\n" #: .././repair/dinode.c:2141 #, fuzzy, c-format msgid "problem with attribute contents in inode %\n" msgstr "Problem mit Attributs-Inhalt in Inode %llu\n" #: .././repair/dinode.c:2149 msgid "would clear attr fork\n" msgstr "könnte attr-Unterelement bereinigen\n" #: .././repair/dinode.c:2182 #, fuzzy, c-format msgid "" "clearing obsolete nlink field in version 2 inode %, was %d, now 0\n" msgstr "" "überflüssiges nlink-Feld in Version-2-Inode %llu wurde bereinigt, war %d,\n" "nun 0\n" #: .././repair/dinode.c:2188 #, fuzzy, c-format msgid "" "would clear obsolete nlink field in version 2 inode %, currently %d\n" msgstr "" "überflüssiges nlink-Feld in Version-2-Inode %llu könnte bereinigt werden,\n" "aktuell %d\n" #: .././repair/dinode.c:2267 #, c-format msgid "bad CRC for inode %%c" msgstr "" #: .././repair/dinode.c:2271 msgid " will rewrite\n" msgstr "" #: .././repair/dinode.c:2274 #, fuzzy msgid " would rewrite\n" msgstr "Tabelle könnte repariert werden\n" #: .././repair/dinode.c:2281 #, fuzzy, c-format msgid "bad magic number 0x%x on inode %%c" msgstr "falsche magische Nummer 0x%x auf Inode %llu%c" #: .././repair/dinode.c:2286 msgid " resetting magic number\n" msgstr " magische Nummer wird zurückgesetzt\n" #: .././repair/dinode.c:2290 msgid " would reset magic number\n" msgstr " magische Nummer würde zurückgesetzt\n" #: .././repair/dinode.c:2297 #, fuzzy, c-format msgid "bad version number 0x%x on inode %%c" msgstr "falsche Versionsnummer 0x%x auf Inode %llu%c" #: .././repair/dinode.c:2302 msgid " resetting version number\n" msgstr " Versionsnummer wird zurückgesetzt\n" #: .././repair/dinode.c:2307 msgid " would reset version number\n" msgstr " Versionsnummer könnte zurückgesetzt werden\n" #: .././repair/dinode.c:2320 #, c-format msgid "inode identifier %llu mismatch on inode %\n" msgstr "" #: .././repair/dinode.c:2330 #, c-format msgid "UUID mismatch on inode %\n" msgstr "" #: .././repair/dinode.c:2343 #, fuzzy, c-format msgid "bad (negative) size % on inode %\n" msgstr "falsche (negative) Größe %lld auf Inode %llu\n" #: .././repair/dinode.c:2376 #, fuzzy, c-format msgid "imap claims a free inode % is in use, " msgstr "imap beansprucht einen freien Inode, %llu ist in Benutzung" #: .././repair/dinode.c:2378 msgid "correcting imap and clearing inode\n" msgstr "imap wird korrigiert und Inode bereinigt\n" #: .././repair/dinode.c:2382 msgid "would correct imap and clear inode\n" msgstr "imap könnte korrigiert und Inode bereinigt werden\n" #: .././repair/dinode.c:2399 #, fuzzy, c-format msgid "bad inode format in inode %\n" msgstr "falsches Inode-Format in Inode %llu\n" #: .././repair/dinode.c:2415 #, c-format msgid "Bad flags set in inode %\n" msgstr "" #: .././repair/dinode.c:2426 #, c-format msgid "inode % has RT flag set but there is no RT device\n" msgstr "" #: .././repair/dinode.c:2438 #, c-format msgid "inode % not rt bitmap\n" msgstr "" #: .././repair/dinode.c:2452 #, fuzzy, c-format msgid "directory flags set on non-directory inode %\n" msgstr "falscher Verzeichnis-btree für Verzeichnis-Inode %llu\n" #: .././repair/dinode.c:2466 #, c-format msgid "file flags set on non-file inode %\n" msgstr "" #: .././repair/dinode.c:2475 msgid "fixing bad flags.\n" msgstr "" #: .././repair/dinode.c:2479 #, fuzzy msgid "would fix bad flags.\n" msgstr "falscher sb für ag %d könnte zurückgesetzt werden\n" #: .././repair/dinode.c:2494 #, c-format msgid "Bad flags2 set in inode %\n" msgstr "" #: .././repair/dinode.c:2504 #, c-format msgid "" "inode % is marked reflinked but file system does not support " "reflink\n" msgstr "" #: .././repair/dinode.c:2515 #, c-format msgid "reflink flag set on non-file inode %\n" msgstr "" #: .././repair/dinode.c:2526 #, c-format msgid "Cannot have a reflinked realtime inode %\n" msgstr "" #: .././repair/dinode.c:2536 #, c-format msgid "" "inode % has CoW extent size hint but file system does not support " "reflink\n" msgstr "" #: .././repair/dinode.c:2547 #, c-format msgid "CoW extent size flag set on non-file, non-directory inode %\n" msgstr "" #: .././repair/dinode.c:2558 #, c-format msgid "Cannot have CoW extent size hint on a realtime inode %\n" msgstr "" #: .././repair/dinode.c:2566 msgid "fixing bad flags2.\n" msgstr "" #: .././repair/dinode.c:2570 msgid "would fix bad flags2.\n" msgstr "" #: .././repair/dinode.c:2621 #, fuzzy, c-format msgid "bad inode type %#o inode %\n" msgstr "falscher Inode-Typ %#o Inode %llu\n" #: .././repair/dinode.c:2645 #, fuzzy, c-format msgid "bad non-zero extent size %u for non-realtime/extsize inode %, " msgstr "falsches Nicht-Null-Ausmaß %u für Nicht-Echtzeit/extsize Inode %llu, " #: .././repair/dinode.c:2648 .././repair/dinode.c:2671 msgid "resetting to zero\n" msgstr "wird auf Null zurückgesetzt\n" #: .././repair/dinode.c:2652 .././repair/dinode.c:2675 msgid "would reset to zero\n" msgstr "könnte auf Null zurückgesetzt werden\n" #: .././repair/dinode.c:2668 #, fuzzy, c-format msgid "" "Cannot have non-zero CoW extent size %u on non-cowextsize inode %, " msgstr "falsches Nicht-Null-Ausmaß %u für Nicht-Echtzeit/extsize Inode %llu, " #: .././repair/dinode.c:2734 #, fuzzy, c-format msgid "problem with directory contents in inode %\n" msgstr "Problem mit Verzeichnis-Inhalt in Inode %llu\n" #: .././repair/dinode.c:2742 #, fuzzy, c-format msgid "problem with symbolic link in inode %\n" msgstr "Problem mit symbolischem Verweis in Inode %llu\n" #: .././repair/dinode.c:2837 #, c-format msgid "processing inode %d/%d\n" msgstr "Inode %d/%d wird verarbeitet\n" #: .././repair/dir2.c:50 #, fuzzy, c-format msgid "malloc failed (%zu bytes) dir2_add_badlist:ino %\n" msgstr "malloc fehlgeschlagen (%u Bytes) dir2_add_badlist:ino %llu\n" #: .././repair/dir2.c:93 msgid "couldn't malloc dir2 shortform copy\n" msgstr "malloc dir2 Kurzformkopie kann nicht durchgeführt werden\n" #: .././repair/dir2.c:229 msgid "current" msgstr "aktuell" #: .././repair/dir2.c:232 .././repair/dir2.c:693 msgid "invalid" msgstr "ungültig" #: .././repair/dir2.c:235 .././repair/dir2.c:695 msgid "realtime bitmap" msgstr "Echtzeit-Bitmap" #: .././repair/dir2.c:238 .././repair/dir2.c:697 msgid "realtime summary" msgstr "Echtzeit-Zusammenfassung" #: .././repair/dir2.c:241 .././repair/dir2.c:699 msgid "user quota" msgstr "Benutzer-Quota" #: .././repair/dir2.c:244 .././repair/dir2.c:701 msgid "group quota" msgstr "Gruppen-Quota" #: .././repair/dir2.c:247 .././repair/dir2.c:703 #, fuzzy msgid "project quota" msgstr " (Projekt %u" #: .././repair/dir2.c:265 .././repair/dir2.c:733 msgid "free" msgstr "frei" #: .././repair/dir2.c:282 .././repair/dir2.c:713 msgid "non-existent" msgstr "nicht existent" #: .././repair/dir2.c:287 #, fuzzy, c-format msgid "" "entry \"%*.*s\" in shortform directory % references %s inode " "%\n" msgstr "" "Eintrag »%*.*s« in Kurzform-Verzeichnis %llu verweist auf %s Inode %llu\n" #: .././repair/dir2.c:293 msgid "is zero length" msgstr "" #: .././repair/dir2.c:298 msgid "extends past end of dir" msgstr "" #: .././repair/dir2.c:304 #, fuzzy, c-format msgid "entry #%d %s in shortform dir %" msgstr "Eintrag der Länge Null in Kurzform dir %llu" #: .././repair/dir2.c:307 #, c-format msgid ", junking %d entries\n" msgstr ", %d Einträge werden verworfen\n" #: .././repair/dir2.c:310 #, c-format msgid ", would junk %d entries\n" msgstr ", %d Einträge könnten verworfen werden\n" #: .././repair/dir2.c:330 #, fuzzy, c-format msgid "entry contains illegal character in shortform dir %\n" msgstr "Eintrag enthält unerlaubtes Zeichen in Kurzform-dir %llu\n" #: .././repair/dir2.c:337 #, fuzzy, c-format msgid "entry contains offset out of order in shortform dir %\n" msgstr "Eintrag enthält Versatz außer Betrieb in Kurzform-dir %llu\n" #: .././repair/dir2.c:394 #, fuzzy, c-format msgid "junking entry \"%s\" in directory inode %\n" msgstr "Eintrag »%s« in Verzeichnis-Inode %llu wird verworfen\n" #: .././repair/dir2.c:398 #, fuzzy, c-format msgid "would have junked entry \"%s\" in directory inode %\n" msgstr "Eintrag »%s« in Verzeichnis-Inode %llu könnte verworfen worden sein\n" #: .././repair/dir2.c:423 #, fuzzy, c-format msgid "would have corrected entry count in directory % from %d to %d\n" msgstr "" "Eintragsanzahl könnte im Verzeichnis %llu von %d auf %d korrigiert\n" "worden sein\n" #: .././repair/dir2.c:427 #, fuzzy, c-format msgid "corrected entry count in directory %, was %d, now %d\n" msgstr "berichtigte Eintragsanzahl im Verzeichnis %llu, war %d, nun %d\n" #: .././repair/dir2.c:438 #, fuzzy, c-format msgid "would have corrected i8 count in directory % from %d to %d\n" msgstr "" "i8-Anzahl in Verzeichnis %llu könnte von %d auf %d berichtigt worden sein\n" #: .././repair/dir2.c:442 #, fuzzy, c-format msgid "corrected i8 count in directory %, was %d, now %d\n" msgstr "i8-Anzahl in Verzeichnis %llu wurde berichtigt, war %d, nun %d\n" #: .././repair/dir2.c:456 #, fuzzy, c-format msgid "" "would have corrected directory % size from % to %\n" msgstr "" "Größe des Verzeichnisses %llu könnte von %lld auf %lld berichtigt worden\n" "sein\n" #: .././repair/dir2.c:461 #, fuzzy, c-format msgid "corrected directory % size, was %, now %\n" msgstr "Größe des Verzeichnisses %llu berichtigt, war %lld, nun %lld\n" #: .././repair/dir2.c:473 #, fuzzy, c-format msgid "directory % offsets too high\n" msgstr "Verzeichnis %llu Versätze zu groß\n" #: .././repair/dir2.c:479 #, fuzzy, c-format msgid "would have corrected entry offsets in directory %\n" msgstr "Eintrags-Versätze in Verzeichnis %llu könnten berichtigt worden sein\n" #: .././repair/dir2.c:483 #, fuzzy, c-format msgid "corrected entry offsets in directory %\n" msgstr "Eintrags-Versätze in Verzeichnis %llu wurden berichtigt\n" #: .././repair/dir2.c:502 #, fuzzy, c-format msgid "bogus .. inode number (%) in directory inode %, " msgstr "fingiert .. Inode-Nummer (%llu) in Verzeichnis-Inode %llu, " #: .././repair/dir2.c:506 .././repair/dir2.c:541 msgid "clearing inode number\n" msgstr "Inode-Nummer wird bereinigt\n" #: .././repair/dir2.c:512 .././repair/dir2.c:547 msgid "would clear inode number\n" msgstr "Inode-Nummer könnte bereinigt werden\n" #: .././repair/dir2.c:520 #, fuzzy, c-format msgid "" "corrected root directory % .. entry, was %, now %\n" msgstr "Wurzel-Verzeichnis %llu berichtigt .. Eintrag war %llu, nun %llu\n" #: .././repair/dir2.c:528 #, fuzzy, c-format msgid "" "would have corrected root directory % .. entry from % to " "%\n" msgstr "" "Wurzel-Verzeichnis %llu könnte berichtigt worden sein .. Eintrag von\n" "%llu zu %llu\n" #: .././repair/dir2.c:538 #, fuzzy, c-format msgid "bad .. entry in directory inode %, points to self, " msgstr "falscher .. Eintrag in Verzeichnis-Inode %llu, zeigt auf sich selbst, " #: .././repair/dir2.c:651 #, fuzzy, c-format msgid "corrupt block %u in directory inode %\n" msgstr "kaputter Block %u in Verzeichnis-Inode %llu\n" #: .././repair/dir2.c:654 msgid "\twill junk block\n" msgstr "\tBlock wird weggeworfen\n" #: .././repair/dir2.c:656 msgid "\twould junk block\n" msgstr "\tBlock könnte weggeworfen werden\n" #: .././repair/dir2.c:742 #, fuzzy, c-format msgid "" "entry \"%*.*s\" at block %d offset % in directory inode % " "references %s inode %\n" msgstr "" "Eintrag »%*.*s« in Block %u Versatz %d in Verzeichnis-Inode %llu bezieht\n" "sich auf %s Inode %llu\n" #: .././repair/dir2.c:765 #, fuzzy, c-format msgid "" "entry at block %u offset % in directory inode %has 0 " "namelength\n" msgstr "" "Eintrag in Block %u Versatz %d in Verzeichnis-Inode %llu hat\n" "Namenslänge 0\n" #: .././repair/dir2.c:778 #, fuzzy, c-format msgid "\tclearing inode number in entry at offset %...\n" msgstr "\t Inode-Nummer im Eintrag bei Versatz %d wird bereinigt...\n" #: .././repair/dir2.c:784 #, fuzzy, c-format msgid "\twould clear inode number in entry at offset %...\n" msgstr "\t Inode-Nummer im Eintrag bei Versatz %d könnte bereinigt werden...\n" #: .././repair/dir2.c:797 #, fuzzy, c-format msgid "" "entry at block %u offset % in directory inode % has illegal " "name \"%*.*s\": " msgstr "" "Eintrag in Block %u Versatz %d in Verzeichnis-Inode %llu hat unerlaubten\n" "Namen »%*.*s«: " #: .././repair/dir2.c:828 #, fuzzy, c-format msgid "bad .. entry in directory inode %, points to self: " msgstr "falscher .. Eintrag in Verzeichnis-Inode %llu zeigt auf sich selbst: " #: .././repair/dir2.c:839 #, fuzzy, c-format msgid "bad .. entry in root directory inode %, was %: " msgstr "falscher .. Eintrag in Wurzelverzeichnis-Inode %llu, war %llu: " #: .././repair/dir2.c:842 .././repair/dir2.c:875 .././repair/phase2.c:217 #: .././repair/phase2.c:226 .././repair/phase2.c:235 msgid "correcting\n" msgstr "wird berichtigt\n" #: .././repair/dir2.c:846 .././repair/dir2.c:879 .././repair/phase2.c:219 #: .././repair/phase2.c:228 .././repair/phase2.c:237 msgid "would correct\n" msgstr "könnte berichtigt werden\n" #: .././repair/dir2.c:859 #, fuzzy, c-format msgid "multiple .. entries in directory inode %: " msgstr "mehrere .. Einträge in Verzeichnis-Inode %llu: " #: .././repair/dir2.c:872 #, fuzzy, c-format msgid "bad . entry in directory inode %, was %: " msgstr "falscher . Eintrag in Verzeichnis-Inode %llu, war %llu: " #: .././repair/dir2.c:884 #, fuzzy, c-format msgid "multiple . entries in directory inode %: " msgstr "mehrere . Einträge in Verzeichnis-Inode %llu: " #: .././repair/dir2.c:894 #, fuzzy, c-format msgid "entry \"%*.*s\" in directory inode % points to self: " msgstr "Eintrag »%*.*s« in Verzeichnis-Inode %llu zeigt auf sich selbst: " #: .././repair/dir2.c:905 msgid "clearing entry\n" msgstr "Eintrag wird bereinigt\n" #: .././repair/dir2.c:907 msgid "would clear entry\n" msgstr "Eintrag könnte gelöscht werden\n" #: .././repair/dir2.c:920 #, fuzzy, c-format msgid "bad bestfree table in block %u in directory inode %: " msgstr "falsche bestfree-Tabelle in Block %u in Verzeichnis-Inode %llu: " #: .././repair/dir2.c:923 msgid "repairing table\n" msgstr "Tabelle wird repariert\n" #: .././repair/dir2.c:928 msgid "would repair table\n" msgstr "Tabelle könnte repariert werden\n" #: .././repair/dir2.c:968 #, fuzzy, c-format msgid "block %u for directory inode % is missing\n" msgstr "Block %u für Verzeichnis-Inode %llu fehlt\n" #: .././repair/dir2.c:977 #, fuzzy, c-format msgid "can't read block %u for directory inode %\n" msgstr "Block %u für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #: .././repair/dir2.c:988 #, fuzzy, c-format msgid "" "bad directory block magic # %#x in block %u for directory inode %\n" msgstr "" "falscher Verzeichnisblock magische # %#x in Block %u für\n" "Verzeichnis-Inode %llu\n" #: .././repair/dir2.c:1040 #, fuzzy, c-format msgid "bad entry count in block %u of directory inode %\n" msgstr "falsche Eintragsanzahl in Block %u des Verzeichnis-Inodes %llu\n" #: .././repair/dir2.c:1048 #, fuzzy, c-format msgid "bad hash ordering in block %u of directory inode %\n" msgstr "falsche Hash-Reihenfolge in Block %u von Verzeichnis-Inode %llu\n" #: .././repair/dir2.c:1056 #, fuzzy, c-format msgid "bad stale count in block %u of directory inode %\n" msgstr "falsche Stale-Anzahl in Block %u von Verzeichnis-Inode %llu\n" #: .././repair/dir2.c:1105 #, fuzzy, c-format msgid "can't map block %u for directory inode %\n" msgstr "Block %u für Verzeichnis-Inode %llu kann nicht kartiert werden\n" #: .././repair/dir2.c:1115 #, fuzzy, c-format msgid "can't read file block %u for directory inode %\n" msgstr "Dateiblock %u für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #: .././repair/dir2.c:1127 #, fuzzy, c-format msgid "bad directory leaf magic # %#x for directory inode % block %u\n" msgstr "" "falsches Verzeichnisblatt magische # %#x für Verzeichnis-Inode %llu Block " "%u\n" #: .././repair/dir2.c:1155 #, fuzzy, c-format msgid "bad sibling back pointer for block %u in directory inode %\n" msgstr "" "falscher Geschwister-Rückwärts-Zeiger für Block %u in\n" "Verzeichnis-Inode %llu\n" #: .././repair/dir2.c:1186 #, fuzzy, c-format msgid "bad hash path in directory %\n" msgstr "falscher Hash-Pfad in Verzeichnis %llu\n" #: .././repair/dir2.c:1296 #, fuzzy, c-format msgid "block % for directory inode % is missing\n" msgstr "Block %u für Verzeichnis-Inode %llu fehlt\n" #: .././repair/dir2.c:1305 #, fuzzy, c-format msgid "can't read block % for directory inode %\n" msgstr "Block %u für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #: .././repair/dir2.c:1313 #, fuzzy, c-format msgid "" "bad directory block magic # %#x in block % for directory inode " "%\n" msgstr "" "falscher Verzeichnisblock magische # %#x in Block %u für\n" "Verzeichnis-Inode %llu\n" #: .././repair/dir2.c:1394 #, fuzzy, c-format msgid "bad size/format for directory %\n" msgstr "falsche Größe/Format für Verzeichnis %llu\n" #: .././repair/dir2.c:1401 #, fuzzy, c-format msgid "no . entry for directory %\n" msgstr "kein . Eintrag für Verzeichnis %llu\n" #: .././repair/dir2.c:1411 #, fuzzy, c-format msgid "no .. entry for directory %\n" msgstr "kein .. Eintrag für Verzeichnis %llu\n" #: .././repair/dir2.c:1413 #, fuzzy, c-format msgid "no .. entry for root directory %\n" msgstr "kein .. Eintrag für Wurzelverzeichnis %llu\n" #: .././repair/incore.c:230 #, fuzzy, c-format msgid "couldn't allocate realtime block map, size = %\n" msgstr "Echtzeit-Blockkarten können nicht alloziert werden, Größe = %llu\n" #: .././repair/incore.c:295 #, fuzzy msgid "couldn't allocate block map btree roots\n" msgstr "Blockkarten-Zeiger können nicht alloziert werden\n" #: .././repair/incore.c:299 msgid "couldn't allocate block map locks\n" msgstr "Blockkarten-Sperren können nicht alloziert werden\n" #: .././repair/incore_ext.c:135 .././repair/incore_ext.c:562 #, fuzzy msgid "couldn't allocate new extent descriptor.\n" msgstr "neue Umfang-Deskriptoren können nicht alloziert werden.\n" #: .././repair/incore_ext.c:232 msgid "duplicate bno extent range\n" msgstr "doppelter bno-Umfangs-Bereich\n" #: .././repair/incore_ext.c:369 msgid ": duplicate bno extent range\n" msgstr ": doppelter bno-Umfangs-Bereich\n" #: .././repair/incore_ext.c:644 .././repair/incore_ext.c:699 msgid "duplicate extent range\n" msgstr "doppelter Umfangs-Bereich\n" #: .././repair/incore_ext.c:752 .././repair/incore_ext.c:756 msgid "couldn't malloc dup extent tree descriptor table\n" msgstr "" "malloc dup extent konnte nicht für Baum-Deskriptor-Tabelle ausgeführt\n" "werden\n" #: .././repair/incore_ext.c:761 msgid "couldn't malloc free by-bno extent tree descriptor table\n" msgstr "" "malloc free by-bno extent konnte nicht für Baum-Deskriptor-Tabelle\n" "ausgeführt werden\n" #: .././repair/incore_ext.c:766 msgid "couldn't malloc free by-bcnt extent tree descriptor table\n" msgstr "" "malloc free by-bcnt extent konnte nicht für Baum-Deskriptor-Tabelle\n" "ausgeführt werden\n" #: .././repair/incore_ext.c:772 msgid "couldn't malloc bno extent tree descriptor\n" msgstr "malloc bno extent konnte nicht für Baum-Deskriptor ausgeführt werden\n" #: .././repair/incore_ext.c:776 msgid "couldn't malloc bcnt extent tree descriptor\n" msgstr "" "malloc bcnt extent konnte nicht für Baum-Deskriptor ausgeführt werden\n" #: .././repair/incore_ext.c:787 msgid "couldn't malloc dup rt extent tree descriptor\n" msgstr "" "malloc dup rt extent konnte nicht für Baum-Deskriptor ausgeführt werden\n" #: .././repair/incore_ino.c:47 msgid "could not allocate nlink array\n" msgstr "nlink-Matrix kann nicht alloziert werden.\n" #: .././repair/incore_ino.c:225 #, fuzzy msgid "could not allocate ftypes array\n" msgstr "nlink-Matrix kann nicht alloziert werden.\n" #: .././repair/incore_ino.c:251 msgid "inode map malloc failed\n" msgstr "Inode map malloc fehlgeschlagen\n" #: .././repair/incore_ino.c:367 msgid "add_aginode_uncertain - duplicate inode range\n" msgstr "add_aginode_uncertain - doppelter Inode-Bereich\n" #: .././repair/incore_ino.c:462 msgid "add_inode - duplicate inode range\n" msgstr "add_inode - doppelter Inode-Bereich\n" #: .././repair/incore_ino.c:556 #, c-format msgid "good inode list is --\n" msgstr "gute Inode-Liste ist --\n" #: .././repair/incore_ino.c:559 #, c-format msgid "uncertain inode list is --\n" msgstr "unsichere Inode-Liste ist --\n" #: .././repair/incore_ino.c:564 #, c-format msgid "agno %d -- no inodes\n" msgstr "agno %d -- keine Inodes\n" #: .././repair/incore_ino.c:568 #, c-format msgid "agno %d\n" msgstr "agno %d\n" #: .././repair/incore_ino.c:572 #, c-format msgid "\tptr = %lx, start = 0x%x, free = 0x%llx, confirmed = 0x%llx\n" msgstr "\tptr = %lx, Start = 0x%x, frei = 0x%llx, bestätigt = 0x%llx\n" #: .././repair/incore_ino.c:623 msgid "couldn't malloc parent list table\n" msgstr "malloc von Elternlistentabelle konnte nicht durchgeführt werden\n" #: .././repair/incore_ino.c:634 .././repair/incore_ino.c:680 msgid "couldn't memalign pentries table\n" msgstr "memalign von pentries-Tabelle konnte nicht durchgeführt werden\n" #: .././repair/incore_ino.c:738 msgid "could not malloc inode extra data\n" msgstr "malloc von Inode-Extradaten konnte nicht durchgeführt werden\n" #: .././repair/incore_ino.c:804 msgid "couldn't malloc inode tree descriptor table\n" msgstr "" "malloc von Inode-Datei-Deskriptor-Tabelle konnte nicht durchgeführt werden\n" #: .././repair/incore_ino.c:808 msgid "couldn't malloc uncertain ino tree descriptor table\n" msgstr "" "malloc von unbestimmter ino-Baum-Deskriptor-Tabelle konnte nicht\n" "durchgeführt werden\n" #: .././repair/incore_ino.c:813 msgid "couldn't malloc inode tree descriptor\n" msgstr "malloc von Baum-Deskriptor konnte nicht durchgeführt werden\n" #: .././repair/incore_ino.c:817 msgid "couldn't malloc uncertain ino tree descriptor\n" msgstr "" "malloc von unbestimmtem ino-Baum-Deskriptor konnte nicht durchgeführt\n" "werden\n" #: .././repair/incore_ino.c:825 msgid "couldn't malloc uncertain inode cache area\n" msgstr "" "malloc von unbestimmtem Inode-Zwischenspeicherbereich konnte nicht\n" "durchgeführt werden\n" #: .././repair/init.c:46 #, c-format msgid "getrlimit(RLIMIT_FSIZE) failed!\n" msgstr "getrlimit(RLIMIT_FSIZE) fehlgeschlagen!\n" #: .././repair/init.c:54 #, c-format msgid "setrlimit failed - current: %lld, max: %lld\n" msgstr "setrlimit fehlgeschlagen - aktuell: %lld, max: %lld\n" #: .././repair/init.c:107 #, c-format msgid "" "Unmount or use the dangerous (-d) option to repair a read-only mounted " "filesystem\n" msgstr "" #: .././repair/init.c:109 msgid "couldn't initialize XFS library\n" msgstr "XFS-Bibliothek kann nicht initialisiert werden\n" #: .././repair/phase1.c:28 msgid "Sorry, could not find valid secondary superblock\n" msgstr "" "Entschuldigung, gültiger zweiter Superblock kann nicht gefunden werden\n" #: .././repair/phase1.c:29 msgid "Exiting now.\n" msgstr "Wird beendet.\n" #: .././repair/phase1.c:40 #, c-format msgid "could not allocate ag header buffer (%d bytes)\n" msgstr "ag-Kopf-Puffer (%d Bytes) kann nicht alloziert werden\n" #: .././repair/phase1.c:58 msgid "Phase 1 - find and verify superblock...\n" msgstr "Phase 1 - Superblock finden und überprüfen...\n" #: .././repair/phase1.c:75 msgid "error reading primary superblock\n" msgstr "Fehler beim Lesen des primären Superblocks\n" #: .././repair/phase1.c:81 #, c-format msgid "bad primary superblock - %s !!!\n" msgstr "falscher primärer Superblock - %s !!!\n" #: .././repair/phase1.c:88 #, c-format msgid "couldn't verify primary superblock - %s !!!\n" msgstr "primärer Superblock kann nicht überprüft werden - %s !!!\n" #: .././repair/phase1.c:106 msgid "superblock has a features2 mismatch, correcting\n" msgstr "" "Superblock hat eine fehlende features2-Übereinstimmung, wird berichtigt\n" #: .././repair/phase1.c:123 #, c-format msgid "Enabling lazy-counters\n" msgstr "Schalte lazy-counters ein\n" #: .././repair/phase1.c:127 #, fuzzy, c-format msgid "Cannot disable lazy-counters on V5 fs\n" msgstr "lazy-counters werden ausgeschaltet\n" #: .././repair/phase1.c:132 #, c-format msgid "Disabling lazy-counters\n" msgstr "lazy-counters werden ausgeschaltet\n" #: .././repair/phase1.c:135 #, c-format msgid "Lazy-counters are already %s\n" msgstr "Lazy-counters sind bereits %s\n" #: .././repair/phase1.c:136 msgid "enabled" msgstr "eingeschaltet" #: .././repair/phase1.c:136 msgid "disabled" msgstr "ausgeschaltet" #: .././repair/phase1.c:143 msgid "writing modified primary superblock\n" msgstr "Schreiben verändert primären Superblock\n" #: .././repair/phase1.c:146 msgid "would write modified primary superblock\n" msgstr "Schreiben könnte primären Superblock verändern\n" #: .././repair/phase2.c:79 #, fuzzy, c-format msgid "zero_log: cannot find log head/tail (xlog_find_tail=%d)\n" msgstr "" "zero_log: Kopf/Fuß des Protokolls kann nicht gefunden werden\n" "(xlog_find_tail=%d), wird trotzdem auf Null gesetzt\n" #: .././repair/phase2.c:83 msgid "" "ERROR: The log head and/or tail cannot be discovered. Attempt to mount the\n" "filesystem to replay the log or use the -L option to destroy the log and\n" "attempt a repair.\n" msgstr "" #: .././repair/phase2.c:90 #, fuzzy, c-format msgid "zero_log: head block % tail block %\n" msgstr "zero_log: Kopfblock %lld Fußblock %lld\n" #: .././repair/phase2.c:96 msgid "" "ALERT: The filesystem has valuable metadata changes in a log which is being\n" "destroyed because the -L option was used.\n" msgstr "" "ALARM: Das Dateisystem hat wertvolle Metadaten-Änderungen in einem\n" "Protokoll, das zerstört wird, weil die -L-Option benutzt wird.\n" #: .././repair/phase2.c:100 msgid "" "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running xfs_repair. If you are unable to mount the filesystem, then use\n" "the -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n" msgstr "" "FEHLER: Das Dateisystem hat wertvolle Metadaten-Änderungen in einem\n" "Protokoll, das wiederholt werden sollte. Hängen Sie das Dateisystem ein,\n" "um das Protokoll zu wiederholen und hängen Sie es wieder aus um\n" "xfs_repair erneut auszuführen. Wenn Sie außer Stande sind, das\n" "Dateisystem einzuhängen, benutzen Sie die -L-Option um das Protokoll zu\n" "zerstören und versuchen Sie eine Reparatur.\n" "Beachten Sie, dass die Zerstörung des Protokolls Schaden verursachen\n" "kann -- bitte versuchen sie das Dateisystem einzuhängen ehe Sie dies tun.\n" #: .././repair/phase2.c:128 #, fuzzy msgid "failed to clear log" msgstr "%s: Gesamtes geleertes Protokoll\n" #: .././repair/phase2.c:162 msgid "" "This filesystem has an external log. Specify log device with the -l " "option.\n" msgstr "" "Das Dateisystem hat ein externes Protokoll. Geben Sie das Protokoll-Gerät\n" "mit der Option -l an.\n" #: .././repair/phase2.c:165 #, c-format msgid "Phase 2 - using external log on %s\n" msgstr "Phase 2 - ein externes Protokoll auf %s benutzen\n" #: .././repair/phase2.c:167 msgid "Phase 2 - using internal log\n" msgstr "Phase 2 - ein internes Protokoll benutzen\n" #: .././repair/phase2.c:170 msgid " - zero log...\n" msgstr " - Null-Protokoll...\n" #: .././repair/phase2.c:173 msgid " - scan filesystem freespace and inode maps...\n" msgstr "" " - freier Speicher und Inode-Karten des Dateisystems werden\n" "gescannt...\n" #: .././repair/phase2.c:189 msgid "root inode chunk not found\n" msgstr "Wurzel-Inode-Stück nicht gefunden\n" #: .././repair/phase2.c:208 msgid " - found root inode chunk\n" msgstr " - Wurzel-Inode-Stück gefunden\n" #: .././repair/phase2.c:214 msgid "root inode marked free, " msgstr "Wurzel-Inode als frei gekennzeichnet, " #: .././repair/phase2.c:223 msgid "realtime bitmap inode marked free, " msgstr "Echtzeit-Bitmap-Inode als frei gekennzeichnet, " #: .././repair/phase2.c:232 msgid "realtime summary inode marked free, " msgstr "Echtzeit-Zusammenfassungs-Inode als frei gekennzeichnet, " #: .././repair/phase3.c:47 #, fuzzy, c-format msgid "cannot read agi block % for ag %u\n" msgstr "agi-Block %lld für ag %u kann nicht gelesen werden\n" #: .././repair/phase3.c:78 .././repair/phase4.c:142 .././repair/phase5.c:2260 #: .././repair/phase6.c:3134 #, c-format msgid " - agno = %d\n" msgstr " - agno = %d\n" #: .././repair/phase3.c:119 msgid "Phase 3 - for each AG...\n" msgstr "Phase 3 - für jedes AG...\n" #: .././repair/phase3.c:121 msgid " - scan and clear agi unlinked lists...\n" msgstr " - agi unverknüpfte Listen werden gescannt und bereinigt...\n" #: .././repair/phase3.c:123 msgid " - scan (but don't clear) agi unlinked lists...\n" msgstr "" " - agi unverknüpfte Listen werden gescannt (aber nicht bereinigt...\n" #: .././repair/phase3.c:143 msgid " - process known inodes and perform inode discovery...\n" msgstr "" " - bekannte Inodes werden behandelt und Inode-Entdeckung wird\n" "durchgeführt...\n" #: .././repair/phase3.c:154 msgid " - process newly discovered inodes...\n" msgstr " - neu entdeckte Inodes werden behandelt...\n" #: .././repair/phase3.c:159 msgid "no memory for uncertain inode counts\n" msgstr "" #: .././repair/phase4.c:165 #, c-format msgid "" "unable to finish adding attr/data fork reverse-mapping data for AG %u.\n" msgstr "" #: .././repair/phase4.c:181 #, c-format msgid "unable to add AG %u metadata reverse-mapping data.\n" msgstr "" #: .././repair/phase4.c:186 #, c-format msgid "unable to merge AG %u metadata reverse-mapping data.\n" msgstr "" #: .././repair/phase4.c:191 #, c-format msgid "%s while checking reverse-mappings" msgstr "" #: .././repair/phase4.c:206 #, c-format msgid "%s while computing reference count records.\n" msgstr "" #: .././repair/phase4.c:221 #, c-format msgid "%s while fixing inode reflink flags.\n" msgstr "" #: .././repair/phase4.c:236 #, c-format msgid "%s while checking reference counts" msgstr "" #: .././repair/phase4.c:290 msgid "Phase 4 - check for duplicate blocks...\n" msgstr "Phase 4 - auf doppelte Blöcke überprüfen...\n" #: .././repair/phase4.c:291 msgid " - setting up duplicate extent list...\n" msgstr " - Liste mit doppeltem Ausmaß wird eingerichtet...\n" #: .././repair/phase4.c:305 msgid "root inode would be lost\n" msgstr "Wurzel-Inode könnte verloren worden sein\n" #: .././repair/phase4.c:307 msgid "root inode lost\n" msgstr "Wurzel-Inode wurde verloren\n" #: .././repair/phase4.c:324 #, c-format msgid "unknown block state, ag %d, block %d\n" msgstr "unbekannter Block-Status, ag %d, Block %d\n" #: .././repair/phase4.c:357 #, fuzzy, c-format msgid "unknown rt extent state, extent %\n" msgstr "unbekannter rt-Ausmaß-Status, Ausmaß %llu\n" #: .././repair/phase4.c:406 msgid " - check for inodes claiming duplicate blocks...\n" msgstr " - es wird geprüft ob Inodes Blocks doppelt beanspruchen...\n" #: .././repair/phase5.c:223 msgid "could not set up btree block array\n" msgstr "btree-Block-Matrix kann nicht eingerichtet werden\n" #: .././repair/phase5.c:244 msgid "error - not enough free space in filesystem\n" msgstr "Fehler - nicht genug freier Platz im Dateisystem\n" #: .././repair/phase5.c:259 #, fuzzy, c-format msgid "could not set up btree rmaps: %s\n" msgstr "btree-Block-Matrix kann nicht eingerichtet werden\n" #: .././repair/phase5.c:475 #, c-format msgid "can't rebuild fs trees -- not enough free space on ag %u\n" msgstr "" "fs-Bäume können nicht erneut gebildet werden -- nicht genug freier Platz\n" "auf ag %u\n" #: .././repair/phase5.c:498 #, c-format msgid "ag %u - not enough free space to build freespace btrees\n" msgstr "ag %u - nicht genug freier Platz im Freiplatz-btrees zu bilden\n" #: .././repair/phase5.c:533 #, c-format msgid "not enough free blocks left to describe all free blocks in AG %u\n" msgstr "" "nicht genügend freie Blöcke vorhandene um alle freien Blöcke in AG %u\n" "zu beschreiben\n" #: .././repair/phase5.c:1622 msgid "Insufficient memory to construct reverse-map cursor." msgstr "" #: .././repair/phase5.c:1928 msgid "Insufficient memory to construct refcount cursor." msgstr "" #: .././repair/phase5.c:2139 .././repair/phase5.c:2147 msgid "Insufficient memory saving lost blocks.\n" msgstr "" #: .././repair/phase5.c:2202 .././repair/xfs_repair.c:1032 msgid "couldn't get superblock\n" msgstr "Superblock kann nicht bekommen werden\n" #: .././repair/phase5.c:2283 #, c-format msgid "unable to rebuild AG %u. Not enough free space in on-disk AG.\n" msgstr "" "außerstande AG %u erneut zu bilden. Nicht genug freier Platz in on-disk AG.\n" #: .././repair/phase5.c:2335 #, c-format msgid "unable to rebuild AG %u. No free space.\n" msgstr "außerstande AG %u erneut zu bilden. Nicht genug Platz.\n" #: .././repair/phase5.c:2459 #, c-format msgid "unable to add AG %u reverse-mapping data to btree.\n" msgstr "" #: .././repair/phase5.c:2519 msgid "Phase 5 - rebuild AG headers and trees...\n" msgstr "Phase 5 - AG-Köpfe und Bäume werden erneut gebildet...\n" #: .././repair/phase5.c:2548 msgid "cannot alloc sb_icount_ag buffers\n" msgstr "sb_icount_ag-Puffer können nicht alloziert werden\n" #: .././repair/phase5.c:2552 msgid "cannot alloc sb_ifree_ag buffers\n" msgstr "sb_ifree_ag-Puffer können nicht alloziert werden\n" #: .././repair/phase5.c:2556 msgid "cannot alloc sb_fdblocks_ag buffers\n" msgstr "sb_fdblocks_ag-Puffer können nicht alloziert werden\n" #: .././repair/phase5.c:2560 #, fuzzy msgid "cannot alloc lost block slab\n" msgstr "sb_fdblocks_ag-Puffer können nicht alloziert werden\n" #: .././repair/phase5.c:2579 msgid " - generate realtime summary info and bitmap...\n" msgstr " - Echtzeit-Zusammenfassung und Bitmap wird erzeugt...\n" #: .././repair/phase5.c:2584 msgid " - reset superblock...\n" msgstr " - Superblock wird zurückgesetzt...\n" #: .././repair/phase5.c:2593 #, fuzzy msgid "Unable to reinsert lost blocks into filesystem.\n" msgstr "Fehler in ein Dateisystem einspeisen" #: .././repair/phase6.c:64 #, fuzzy, c-format msgid "malloc failed add_dotdot_update (%zu bytes)\n" msgstr "malloc fehlgeschlagen add_dotdot_update (%u Bytes)\n" #: .././repair/phase6.c:216 #, fuzzy, c-format msgid "malloc failed in dir_hash_add (%zu bytes)\n" msgstr "malloc fehlgeschlagen in dir_hash_add (%u Bytes)\n" #: .././repair/phase6.c:270 msgid "ok" msgstr "ok" #: .././repair/phase6.c:271 msgid "duplicate leaf" msgstr "doppeltes Blatt" #: .././repair/phase6.c:272 msgid "hash value mismatch" msgstr "Hash-Wert stimmt nicht überein" #: .././repair/phase6.c:273 msgid "no data entry" msgstr "kein Dateneintrag" #: .././repair/phase6.c:274 msgid "no leaf entry" msgstr "kein Blatteintrag" #: .././repair/phase6.c:275 msgid "bad stale count" msgstr "falsche Stale-Anzahl" #: .././repair/phase6.c:283 #, fuzzy, c-format msgid "bad hash table for directory inode % (%s): " msgstr "falsche Hash-Tabelle für Verzeichnis-Inode %llu (%s): " #: .././repair/phase6.c:286 msgid "rebuilding\n" msgstr "erneut bilden\n" #: .././repair/phase6.c:288 msgid "would rebuild\n" msgstr "könnte erneut bilden\n" #: .././repair/phase6.c:324 msgid "calloc failed in dir_hash_init\n" msgstr "calloc fehlgeschlagen in dir_hash_init\n" #: .././repair/phase6.c:472 msgid "ran out of disk space!\n" msgstr "lief außerhalb des Plattenplatzes!\n" #: .././repair/phase6.c:474 #, c-format msgid "xfs_trans_reserve returned %d\n" msgstr "xfs_trans_reserve zurückgegeben %d\n" #: .././repair/phase6.c:504 .././repair/phase6.c:606 #, c-format msgid "couldn't iget realtime bitmap inode -- error - %d\n" msgstr "" "iget für Echtezeit-Bitmap-Inode konnte nicht ausgeführt werden --\n" "Fehler - %d\n" #: .././repair/phase6.c:562 #, c-format msgid "couldn't allocate realtime bitmap, error = %d\n" msgstr "Echtzeit-Bitmap kann nicht alloziert werden, Fehler = %d\n" #: .././repair/phase6.c:575 #, c-format msgid "allocation of the realtime bitmap failed, error = %d\n" msgstr "Allokation des Echtzeit-Bitmaps fehlgeschlagen, Fehler = %d\n" #: .././repair/phase6.c:620 #, fuzzy, c-format msgid "couldn't map realtime bitmap block %, error = %d\n" msgstr "Echtzeit-Bitmap-Block %llu kann nicht kartiert werden, Fehler = %d\n" #: .././repair/phase6.c:633 #, fuzzy, c-format msgid "" "can't access block % (fsbno %) of realtime bitmap inode " "%\n" msgstr "" "auf Block %llu (fsbno %llu) des Echtzeit-Bitmap-Inodes %llu kann nicht\n" "zugegriffen werden.\n" #: .././repair/phase6.c:677 .././repair/phase6.c:751 #, c-format msgid "couldn't iget realtime summary inode -- error - %d\n" msgstr "" "iget für Echtezeit-Zusammenfassungs-Inode konnte nicht ausgeführt werden\n" "-- Fehler - %d\n" #: .././repair/phase6.c:691 #, fuzzy, c-format msgid "couldn't map realtime summary inode block %, error = %d\n" msgstr "" "Echtzeit-Zusammenfassungs-Inode-Block %llu kann nicht kartiert werden,\n" "Fehler = %d\n" #: .././repair/phase6.c:704 #, fuzzy, c-format msgid "" "can't access block % (fsbno %) of realtime summary inode " "%\n" msgstr "" "auf Block %llu (fsbno %llu) des Echtzeit-Zusammenfassungs-Inodes %llu\n" "kann nicht zugegriffen werden.\n" #: .././repair/phase6.c:814 #, c-format msgid "couldn't allocate realtime summary inode, error = %d\n" msgstr "" "Echtzeit-Zusammenfassungs-Inode kann nicht alloziert werden, Fehler = %d\n" #: .././repair/phase6.c:827 #, c-format msgid "allocation of the realtime summary ino failed, error = %d\n" msgstr "" "Allokation des Echtzeit-Zusammenfassungs-ino fehlgeschlagen, Fehler = %d\n" #: .././repair/phase6.c:856 #, c-format msgid "could not iget root inode -- error - %d\n" msgstr "iget für Wurzel-Inode konnte nicht ausgeführt werden -- Fehler - %d\n" #: .././repair/phase6.c:933 #, c-format msgid "%d - couldn't iget root inode to obtain %s\n" msgstr "" "%d - iget für Wurzel-Inode konnte nicht ausgeführt werden, um %s zu\n" "erhalten\n" #: .././repair/phase6.c:963 #, c-format msgid "%s inode allocation failed %d\n" msgstr "%s Inode-Allokation fehlgeschlagen %d\n" #: .././repair/phase6.c:1010 #, c-format msgid "can't make %s, createname error %d\n" msgstr "%s kann nicht gemacht werden, createname-Fehler %d\n" #: .././repair/phase6.c:1030 #, c-format msgid "%s directory creation failed -- bmapf error %d\n" msgstr "%s Verzeichnis erzeugen fehlgeschlagen -- bmapf Fehler %d\n" #: .././repair/phase6.c:1072 #, c-format msgid "%d - couldn't iget orphanage inode\n" msgstr "%d - iget für verwaisten Inode konnte nicht ausgeführt werden\n" #: .././repair/phase6.c:1083 #, c-format msgid "%d - couldn't iget disconnected inode\n" msgstr "%d - iget für getrennten Inode konnte nicht ausgeführt werden\n" #: .././repair/phase6.c:1104 .././repair/phase6.c:1146 #: .././repair/phase6.c:1202 #, c-format msgid "space reservation failed (%d), filesystem may be out of space\n" msgstr "" "Platzreservierung fehlgeschlagen (%d), auf dem Dateisystem könnte kein\n" "Platz sein\n" #: .././repair/phase6.c:1115 .././repair/phase6.c:1158 #: .././repair/phase6.c:1213 #, c-format msgid "name create failed in %s (%d), filesystem may be out of space\n" msgstr "" "Erzeugen des Namens fehlgeschlagen in %s (%d), auf dem Dateisystem\n" "könnte kein Platz sein\n" #: .././repair/phase6.c:1128 #, c-format msgid "creation of .. entry failed (%d), filesystem may be out of space\n" msgstr "" "Erzeugung von ..-Eintrag fehlgeschlagen (%d), auf dem Dateisystem könnte\n" "kein Platz sein\n" #: .././repair/phase6.c:1137 #, c-format msgid "bmap finish failed (err - %d), filesystem may be out of space\n" msgstr "" "Beenden von bmap fehlgeschlagen (err - %d), auf dem Dateisystem könnte\n" "kein Platz sein\n" #: .././repair/phase6.c:1177 #, c-format msgid "name replace op failed (%d), filesystem may be out of space\n" msgstr "" "op-Namen ersetzen fehlgeschlagen (%d), auf dem Dateisystem könnte kein\n" "Platz sein\n" #: .././repair/phase6.c:1184 .././repair/phase6.c:1223 #: .././repair/phase6.c:1357 #, c-format msgid "bmap finish failed (%d), filesystem may be out of space\n" msgstr "" "Beenden von bmap fehlgeschlagen (%d), auf dem Dateisystem könnte kein\n" "Platz sein\n" #: .././repair/phase6.c:1242 msgid ", marking entry to be junked\n" msgstr ", Eintrag wird zum verwerfen gekennzeichnet\n" #: .././repair/phase6.c:1246 msgid ", would junk entry\n" msgstr ", Eintrag könnte verworfen werden\n" #: .././repair/phase6.c:1279 #, fuzzy, c-format msgid "rebuilding directory inode %\n" msgstr "Verzeichnis-Inode %llu wird erneut erzeugt\n" #: .././repair/phase6.c:1301 #, c-format msgid "xfs_bmap_last_offset failed -- error - %d\n" msgstr "xfs_bmap_last_offset fehlgeschlagen -- Fehler - %d\n" #: .././repair/phase6.c:1308 #, c-format msgid "xfs_bunmapi failed -- error - %d\n" msgstr "xfs_bunmapi fehlgeschlagen -- Fehler - %d\n" #: .././repair/phase6.c:1316 #, fuzzy, c-format msgid "xfs_dir_init failed -- error - %d\n" msgstr "xfs_bunmapi fehlgeschlagen -- Fehler - %d\n" #: .././repair/phase6.c:1349 #, fuzzy, c-format msgid "" "name create failed in ino % (%d), filesystem may be out of space\n" msgstr "" "Erzeugen des Namens fehlgeschlagen in ino %llu (%d), auf dem Dateisystem\n" "könnte kein Platz sein\n" #: .././repair/phase6.c:1412 #, fuzzy, c-format msgid "shrink_inode failed inode % block %u\n" msgstr "shrink_inode fehlgeschlagen Inode %llu Block %u\n" #: .././repair/phase6.c:1503 .././repair/phase6.c:2300 #, fuzzy, c-format msgid "realloc failed in %s (%zu bytes)\n" msgstr "»realloc« in »blkent_grow« fehlgeschlagen (%u Bytes)\n" #: .././repair/phase6.c:1560 #, fuzzy, c-format msgid "empty data block %u in directory inode %: " msgstr "leerer Datenblock %u in Verzeichnis-Inode %llu: " #: .././repair/phase6.c:1564 #, fuzzy, c-format msgid "corrupt block %u in directory inode %: " msgstr "beschädigter Block %u in Verzeichnis-Inode %llu: " #: .././repair/phase6.c:1568 msgid "junking block\n" msgstr "Block wird weggeworfen\n" #: .././repair/phase6.c:1571 msgid "would junk block\n" msgstr "Block könnte weggeworfen werden\n" #: .././repair/phase6.c:1593 #, fuzzy, c-format msgid "" "bad directory block magic # %#x for directory inode % block %d: " msgstr "" "falscher Verzeichnisblock magische # %#x für Verzeichnis-Inode %llu Block " "%d: " #: .././repair/phase6.c:1596 #, c-format msgid "fixing magic # to %#x\n" msgstr "magische # wird auf %#x fixiert\n" #: .././repair/phase6.c:1600 #, c-format msgid "would fix magic # to %#x\n" msgstr "magische # würde auf %#x fixiert\n" #: .././repair/phase6.c:1621 #, fuzzy, c-format msgid "directory inode % block %u has consecutive free entries: " msgstr "" "Verzeichnis-Inode %llu Block %u hat aufeinander folgende freie Einträge: " #: .././repair/phase6.c:1625 msgid "joining together\n" msgstr "wird zusammengeführt\n" #: .././repair/phase6.c:1634 msgid "would join together\n" msgstr "könnte zusammengeführt werden\n" #: .././repair/phase6.c:1667 #, fuzzy, c-format msgid "" "entry \"%s\" in directory inode % points to non-existent inode " "%" msgstr "" "Eintrag »%s« in Verzeichnis-Inode %llu zeigt auf nicht existierenden\n" "Inode %llu" #: .././repair/phase6.c:1684 #, fuzzy, c-format msgid "" "entry \"%s\" in directory inode % points to free inode %" msgstr "Eintrag »%s« in Verzeichnis-Inode %llu zeigt auf freien Inode %llu" #: .././repair/phase6.c:1702 .././repair/phase6.c:2627 #, fuzzy, c-format msgid "%s (ino %) in root (%) is not a directory" msgstr "%s (ino %llu) in Wurzel (%llu) ist kein Verzeichnis" #: .././repair/phase6.c:1724 .././repair/phase6.c:2649 #, fuzzy, c-format msgid "entry \"%s\" (ino %) in dir % is a duplicate name" msgstr "Eintrag »%s« (ino %llu) in dir %llu ist ein doppelter Name" #: .././repair/phase6.c:1755 #, fuzzy, c-format msgid "" "entry \"%s\" (ino %) in dir % is not in the the first block" msgstr "Eintrag »%s« (ino %llu) in dir %llu ist nicht im ersten Block" #: .././repair/phase6.c:1781 #, fuzzy, c-format msgid "entry \"%s\" in dir % is not the first entry" msgstr "Eintrag »%s« in dir %llu ist nicht der erste Eintrag" #: .././repair/phase6.c:1807 .././repair/phase6.c:2718 #, c-format msgid "" "would fix ftype mismatch (%d/%d) in directory/child inode %/" "%\n" msgstr "" #: .././repair/phase6.c:1812 .././repair/phase6.c:2723 #, c-format msgid "" "fixing ftype mismatch (%d/%d) in directory/child inode %/%\n" msgstr "" #: .././repair/phase6.c:1845 #, fuzzy, c-format msgid "" "entry \"%s\" in dir % points to an already connected directory inode " "%\n" msgstr "" "Eintrag »%s« in dir %llu zeigt auf einen bereits verbundenen Verzeichnis-" "Inode %llu\n" #: .././repair/phase6.c:1854 .././repair/phase6.c:2687 #, fuzzy, c-format msgid "" "entry \"%s\" in dir ino % doesn't have a .. entry, will set it in " "ino %.\n" msgstr "" "Eintrag »%s« in dir %llu hat keinen ..-Eintrag, wird in ino %llu gesetzt.\n" #: .././repair/phase6.c:1864 #, fuzzy, c-format msgid "" "entry \"%s\" in dir inode % inconsistent with .. value (%) " "in ino %\n" msgstr "" "Eintrag »%s« in dir %llu stimmt nicht mit ..-Wert (%llu) in ino %llu " "überein\n" #: .././repair/phase6.c:1876 #, c-format msgid "\twill clear entry \"%s\"\n" msgstr "\tEintrag »%s« wird bereinigt\n" #: .././repair/phase6.c:1879 #, c-format msgid "\twould clear entry \"%s\"\n" msgstr "\tEintrag »%s« könnte bereinigt werden\n" #: .././repair/phase6.c:1912 #, c-format msgid "expected owner inode %, got %llu, directory block %\n" msgstr "" #: .././repair/phase6.c:1919 #, fuzzy, c-format msgid "expected block %, got %llu, directory inode %\n" msgstr "" "Block %u(fsbno %llu) kann nicht gelesen werden für Verzeichnis-Inode %llu\n" #: .././repair/phase6.c:1926 #, c-format msgid "wrong FS UUID, directory inode % block %\n" msgstr "" #: .././repair/phase6.c:1986 #, fuzzy, c-format msgid "leaf block %u for directory inode % bad CRC\n" msgstr "Blatt-Block %u für Verzeichnis-Inode %llu hat falsches Ende\n" #: .././repair/phase6.c:1991 #, fuzzy, c-format msgid "can't read block %u for directory inode %, error %d\n" msgstr "Block %u für Verzeichnis-Inode %lld kann nicht gelesen werden\n" #: .././repair/phase6.c:2009 .././repair/phase6.c:2132 #, fuzzy, c-format msgid "leaf block %u for directory inode % bad header\n" msgstr "Blattblock %u für Verzeichnis-Inode %llu hat falsche Kopfzeilen\n" #: .././repair/phase6.c:2035 #, fuzzy, c-format msgid "leaf block %u for directory inode % bad tail\n" msgstr "Blatt-Block %u für Verzeichnis-Inode %llu hat falsches Ende\n" #: .././repair/phase6.c:2089 #, fuzzy, c-format msgid "can't read leaf block %u for directory inode %, error %d\n" msgstr "Blatt-Block %u für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #: .././repair/phase6.c:2101 #, fuzzy, c-format msgid "unknown magic number %#x for block %u in directory inode %\n" msgstr "" "unbekannte Magische Nummer %#x für Block %u in Verzeichnis-Inode %llu\n" #: .././repair/phase6.c:2157 #, fuzzy, c-format msgid "can't read freespace block %u for directory inode %, error %d\n" msgstr "" "Block %u mit freiem Platz für Verzeichnis-Inode %llu konnte nicht gelesen\n" "werden\n" #: .././repair/phase6.c:2172 #, fuzzy, c-format msgid "free block %u for directory inode % bad header\n" msgstr "freier Block %u für Verzeichnis-Inode %llu hat falschen Kopf\n" #: .././repair/phase6.c:2190 #, fuzzy, c-format msgid "free block %u entry %i for directory ino % bad\n" msgstr "freier Block %u Eintrag %i für Verzeichnis-ino %llu falsch\n" #: .././repair/phase6.c:2200 #, fuzzy, c-format msgid "free block %u for directory inode % bad nused\n" msgstr "freier Block %u für Verzeichnis-Inode %llu falsch nused\n" #: .././repair/phase6.c:2211 #, fuzzy, c-format msgid "missing freetab entry %u for directory inode %\n" msgstr "fehlender freetab-Eintrag %u für Verzeichnis-Inode %llu\n" #: .././repair/phase6.c:2250 #, fuzzy, c-format msgid "malloc failed in %s (% bytes)\n" msgstr "malloc fehlgeschlagen in dir_hash_add (%u Bytes)\n" #: .././repair/phase6.c:2264 #, fuzzy, c-format msgid "calloc failed in %s (%zu bytes)\n" msgstr "malloc fehlgeschlagen in dir_hash_add (%u Bytes)\n" #: .././repair/phase6.c:2313 #, fuzzy, c-format msgid "can't read data block %u for directory inode % error %d\n" msgstr "Datenblock %u für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #: .././repair/phase6.c:2420 msgid "would junk entry\n" msgstr "Eintrag könnte verworfen werden\n" #: .././repair/phase6.c:2444 msgid "junking entry\n" msgstr "Eintrag wird verworfen\n" #: .././repair/phase6.c:2490 #, fuzzy, c-format msgid "would set .. in sf dir inode % to %\n" msgstr ".. könnte in sf dir-Inode %llu auf %llu gesetzt werden\n" #: .././repair/phase6.c:2494 #, fuzzy, c-format msgid "setting .. in sf dir inode % to %\n" msgstr ".. wird in sf dir-Inode %llu auf %llu gesetzt\n" #: .././repair/phase6.c:2594 #, fuzzy, c-format msgid "" "entry \"%s\" in shortform directory % references non-existent inode " "%\n" msgstr "" "Eintrag »%s« in Kurzform-Verzeichnis %llu bezieht sich auf nicht\n" "existierenden Inode %llu" #: .././repair/phase6.c:2611 #, fuzzy, c-format msgid "" "entry \"%s\" in shortform directory inode % points to free inode " "%\n" msgstr "" "Eintrag »%s« in Kurzform-Verzeichnis-Inode %llu zeigt auf freien\n" "Inode %llu" #: .././repair/phase6.c:2673 #, fuzzy, c-format msgid "" "entry \"%s\" in directory inode % references already connected inode " "%.\n" msgstr "" "Eintrag »%s« in Verzeichnis-Inode %llu bezieht sich auf bereits verbundenen " "Inode %llu,\n" #: .././repair/phase6.c:2696 #, fuzzy, c-format msgid "" "entry \"%s\" in directory inode % not consistent with .. value " "(%) in inode %,\n" msgstr "" "Eintrag »%s« in Verzeichnis-Inode %llu nicht übereinstimmen mit ..-Wert " "(%llu) in Inode %llu,\n" #: .././repair/phase6.c:2753 #, fuzzy, c-format msgid "would fix i8count in inode %\n" msgstr "i8count in Inode %llu könnte repariert werden\n" #: .././repair/phase6.c:2768 #, fuzzy, c-format msgid "fixing i8count in inode %\n" msgstr "i8count in Inode %llu wird repariert\n" #: .././repair/phase6.c:2788 #, fuzzy, c-format msgid "setting size to % bytes to reflect junked entries\n" msgstr "" "Größe wird auf %lld Bytes gesetzt um verworfene Einträge\n" "widerzuspiegeln\n" #: .././repair/phase6.c:2827 .././repair/phase6.c:2831 .././repair/phase7.c:52 #, fuzzy, c-format msgid "couldn't map inode %, err = %d\n" msgstr "Inode %llu kann nicht kartiert werden, err = %d\n" #: .././repair/phase6.c:2932 msgid "recreating root directory .. entry\n" msgstr "..-Eintrag des Wurzel-Verzeichnisses wird neu erzeugt\n" #: .././repair/phase6.c:2948 #, fuzzy, c-format msgid "can't make \"..\" entry in root inode %, createname error %d\n" msgstr "" "»..«-Eintrag im Wurzel-Inode %llu kann nicht erstellt werden, createname-" "Fehler %d\n" #: .././repair/phase6.c:2958 msgid "would recreate root directory .. entry\n" msgstr "..-Eintrag des Wurzel-Verzeichnisses könnte neu erzeugt werden\n" #: .././repair/phase6.c:2982 #, fuzzy, c-format msgid "would create missing \".\" entry in dir ino %\n" msgstr "fehlender ».«-Eintrag in dir ino %llu könnte erzeugt werden\n" #: .././repair/phase6.c:2989 #, fuzzy, c-format msgid "creating missing \".\" entry in dir ino %\n" msgstr "fehlender ».«-Eintrag in dir ino %llu wird erzeugt\n" #: .././repair/phase6.c:3005 #, fuzzy, c-format msgid "can't make \".\" entry in dir ino %, createname error %d\n" msgstr "" "».«-Eintrag in dir ino %llu kann nicht erzeugt werden createname-Fehler %d\n" #: .././repair/phase6.c:3101 #, fuzzy, c-format msgid "disconnected dir inode %, " msgstr "nicht verbundener dir-Inode %llu, " #: .././repair/phase6.c:3103 #, fuzzy, c-format msgid "disconnected inode %, " msgstr "nicht verbundener Inode %llu, " #: .././repair/phase6.c:3107 #, c-format msgid "moving to %s\n" msgstr "gehe zu %s\n" #: .././repair/phase6.c:3110 #, c-format msgid "would move to %s\n" msgstr "könnte zu %s gehen\n" #: .././repair/phase6.c:3195 msgid "Phase 6 - check inode connectivity...\n" msgstr "Phase 6 - Inode-Verbindbarkeit wird geprüft...\n" #: .././repair/phase6.c:3209 msgid "reinitializing root directory\n" msgstr "Wurzel-Verzeichnis wird neu initialisiert\n" #: .././repair/phase6.c:3214 msgid "would reinitialize root directory\n" msgstr "Wurzel-Verzeichnis könnte neu initialisiert werden\n" #: .././repair/phase6.c:3220 msgid "reinitializing realtime bitmap inode\n" msgstr "Echtzeit-Bitmap-Inode wird neu initialisiert\n" #: .././repair/phase6.c:3224 msgid "would reinitialize realtime bitmap inode\n" msgstr "Echtzeit-Bitmap-Inode könnte neu initialisiert werden\n" #: .././repair/phase6.c:3230 msgid "reinitializing realtime summary inode\n" msgstr "Echtzeit-Zusammenfassung wird neu initialisiert\n" #: .././repair/phase6.c:3234 msgid "would reinitialize realtime summary inode\n" msgstr "Echtzeit-Zusammenfassung könnte neu initialisiert werden\n" #: .././repair/phase6.c:3240 msgid " - resetting contents of realtime bitmap and summary inodes\n" msgstr "" " - Inhalte der Echtzeit-Bitmaps und Zusammenfassungs-Inodes werden " "zurückgesetzt\n" #: .././repair/phase6.c:3243 .././repair/phase6.c:3248 msgid "Warning: realtime bitmap may be inconsistent\n" msgstr "Warnung: Echtzeit-Bitmap kann unvollständig sein\n" #: .././repair/phase6.c:3254 msgid " - traversing filesystem ...\n" msgstr " - Dateisystem wird durchquert ...\n" #: .././repair/phase6.c:3277 msgid " - traversal finished ...\n" msgstr " - durchqueren beendet ...\n" #: .././repair/phase6.c:3278 #, c-format msgid " - moving disconnected inodes to %s ...\n" msgstr " - nicht verbundene Inodes werden nach %s verschoben ...\n" #: .././repair/phase7.c:56 #, fuzzy, c-format msgid "couldn't map inode %, err = %d, can't compare link counts\n" msgstr "" "Inode %llu kann nicht kartiert werden, err = %d, Anzahl der Verweise kann\n" "nicht verglichen werden\n" #: .././repair/phase7.c:68 #, fuzzy, c-format msgid "resetting inode % nlinks from %u to %u\n" msgstr "Inode %llu nlinks wird von %d auf %d zurückgesetzt\n" #: .././repair/phase7.c:74 #, fuzzy, c-format msgid "would have reset inode % nlinks from %u to %u\n" msgstr "Inode %llu nlinks könnte von %d auf %d zurückgesetzt werden\n" #: .././repair/phase7.c:142 msgid "Phase 7 - verify and correct link counts...\n" msgstr "Phase 7 - Verweisanzahl wird geprüft und berichtigt...\n" #: .././repair/phase7.c:144 msgid "Phase 7 - verify link counts...\n" msgstr "Phase 7 - Verweisanzahl wird geprüft\n" #: .././repair/prefetch.c:543 msgid "prefetch corruption\n" msgstr "Voraufrufbeschädigung\n" #: .././repair/prefetch.c:704 .././repair/prefetch.c:817 #, c-format msgid "failed to create prefetch thread: %s\n" msgstr "Erzeugung des Voraufruf-Threads fehlgeschlagen: %s\n" #: .././repair/prefetch.c:854 msgid "failed to initialize prefetch mutex\n" msgstr "initialisieren des Voraufruf-Mutex fehlgeschlagen\n" #: .././repair/prefetch.c:856 .././repair/prefetch.c:858 msgid "failed to initialize prefetch cond var\n" msgstr "initialisieren der Voraufruf-cond var fehlgeschlagen\n" #: .././repair/progress.c:16 msgid "inodes" msgstr "Inodes" #: .././repair/progress.c:20 msgid "directories" msgstr "Verzeichnisse" #: .././repair/progress.c:22 msgid "allocation groups" msgstr "Allokations-Gruppen" #: .././repair/progress.c:24 msgid "AGI unlinked buckets" msgstr "AGI gelöste Verweisbehälter" #: .././repair/progress.c:28 msgid "realtime extents" msgstr "Echtzeitbereiche" #: .././repair/progress.c:30 msgid "unlinked lists" msgstr "unverknüpfte Listen" #: .././repair/progress.c:37 #, c-format msgid " - %02d:%02d:%02d: %s - %llu of %llu %s done\n" msgstr " - %02d:%02d:%02d: %s - %llu von %llu %s erledigt\n" #: .././repair/progress.c:39 #, c-format msgid " - %02d:%02d:%02d: %s - %llu %s done\n" msgstr " - %02d:%02d:%02d: %s - %llu %s erledigt\n" #: .././repair/progress.c:51 msgid "scanning filesystem freespace" msgstr "freier Speicher des Dateisystems wird gescannt" #: .././repair/progress.c:53 msgid "scanning agi unlinked lists" msgstr "unverknüpfte agi-Listen werden gescannt" #: .././repair/progress.c:55 msgid "check uncertain AG inodes" msgstr "einige unklare AG-Inodes werden geprüft" #: .././repair/progress.c:57 msgid "process known inodes and inode discovery" msgstr "bekannte Inodes werden abgearbeitet und Inodes entdeckt" #: .././repair/progress.c:59 msgid "process newly discovered inodes" msgstr "neu entdeckte Inodes werden abgearbeitet" #: .././repair/progress.c:61 msgid "setting up duplicate extent list" msgstr "Liste mit doppelten Bereichen wird eingerichtet" #: .././repair/progress.c:63 msgid "initialize realtime bitmap" msgstr "Echtzeit-Bitmap wird initialisiert" #: .././repair/progress.c:65 msgid "reset realtime bitmaps" msgstr "Echtzeit-Bitmap wird zurückgesetzt" #: .././repair/progress.c:67 msgid "check for inodes claiming duplicate blocks" msgstr "es wird geprüft, ob Inodes doppelte Blöcke beanspruchen" #: .././repair/progress.c:69 msgid "rebuild AG headers and trees" msgstr "AG-Köpfe und Bäume werden neu erstellt" #: .././repair/progress.c:71 msgid "traversing filesystem" msgstr "Dateisystem wird durchquert" #: .././repair/progress.c:73 msgid "traversing all unattached subtrees" msgstr "alle unabhängigen Unterbäume werden durchquert" #: .././repair/progress.c:75 msgid "moving disconnected inodes to lost+found" msgstr "nicht verbundene Inodes werden nach lost+found verschoben" #: .././repair/progress.c:77 msgid "verify and correct link counts" msgstr "Verweisanzahl wird geprüft und berichtigt" #: .././repair/progress.c:79 msgid "verify link counts" msgstr "Verweisanzahl wird geprüft" #: .././repair/progress.c:118 msgid "cannot malloc pointer to done vector\n" msgstr "malloc von Zeiger auf erledigten Vektor nicht möglich\n" #: .././repair/progress.c:135 msgid "unable to create progress report thread\n" msgstr "außerstande einen Fortschritts-Bericht-Thread zu erzeugen\n" #: .././repair/progress.c:178 msgid "progress_rpt: cannot malloc progress msg buffer\n" msgstr "progress_rpt: malloc Fortschritts-msg-Puffer\n" #: .././repair/progress.c:191 msgid "progress_rpt: cannot create timer\n" msgstr "progress_rpt: Zeitnehmer kann nicht erzeugt werden\n" #: .././repair/progress.c:194 msgid "progress_rpt: cannot set timer\n" msgstr "progress_rpt: Zeitnehmer kann nicht gesetzt werden\n" #: .././repair/progress.c:218 msgid "progress_rpt: cannot lock progress mutex\n" msgstr "progress_rpt: mutex-Fortschritt kann nicht gesperrt werden\n" #: .././repair/progress.c:255 .././repair/progress.c:358 #, c-format msgid "%s" msgstr "%s" #: .././repair/progress.c:263 #, c-format msgid "" "\t- %02d:%02d:%02d: Phase %d: elapsed time %s - processed %d %s per minute\n" msgstr "" "\t- %02d:%02d:%02d: Phase %d: verstrichene Zeit %s - %d abgearbeitet %s\n" "pro Minute\n" #: .././repair/progress.c:268 #, fuzzy, c-format msgid "" "\t- %02d:%02d:%02d: Phase %d: %%% done - estimated remaining time " "%s\n" msgstr "" "\t- %02d:%02d:%02d: Phase %d: %llu%% erledigt - geschätzte verbleibende\n" "Zeit %s\n" #: .././repair/progress.c:276 msgid "progress_rpt: error unlock msg mutex\n" msgstr "progress_rpt: Fehler beim Entsperren von msg mutex\n" #: .././repair/progress.c:282 msgid "cannot delete timer\n" msgstr "Zeitnehmer kann nicht gelöscht werden\n" #: .././repair/progress.c:296 msgid "set_progress_msg: cannot lock progress mutex\n" msgstr "set_progress_msg: Mutex-Fortschritt kann nicht gesperrt werden\n" #: .././repair/progress.c:306 msgid "set_progress_msg: cannot unlock progress mutex\n" msgstr "set_progress_msg: Mutex-Fortschritt kann nicht entsperrt werden\n" #: .././repair/progress.c:326 msgid "print_final_rpt: cannot lock progress mutex\n" msgstr "print_final_rpt: Mutex-Fortschritt kann nicht gesperrt werden\n" #: .././repair/progress.c:362 msgid "print_final_rpt: cannot unlock progress mutex\n" msgstr "print_final_rpt: Mutex-Fortschritt kann nicht entsperrt werden\n" #: .././repair/progress.c:411 #, c-format msgid "%02d:%02d:%02d" msgstr "%02d:%02d:%02d" #: .././repair/progress.c:433 #, c-format msgid "%d week" msgstr "%d Woche" #: .././repair/progress.c:434 .././repair/progress.c:444 #: .././repair/progress.c:460 .././repair/progress.c:478 #: .././repair/progress.c:493 msgid "s" msgstr "s" #: .././repair/progress.c:443 #, c-format msgid "%d day" msgstr "%d Tag" #: .././repair/progress.c:450 .././repair/progress.c:467 #: .././repair/progress.c:485 .././repair/progress.c:495 msgid ", " msgstr ", " #: .././repair/progress.c:459 #, c-format msgid "%d hour" msgstr "%d Stunde" #: .././repair/progress.c:477 #, c-format msgid "%d minute" msgstr "%d Minute" #: .././repair/progress.c:492 #, c-format msgid "%d second" msgstr "%d Sekunde" #: .././repair/progress.c:513 #, c-format msgid "" "\n" " XFS_REPAIR Summary %s\n" msgstr "" "\n" " XFS_REPAIR Zusammenfassung %s\n" #: .././repair/progress.c:515 msgid "Phase\t\tStart\t\tEnd\t\tDuration\n" msgstr "Phase\t\tStart\t\tEnde\t\tDauer\n" #: .././repair/progress.c:520 .././repair/progress.c:523 #, c-format msgid "Phase %d:\tSkipped\n" msgstr "Phase %d:\tÜbersprungen\n" #: .././repair/progress.c:527 #, c-format msgid "Phase %d:\t%02d/%02d %02d:%02d:%02d\t%02d/%02d %02d:%02d:%02d\t%s\n" msgstr "Phase %d:\t%02d/%02d %02d:%02d:%02d\t%02d/%02d %02d:%02d:%02d\t%s\n" #: .././repair/progress.c:533 #, c-format msgid "" "\n" "Total run time: %s\n" msgstr "" "\n" "Gesamte Laufzeit: %s\n" #: .././repair/rmap.c:112 #, fuzzy msgid "couldn't allocate per-AG reverse map roots\n" msgstr "Blockkarten-Sperren können nicht alloziert werden\n" #: .././repair/rmap.c:119 msgid "Insufficient memory while allocating reverse mapping slabs." msgstr "" #: .././repair/rmap.c:124 .././repair/rmap.c:363 msgid "" "Insufficient memory while allocating raw metadata reverse mapping slabs." msgstr "" #: .././repair/rmap.c:130 msgid "Insufficient memory while allocating refcount item slabs." msgstr "" #: .././repair/rmap.c:736 msgid "Insufficient memory while recreating refcount tree." msgstr "" #: .././repair/rmap.c:993 msgid "would rebuild corrupt rmap btrees.\n" msgstr "" #: .././repair/rmap.c:1036 #, c-format msgid "" "Missing reverse-mapping record for (%u/%u) %slen %u owner % %s%soff " "%\n" msgstr "" #: .././repair/rmap.c:1040 .././repair/rmap.c:1058 .././repair/rmap.c:1068 #, fuzzy msgid "unwritten " msgstr "pwrite" #: .././repair/rmap.c:1044 .././repair/rmap.c:1062 .././repair/rmap.c:1072 #, fuzzy msgid "attr " msgstr "attr" #: .././repair/rmap.c:1046 .././repair/rmap.c:1064 .././repair/rmap.c:1074 msgid "bmbt " msgstr "" #: .././repair/rmap.c:1054 #, c-format msgid "" "Incorrect reverse-mapping: saw (%u/%u) %slen %u owner % %s%soff " "%; should be (%u/%u) %slen %u owner % %s%soff %\n" msgstr "" #: .././repair/rmap.c:1189 #, c-format msgid "setting reflink flag on inode %\n" msgstr "" #: .././repair/rmap.c:1193 #, c-format msgid "clearing reflink flag on inode %\n" msgstr "" #: .././repair/rmap.c:1264 #, c-format msgid "Unable to fix reflink flag on inode %.\n" msgstr "" #: .././repair/rmap.c:1325 msgid "would rebuild corrupt refcount btrees.\n" msgstr "" #: .././repair/rmap.c:1358 .././repair/rmap.c:1369 #, c-format msgid "Missing reference count record for (%u/%u) len %u count %u\n" msgstr "" #: .././repair/rmap.c:1380 #, c-format msgid "" "Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) " "len %u nlinks %u\n" msgstr "" #: .././repair/rmap.c:1422 .././repair/rmap.c:1453 #, fuzzy, c-format msgid "failed to fix AGFL on AG %d, error %d\n" msgstr "%s: Kopf und Ende zu finden fehlgeschlagen, Fehler: %d\n" #: .././repair/rt.c:47 msgid "couldn't allocate memory for incore realtime bitmap.\n" msgstr "Speicher für Incore-Echtzeit-Bitmap kann nicht alloziert werden.\n" #: .././repair/rt.c:51 msgid "couldn't allocate memory for incore realtime summary info.\n" msgstr "" "Speicher für Incore-Echtzeit-Zusammenfassungs-Info kann nicht alloziert\n" "werden.\n" #: .././repair/rt.c:203 #, c-format msgid "can't find block %d for rtbitmap inode\n" msgstr "Block %d für rtbitmap-Inode kann nicht gefunden werden\n" #: .././repair/rt.c:211 #, c-format msgid "can't read block %d for rtbitmap inode\n" msgstr "Block %d für rtbitmap-Inode kann nicht gelesen werden\n" #: .././repair/rt.c:265 #, c-format msgid "block %d for rtsummary inode is missing\n" msgstr "Block %d für rtsummary-Inode fehlt\n" #: .././repair/rt.c:273 #, c-format msgid "can't read block %d for rtsummary inode\n" msgstr "Block %d für rtsummary-Inode kann nicht gelesen werden\n" #: .././repair/sb.c:125 msgid "error finding secondary superblock -- failed to memalign buffer\n" msgstr "" "Fehler beim Finden eines zweiten Superblocks -- memalign des Puffers\n" "fehlgeschlagen\n" #: .././repair/sb.c:162 msgid "found candidate secondary superblock...\n" msgstr "Kandidat für zweiten Superblock gefunden...\n" #: .././repair/sb.c:174 msgid "verified secondary superblock...\n" msgstr "zweiter Superblock geprüft...\n" #: .././repair/sb.c:179 msgid "unable to verify superblock, continuing...\n" msgstr "außerstande Superblock zu prüfen, wird fortgesetzt...\n" #: .././repair/sb.c:229 msgid "" "\n" "attempting to find secondary superblock...\n" msgstr "" "\n" "es wird versucht einen zweiten Superblock zu finden...\n" #: .././repair/sb.c:510 msgid "failed to memalign superblock buffer\n" msgstr "memalign des Superblock-Puffers fehlgeschlagen\n" #: .././repair/sb.c:517 msgid "couldn't seek to offset 0 in filesystem\n" msgstr "Versatz 0 im Dateisystem kann nicht positioniert werden\n" #: .././repair/sb.c:527 msgid "primary superblock write failed!\n" msgstr "Schreiben der primären Superblock fehlgeschlagen!\n" #: .././repair/sb.c:545 #, c-format msgid "error reading superblock %u -- failed to memalign buffer\n" msgstr "" "Fehler beim Lesen des Superblocks %u - memalign des Puffers\n" "fehlgeschlagen\n" #: .././repair/sb.c:556 #, fuzzy, c-format msgid "error reading superblock %u -- seek to offset % failed\n" msgstr "" "Fehler beim Lesen des Superblocks %u - positionieren des Versatzes %lld\n" "fehlgeschlagen\n" #: .././repair/sb.c:565 #, fuzzy, c-format msgid "superblock read failed, offset %, size %d, ag %u, rval %d\n" msgstr "" "Lesen des Superblocks fehlgeschlagen, Versatz %lld, Größe %d, ag %u,\n" "rval %d\n" #: .././repair/sb.c:612 msgid "couldn't malloc geometry structure\n" msgstr "malloc konnte nicht für Geometriestruktur erfolgen\n" #: .././repair/sb.c:766 msgid "" "Only two AGs detected and they do not match - cannot validate filesystem " "geometry.\n" "Use the -o force_geometry option to proceed.\n" msgstr "" "Nur zwei AGs wurden entdeckt und diese passen nicht - die Geometrie des\n" "Dateisystems konnte nicht bestätigt werden.\n" #: .././repair/sb.c:782 msgid "" "Only one AG detected - cannot validate filesystem geometry.\n" "Use the -o force_geometry option to proceed.\n" msgstr "" "Nur ein AGs wurde entdeckt - die Geometrie des Dateisystems konnte nicht\n" "bestätigt werden.\n" "Benutzen Sie die force_geometry-Option -o um fortzufahren\n" #: .././repair/sb.c:797 msgid "Not enough matching superblocks - cannot proceed.\n" msgstr "" "Nicht genug passende Superblöcke - es kann nicht fortgefahren werden.\n" #: .././repair/sb.c:812 msgid "could not read superblock\n" msgstr "Superblock kann nicht gelesen werden\n" #: .././repair/scan.c:85 .././repair/scan.c:140 #, c-format msgid "can't read btree block %d/%d\n" msgstr "btree-Block %d/%d kann nicht gelesen werden\n" #: .././repair/scan.c:89 .././repair/scan.c:152 #, fuzzy, c-format msgid "btree block %d/%d is suspect, error %d\n" msgstr "Inode-Block %d/%d Status schlecht, (Status %d)\n" #: .././repair/scan.c:213 #, fuzzy, c-format msgid "bad magic # %#x in inode % (%s fork) bmbt block %\n" msgstr "falsche magische # %#x in Inode %llu (%s fork) bmbt Block %llu\n" #: .././repair/scan.c:219 #, fuzzy, c-format msgid "" "expected level %d got %d in inode %, (%s fork) bmbt block %\n" msgstr "" "erwartete Stufe %d hat %d in Inode %llu (%s Unterelement) bmbt Block %llu\n" #: .././repair/scan.c:229 #, fuzzy, c-format msgid "expected owner inode %, got %llu, bmbt block %\n" msgstr "erwartete Stufe %d hat %d in Inode %lld bmbt-Block %u/%u\n" #: .././repair/scan.c:237 #, fuzzy, c-format msgid "expected block %, got %llu, bmbt block %\n" msgstr "erwartete Stufe %d hat %d in Inode %lld bmbt-Block %u/%u\n" #: .././repair/scan.c:246 #, c-format msgid "wrong FS UUID, bmbt block %\n" msgstr "" #: .././repair/scan.c:266 #, fuzzy, c-format msgid "" "bad fwd (right) sibling pointer (saw % parent block says %)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "falscher fwd (rechts) Geschwisterzeiger (%llu gesehen Elternblock\n" "\tsagt %llu) in Inode %llu (%s Unterelement) bmap btree Block %llu\n" #: .././repair/scan.c:276 #, fuzzy, c-format msgid "" "bad back (left) sibling pointer (saw %llu parent block says %)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "falscher zurück (links) Geschwisterzeiger (%llu gesehen Elternblock\n" "\tsagt %llu) in Inode %llu (%s Unterelement) bmap btree Block %llu\n" #: .././repair/scan.c:291 #, fuzzy, c-format msgid "" "bad back (left) sibling pointer (saw %llu should be NULL (0))\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "falscher zurück (links) Geschwisterzeiger (%llu gesehen könnte NULL (0)\n" "\tsein) in Inode %llu (%s Unterelement) bmap btree Block %llu\n" #: .././repair/scan.c:339 #, fuzzy, c-format msgid "inode 0x%bmap block 0x% claimed, state is %d\n" msgstr "Inode 0x%llx bmap Block 0x%llx beansprucht, Status ist %d\n" #: .././repair/scan.c:346 #, fuzzy, c-format msgid "inode 0x% bmap block 0x% claimed, state is %d\n" msgstr "Inode 0x%llx bmap Block 0x%llx beansprucht, Status ist %d\n" #: .././repair/scan.c:361 #, fuzzy, c-format msgid "bad state %d, inode % bmap block 0x%\n" msgstr "falscher Status %d, Inode 0x%llx bmap Block 0x%llx\n" #: .././repair/scan.c:389 #, c-format msgid "couldn't add inode % bmbt block % reverse-mapping data." msgstr "" #: .././repair/scan.c:397 .././repair/scan.c:448 #, fuzzy, c-format msgid "inode % bad # of bmap records (%u, min - %u, max - %u)\n" msgstr "Inode 0x%llx falsche # von bmap-Datensätzen (%u, Min - %u, Max - %u)\n" #: .././repair/scan.c:427 #, fuzzy, c-format msgid "" "out-of-order bmap key (file offset) in inode %, %s fork, fsbno " "%\n" msgstr "" "bmap-Schlüssel außer Betrieb (Dateiversatz) in Inode %llu,\n" "%s Unterelement, fsbno %llu\n" #: .././repair/scan.c:465 #, fuzzy, c-format msgid "bad bmap btree ptr 0x%llx in ino %\n" msgstr "falscher bmap btree ptr 0x%llx in ino %llu\n" #: .././repair/scan.c:493 #, fuzzy, c-format msgid "" "correcting bt key (was %llu, now %) in inode %\n" "\t\t%s fork, btree block %\n" msgstr "" "bt-Schlüssel wird korrigiert (war %llu, nun %llu) in Inode %llu\n" "\t\t%s Unterelement, btree Block %llu\n" #: .././repair/scan.c:505 #, fuzzy, c-format msgid "" "bad btree key (is %llu, should be %) in inode %\n" "\t\t%s fork, btree block %\n" msgstr "" "falscher btree-Schlüssel (ist %llu, könnte %llu sein) in Inode %llu\n" "\t\t%s Unterelement, btree-Block %llu\n" #: .././repair/scan.c:523 #, fuzzy, c-format msgid "" "bad fwd (right) sibling pointer (saw % should be NULLFSBLOCK)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "falscher fwd (rechts) Geschwisterzeiger (%llu gesehen könnte NULLFSBLOCK\n" "\tsein) in Inode %llu (%s Unterelement) »bmap btree«-Block %llu\n" #: .././repair/scan.c:581 .././repair/scan.c:958 #, fuzzy, c-format msgid "bad magic # %#x in bt%s block %d/%d\n" msgstr "falsche magische # %#x in btbno-Block %d/%d\n" #: .././repair/scan.c:599 .././repair/scan.c:977 #, fuzzy, c-format msgid "expected level %d got %d in bt%s block %d/%d\n" msgstr "erwartete Stufe %d hat %d in btbno-Block %d/%d\n" #: .././repair/scan.c:613 #, fuzzy, c-format msgid "" "%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "bno freespace btree Block beansprucht (Status %d), agno %d, bno %d,\n" "Suspekt %d\n" #: .././repair/scan.c:633 .././repair/scan.c:734 .././repair/scan.c:1008 #: .././repair/scan.c:1152 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n" msgstr "falsche btree nrecs (%u, Min=%u, Max=%u) in btbno-Block %u/%u\n" #: .././repair/scan.c:651 .././repair/scan.c:1043 .././repair/scan.c:1329 #, c-format msgid "invalid start block %u in record %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:657 .././repair/scan.c:1049 .././repair/scan.c:1335 #, fuzzy, c-format msgid "invalid length %u in record %u of %s btree block %u/%u\n" msgstr "btree-Block %u/%u kann nicht gelesen werden\n" #: .././repair/scan.c:704 #, fuzzy, c-format msgid "block (%d,%d-%d) multiply claimed by %s space tree, state - %d\n" msgstr "Block (%d,%d) mehrfach beansprucht vonbno space tree, Status - %d\n" #: .././repair/scan.c:833 #, c-format msgid "" "Static meta block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:842 #, fuzzy, c-format msgid "AG meta block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "Block (%d,%d) mehrfach beansprucht vonbno space tree, Status - %d\n" #: .././repair/scan.c:850 #, fuzzy, c-format msgid "inode block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "Inode-Block %d/%d Status schlecht, (Status %d)\n" #: .././repair/scan.c:858 #, c-format msgid "" "AG refcount block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:867 #, fuzzy, c-format msgid "in use block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "Block (%d,%d) mehrfach beansprucht vonbno space tree, Status - %d\n" #: .././repair/scan.c:889 #, fuzzy, c-format msgid "unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%\n" msgstr "Block (%d,%d) mehrfach beansprucht vonbno space tree, Status - %d\n" #: .././repair/scan.c:989 #, fuzzy, c-format msgid "%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "Inode-btree-Block beansprucht (Status %d), agno %d, bno %d, verdächtig %d\n" #: .././repair/scan.c:1033 #, fuzzy, c-format msgid "invalid flags in record %u of %s btree block %u/%u\n" msgstr "btree-Block %u/%u kann nicht gelesen werden\n" #: .././repair/scan.c:1062 #, fuzzy, c-format msgid "invalid owner in rmap btree record %d (% %u) block %u/%u\n" msgstr "außer Betreib bno btree Datensatz %d (%u %u) Block %u/%u\n" #: .././repair/scan.c:1069 #, c-format msgid "" "record %d of block (%u/%u) in %s btree cannot have non-inode owner with " "flags\n" msgstr "" #: .././repair/scan.c:1073 #, c-format msgid "" "record %d of block (%u/%u) in %s btree cannot have non-inode owner with " "offset\n" msgstr "" #: .././repair/scan.c:1094 #, fuzzy, c-format msgid "" "out-of-order rmap btree record %d (%u % % %u) block %u/%u\n" msgstr "außer Betreib bno btree Datensatz %d (%u %u) Block %u/%u\n" #: .././repair/scan.c:1103 .././repair/scan.c:1381 #, c-format msgid "" "record %d in block (%u/%u) of %s tree should be merged with previous record\n" msgstr "" #: .././repair/scan.c:1118 #, c-format msgid "record %d greater than high key of block (%u/%u) in %s tree\n" msgstr "" #: .././repair/scan.c:1174 #, fuzzy, c-format msgid "invalid flags in key %u of %s btree block %u/%u\n" msgstr "falsche magische # %#x in btbno-Block %u/%u\n" #: .././repair/scan.c:1180 #, c-format msgid "key %d greater than high key of block (%u/%u) in %s tree\n" msgstr "" #: .././repair/scan.c:1206 #, c-format msgid "invalid flags in high key %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:1257 #, fuzzy, c-format msgid "bad magic # %#x in %s btree block %d/%d\n" msgstr "falsche magische # %#x in btbno-Block %d/%d\n" #: .././repair/scan.c:1265 #, fuzzy, c-format msgid "expected level %d got %d in %s btree block %d/%d\n" msgstr "erwartete Stufe %d hat %d in btbno-Block %d/%d\n" #: .././repair/scan.c:1279 #, fuzzy, c-format msgid "%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "Inode-btree-Block beansprucht (Status %d), agno %d, bno %d, verdächtig %d\n" #: .././repair/scan.c:1298 .././repair/scan.c:1415 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n" msgstr "falsche btree nrecs (%u, Min=%u, Max=%u) in btbno-Block %u/%u\n" #: .././repair/scan.c:1316 #, c-format msgid "" "leftover CoW extent has incorrect refcount in record %u of %s btree block %u/" "%u\n" msgstr "" #: .././repair/scan.c:1321 #, c-format msgid "" "leftover CoW extent has invalid startblock in record %u of %s btree block %u/" "%u\n" msgstr "" #: .././repair/scan.c:1356 #, fuzzy, c-format msgid "extent (%u/%u) len %u claimed, state is %d\n" msgstr "Inode 0x%llx bmap Block 0x%llx beansprucht, Status ist %d\n" #: .././repair/scan.c:1363 #, c-format msgid "invalid reference count %u in record %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:1370 #, fuzzy, c-format msgid "out-of-order %s btree record %d (%u %u) block %u/%u\n" msgstr "außer Betreib bno btree Datensatz %d (%u %u) Block %u/%u\n" #: .././repair/scan.c:1496 #, fuzzy, c-format msgid "badly aligned %s rec (starting inode = %)\n" msgstr "schlecht ausgerichteter Inode-rec (Start-Inode = %llu)\n" #: .././repair/scan.c:1510 #, fuzzy, c-format msgid "bad starting inode # (% (0x%x 0x%x)) in %s rec, skipping rec\n" msgstr "" "falsche Start-Inode # (%llu(0x%x 0x%x)) in ino rec, rec wird übersprungen\n" #: .././repair/scan.c:1519 #, fuzzy, c-format msgid "bad ending inode # (% (0x%x 0x%zx)) in %s rec, skipping rec\n" msgstr "" "falsch verschlüsselte Inode # (%llu (0x%x 0x%x)) in ino rec, rec wird\n" "übersprungen\n" #: .././repair/scan.c:1584 #, fuzzy, c-format msgid "" "ir_holemask/ir_free mismatch, %s chunk %d/%u, holemask 0x%x free 0x%llx\n" msgstr "" "ir_freecount/frei keine Übereinstimmung, Inode-Chunk %d/%d,\n" "freecount %d nfree %d\n" #: .././repair/scan.c:1671 #, c-format msgid "" "inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n" msgstr "" "Inode Chunk beansprucht benutzten Block, inobt Block - agno %d, bno %d,\n" "inopb %d\n" #: .././repair/scan.c:1689 #, fuzzy, c-format msgid "" "inode rec for ino % (%d/%d) overlaps existing rec (start %d/%d)\n" msgstr "" "Inode-rec für ino %llu (%d/%d) überlappt existierenden rec (Start %d/%d)\n" #: .././repair/scan.c:1713 #, fuzzy, c-format msgid "ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n" msgstr "" "ir_freecount/free Nichtübereinstimmung, Inode Speicherstück %u/%u, freecount " "%d nfree %d\n" #: .././repair/scan.c:1721 .././repair/scan.c:1911 #, fuzzy, c-format msgid "invalid inode count, inode chunk %d/%u, count %d ninodes %d\n" msgstr "" "ir_freecount/frei keine Übereinstimmung, Inode-Chunk %d/%d,\n" "freecount %d nfree %d\n" #: .././repair/scan.c:1775 #, fuzzy, c-format msgid "" "sparse inode chunk claims inode block, finobt block - agno %d, bno %d, inopb " "%d\n" msgstr "" "Inode Chunk beansprucht benutzten Block, inobt Block - agno %d, bno %d,\n" "inopb %d\n" #: .././repair/scan.c:1790 .././repair/scan.c:1802 #, fuzzy, c-format msgid "" "inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb " "%d\n" msgstr "" "Inode Chunk beansprucht benutzten Block, inobt Block - agno %d, bno %d,\n" "inopb %d\n" #: .././repair/scan.c:1812 #, fuzzy, c-format msgid "" "inode chunk claims used block, finobt block - agno %d, bno %d, inopb %d\n" msgstr "" "Inode Chunk beansprucht benutzten Block, inobt Block - agno %d, bno %d,\n" "inopb %d\n" #: .././repair/scan.c:1834 #, fuzzy, c-format msgid "" "finobt rec for ino % (%d/%u) does not match existing rec (%d/%d)\n" msgstr "" "Inode-rec für ino %llu (%d/%d) überlappt existierenden rec (Start %d/%d)\n" #: .././repair/scan.c:1876 #, c-format msgid "undiscovered finobt record, ino % (%d/%u)\n" msgstr "" #: .././repair/scan.c:1898 #, fuzzy, c-format msgid "" "finobt ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n" msgstr "" "ir_freecount/free Nichtübereinstimmung, Inode Speicherstück %u/%u, freecount " "%d nfree %d\n" #: .././repair/scan.c:1904 #, c-format msgid "finobt record with no free inodes, inode chunk %d/%u\n" msgstr "" #: .././repair/scan.c:1957 #, c-format msgid "bad magic # %#x in inobt block %d/%d\n" msgstr "falsche magische # %#x in inobt-Block %d/%d\n" #: .././repair/scan.c:1965 #, c-format msgid "expected level %d got %d in inobt block %d/%d\n" msgstr "erwartete Stufe %d hat %d in inobt-Block %d/%d\n" #: .././repair/scan.c:1988 #, c-format msgid "inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "Inode-btree-Block beansprucht (Status %d), agno %d, bno %d, verdächtig %d\n" #: .././repair/scan.c:2011 #, c-format msgid "dubious inode btree block header %d/%d\n" msgstr "fragwürdiger Inode-btree-Kopf %d/%d\n" #: .././repair/scan.c:2129 #, c-format msgid "can't read agfl block for ag %d\n" msgstr "agfl-Block für ag %d kann nicht gelesen werden\n" #: .././repair/scan.c:2133 #, fuzzy, c-format msgid "agfl has bad CRC for ag %d\n" msgstr "falscher sb für ag %d wird zurückgesetzt\n" #: .././repair/scan.c:2154 #, c-format msgid "bad agbno %u in agfl, agno %d\n" msgstr "falsche agbno %u in agfl, agno %d\n" #: .././repair/scan.c:2163 #, c-format msgid "freeblk count %d != flcount %d in ag %d\n" msgstr "freeblk-Anzahl %d != flcount %d in ag %d\n" #: .././repair/scan.c:2189 #, c-format msgid "bad agbno %u for btbno root, agno %d\n" msgstr "falscher agbno %u für btbno-Wurzel, agno %d\n" #: .././repair/scan.c:2201 #, c-format msgid "bad agbno %u for btbcnt root, agno %d\n" msgstr "falscher agbno %u für btbcnt-Wurzel, agno %d\n" #: .././repair/scan.c:2220 #, fuzzy, c-format msgid "bad rmapbt block count %u, saw %u\n" msgstr "falsche blockuse-Anzahl %s\n" #: .././repair/scan.c:2224 #, fuzzy, c-format msgid "bad agbno %u for rmapbt root, agno %d\n" msgstr "falscher agbno %u für inobt-Wurzel, agno %d\n" #: .././repair/scan.c:2241 #, fuzzy, c-format msgid "bad refcountbt block count %u, saw %u\n" msgstr "falsche blockuse-Anzahl %s\n" #: .././repair/scan.c:2245 #, fuzzy, c-format msgid "bad agbno %u for refcntbt root, agno %d\n" msgstr "falscher agbno %u für inobt-Wurzel, agno %d\n" #: .././repair/scan.c:2263 #, fuzzy, c-format msgid "agf_btreeblks %u, counted % in ag %u\n" msgstr "agf_btreeblks %u, gezählt %u in ag %u\n" #: .././repair/scan.c:2287 #, c-format msgid "bad agbno %u for inobt root, agno %d\n" msgstr "falscher agbno %u für inobt-Wurzel, agno %d\n" #: .././repair/scan.c:2300 #, fuzzy, c-format msgid "bad agbno %u for finobt root, agno %d\n" msgstr "falscher agbno %u für inobt-Wurzel, agno %d\n" #: .././repair/scan.c:2317 #, fuzzy, c-format msgid "agi_freecount %u, counted %u in ag %u finobt\n" msgstr "agi_freecount %u, gezählt %u in ag %u\n" #: .././repair/scan.c:2327 #, fuzzy, c-format msgid "agi unlinked bucket %d is %u in ag %u (inode=%)\n" msgstr "agi gelöster Verweis Behälter %d ist %u in ag %u (Inode=%lld)\n" #: .././repair/scan.c:2358 msgid "can't allocate memory for superblock\n" msgstr "Speicher für Superblock kann nicht alloziert werden\n" #: .././repair/scan.c:2365 #, fuzzy msgid "root superblock" msgstr "Superblock kann nicht gelesen werden\n" #: .././repair/scan.c:2374 #, fuzzy msgid "agf block" msgstr "Blöcke" #: .././repair/scan.c:2383 #, fuzzy msgid "agi block" msgstr "Blöcke" #: .././repair/scan.c:2404 #, c-format msgid "reset bad sb for ag %d\n" msgstr "falscher sb für ag %d wird zurückgesetzt\n" #: .././repair/scan.c:2407 #, c-format msgid "would reset bad sb for ag %d\n" msgstr "falscher sb für ag %d könnte zurückgesetzt werden\n" #: .././repair/scan.c:2412 #, c-format msgid "reset bad agf for ag %d\n" msgstr "falscher agf für ag %d wird zurückgesetzt\n" #: .././repair/scan.c:2415 #, c-format msgid "would reset bad agf for ag %d\n" msgstr "falscher agf für ag %d könnte zurückgesetzt werden\n" #: .././repair/scan.c:2420 #, c-format msgid "reset bad agi for ag %d\n" msgstr "falscher agi für ag %d wird zurückgesetzt\n" #: .././repair/scan.c:2423 #, c-format msgid "would reset bad agi for ag %d\n" msgstr "falscher agi für ag %d könnte zurückgesetzt werden\n" #: .././repair/scan.c:2428 #, c-format msgid "bad uncorrected agheader %d, skipping ag...\n" msgstr "falscher nicht berichtigter agheader %d, ag wird übersprungen...\n" #: .././repair/scan.c:2491 #, fuzzy, c-format msgid "can't get %s for ag %d\n" msgstr "Wurzel-Superblock für ag %d kann nicht erlangt werden\n" #: .././repair/scan.c:2511 msgid "no memory for ag header counts\n" msgstr "" #: .././repair/scan.c:2537 #, fuzzy, c-format msgid "sb_icount %, counted %\n" msgstr "sb_icount %lld, gezählt %lld\n" #: .././repair/scan.c:2542 #, fuzzy, c-format msgid "sb_ifree %, counted %\n" msgstr "sb_ifree %lld, gezählt %lld\n" #: .././repair/scan.c:2547 #, fuzzy, c-format msgid "sb_fdblocks %, counted %\n" msgstr "sb_fdblocks %lld, gezählt %lld\n" #: .././repair/scan.c:2553 #, fuzzy, c-format msgid "used blocks %, counted %\n" msgstr "sb_fdblocks %lld, gezählt %lld\n" #: .././repair/threads.c:90 #, c-format msgid "cannot create worker threads, error = [%d] %s\n" msgstr "Arbeiter-Threads können nicht erzeugt werden, Fehler = [%d] %s\n" #: .././repair/threads.c:108 #, c-format msgid "cannot allocate worker item, error = [%d] %s\n" msgstr "Arbeiter-Gegenstand kann nicht alloziert werden, Fehler = [%d] %s\n" #: .././repair/versions.c:68 #, c-format msgid "bogus quota flags 0x%x set in superblock" msgstr "fingierte Quota-Markierungen 0x%x im Superblock gesetzt" #: .././repair/versions.c:74 msgid ", bogus flags will be cleared\n" msgstr ", fingierte Markierungen werden bereinigt\n" #: .././repair/versions.c:76 msgid ", bogus flags would be cleared\n" msgstr ", fingierte Markierungen könnten bereinigt werden\n" #: .././repair/versions.c:115 .././repair/versions.c:120 #: .././repair/versions.c:125 msgid "Shared Version bit set. Not supported. Ever.\n" msgstr "" #: .././repair/versions.c:138 msgid "This filesystem has uninitialized extent flags.\n" msgstr "Dieses Dateisystem hat nicht initialisierte Ausmaß-Markierungen\n" #: .././repair/versions.c:144 msgid "" "This filesystem uses feature(s) not yet supported in this release.\n" "Please run a more recent version of xfs_repair.\n" msgstr "" "Dieses Dateisystem benutzt Merkmale, die von dieser Veröffentlichung\n" "noch nicht unterstützt werden.\n" "Bitte führen Sie eine aktuellere Version von xfs_repair aus.\n" #: .././repair/versions.c:150 #, c-format msgid "WARNING: unknown superblock version %d\n" msgstr "WARNUNG: unbekannte Superblock-Version %d\n" #: .././repair/versions.c:153 msgid "This filesystem contains features not understood by this program.\n" msgstr "" "Dieses Dateisystem enthält Merkmale, die von diesem Programm nicht\n" "verstanden werden.\n" #: .././repair/versions.c:161 msgid "" "WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twill be downgraded. This may cause loss of filesystem meta-data\n" msgstr "" "WARNUNG: Sie haben superblock-feature-bits-allowed verboten, aber dieser\n" "\tSuperblock hat Funktions-Bits. Der Superblock wird herabgestuft. Dies\n" "\tkann den Verlust von Dateisystem-Metadaten zur Folge haben\n" #: .././repair/versions.c:166 msgid "" "WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twould be downgraded. This might cause loss of filesystem\n" "\tmeta-data.\n" msgstr "" "WARNUNG: Sie haben superblock-feature-bits-allowed verboten, aber dieser\n" "\tSuperblock hat Funktions-Bits. Der Superblock wird herabgestuft. Dies\n" "\tkönnte den Verlust von Dateisystem-Metadaten zur Folge haben\n" #: .././repair/versions.c:182 #, c-format msgid "" "Superblock has unknown compat/rocompat/incompat features (0x%x/0x%x/0x%x).\n" "Using a more recent xfs_repair is recommended.\n" msgstr "" #: .././repair/versions.c:194 msgid "" "WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attributes will be removed.\n" msgstr "" "WARNUNG: Sie haben Attribute verboten, aber dieses Dateisystem hat\n" "\tAttribute. Das Dateisystem wird herabgestuft und alle Attribute werden\n" "\tentfernt\n" #: .././repair/versions.c:199 msgid "" "WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attributes would be removed.\n" msgstr "" "WARNUNG: Sie haben Attribute verboten, aber dieses Dateisystem hat\n" "\tAttribute. Das Dateisystem könnte herabgestuft und alle Attribute\n" "\tentfernt werden\n" #: .././repair/versions.c:212 msgid "" "WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attr2 attributes will be removed.\n" msgstr "" "WARNUNG: Sie haben attr2-Attribute verboten, aber dieses Dateisystem hat\n" "\tAttribute. Das Dateisystem wird herabgestuft und alle attr2-Attribute\n" "\twerden entfernt\n" #: .././repair/versions.c:217 msgid "" "WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attr2 attributes would be removed.\n" msgstr "" "WARNUNG: Sie haben attr2-Attribute verboten, aber dieses Dateisystem hat\n" "\tAttribute. Das Dateisystem wird herabgestuft und alle attr2-Attribute\n" "\twerden entfernt\n" #: .././repair/versions.c:229 msgid "" "WARNING: you have a V1 inode filesystem. It will be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././repair/versions.c:234 msgid "" "WARNING: you have a V1 inode filesystem. It would be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././repair/versions.c:244 msgid "" "WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem will be downgraded and\n" "\tall quota information will be removed.\n" msgstr "" "WARNUNG: Sie haben Quota verboten, aber dieses Dateisystem hat\n" "\tQuota. Das Dateisystem wird herabgestuft und jegliche Quota-\n" "\tInformation wird entfernt.\n" #: .././repair/versions.c:249 msgid "" "WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem would be downgraded and\n" "\tall quota information would be removed.\n" msgstr "" "WARNUNG: Sie haben Quota verboten, aber dieses Dateisystem hat\n" "\tQuota. Das Dateisystem könnte herabgestuft und jegliche Quota-\n" "\tInformation entfernt werden.\n" #: .././repair/versions.c:277 msgid "" "WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem will be downgraded.\n" "\tThis will permanently degrade the performance of this filesystem.\n" msgstr "" "WARNUNG: Sie haben angepasste Inodes verboten, aber dieses Dateisystem\n" "\that angepasste Inodes. Das Dateisystem wird herabgestuft.\n" "\tDies wird die Leistungsfähigkeit des Dateisystems dauerhaft mindern.\n" #: .././repair/versions.c:282 msgid "" "WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem would be downgraded.\n" "\tThis would permanently degrade the performance of this filesystem.\n" msgstr "" "WARNUNG: Sie haben angepasste Inodes verboten, aber dieses Dateisystem\n" "\that angepasste Inodes. Das Dateisystem könnte herabgestuft werden.\n" "\tDies könnte die Leistungsfähigkeit des Dateisystems dauerhaft mindern\n" #: .././repair/xfs_repair.c:85 #, fuzzy, c-format msgid "" "Usage: %s [options] device\n" "\n" "Options:\n" " -f The device is a file\n" " -L Force log zeroing. Do this as a last resort.\n" " -l logdev Specifies the device where the external log resides.\n" " -m maxmem Maximum amount of memory to be used in megabytes.\n" " -n No modify mode, just checks the filesystem for damage.\n" " -P Disables prefetching.\n" " -r rtdev Specifies the device where the realtime section resides.\n" " -v Verbose output.\n" " -c subopts Change filesystem parameters - use xfs_admin.\n" " -o subopts Override default behaviour, refer to man page.\n" " -t interval Reporting interval in seconds.\n" " -d Repair dangerously.\n" " -V Reports version and exits.\n" msgstr "" "Aufruf: %s [Optionen] Gerät\n" "\n" "Optionen:\n" " -f Das Gerät ist eine Datei\n" " -L Protokoll auf Null setzen erzwingen. Tun Sie dies als\n" " letzten Ausweg.\n" " -l logdev Gibt das Gerät an, auf dem das externe Protokoll liegt.\n" " -m maxmem Maximaler Wert von Speicher zum benutzen in Megabyte.\n" " -n Unveränderlicher Modus, prüft das Dateisystem nur auf\n" " Schäden.\n" " -P Vorher holen abgeschaltet.\n" " -r rtdev Gibt das Gerät an, auf dem der Echtzeitbereich liegt.\n" " -v Ausführliche Ausgabe.\n" " -c subopts Dateisystem-Parameter ändern - xfs_admin benutzen.\n" " -o subopts Standardverhalten überschreiben, bezogen auf Handbuchseite.\n" " -t interval Berichtsintervall in Minuten.\n" " -d Gefährliche Reparatur.\n" " -V Version anzeigen und beenden.\n" #: .././repair/xfs_repair.c:111 msgid "no error" msgstr "kein Fehler" #: .././repair/xfs_repair.c:112 msgid "bad magic number" msgstr "falsche Magische Nummer" #: .././repair/xfs_repair.c:113 msgid "bad blocksize field" msgstr "falsches Blockgrößen-Feld" #: .././repair/xfs_repair.c:114 msgid "bad blocksize log field" msgstr "falsches Blockgrößen-Protokoll-Feld" #: .././repair/xfs_repair.c:115 msgid "bad or unsupported version" msgstr "falsche oder nicht unterstützte Version" #: .././repair/xfs_repair.c:117 msgid "filesystem mkfs-in-progress bit set" msgstr "mkfs-in-progress-Bit des Dateisystems gesetzt" #: .././repair/xfs_repair.c:119 msgid "inconsistent filesystem geometry information" msgstr "unvollständige Information über die Geometrie des Dateisystems" #: .././repair/xfs_repair.c:121 msgid "bad inode size or inconsistent with number of inodes/block" msgstr "falsche Inode-Größe oder unvollständig mit Anzahl der Inodes/Block" #: .././repair/xfs_repair.c:122 msgid "bad sector size" msgstr "falsche Bereichsgröße" #: .././repair/xfs_repair.c:124 msgid "AGF geometry info conflicts with filesystem geometry" msgstr "AGF-Geometrie-Info hat einen Konflikt mit der Dateisystem-Geometrie" #: .././repair/xfs_repair.c:126 msgid "AGI geometry info conflicts with filesystem geometry" msgstr "AGI-Geometrie-Info hat einen Konflikt mit der Dateisystem-Geometrie" #: .././repair/xfs_repair.c:128 msgid "AG superblock geometry info conflicts with filesystem geometry" msgstr "" "AG-Superblock-Geometrie-Info hat einen Konflikt mit der\n" "Dateisystem-Geometrie" #: .././repair/xfs_repair.c:129 msgid "attempted to perform I/O beyond EOF" msgstr "versucht ein I/O jenseits von EOF auszuführen" #: .././repair/xfs_repair.c:131 msgid "inconsistent filesystem geometry in realtime filesystem component" msgstr "" "unvollständige Dateisystem-Geometrie in Echtzeit-Dateisystem-Komponente" #: .././repair/xfs_repair.c:133 msgid "maximum indicated percentage of inodes > 100%" msgstr "maximal angezeigte Prozentzahl der Inodes > 100%" #: .././repair/xfs_repair.c:135 msgid "inconsistent inode alignment value" msgstr "uneinheitlicher Inode-Ausrichtungswert" #: .././repair/xfs_repair.c:137 msgid "not enough secondary superblocks with matching geometry" msgstr "nicht genug sekundäre Superblöcke mit passender Geometrie" #: .././repair/xfs_repair.c:139 msgid "bad stripe unit in superblock" msgstr "falsche Stripe-Einheit in Superblock" #: .././repair/xfs_repair.c:141 msgid "bad stripe width in superblock" msgstr "falsche Stripe-Breite in Superblock" #: .././repair/xfs_repair.c:143 msgid "bad shared version number in superblock" msgstr "falsche verteilte Versionsnummer im Superblock" #: .././repair/xfs_repair.c:145 #, fuzzy msgid "bad CRC in superblock" msgstr "falsche Stripe-Einheit in Superblock" #: .././repair/xfs_repair.c:150 #, c-format msgid "bad error code - %d\n" msgstr "falscher Fehler-Code - %d\n" #: .././repair/xfs_repair.c:158 #, c-format msgid "-%c %s option cannot have a value\n" msgstr "-%c %s-Option kann keinen Wert haben\n" #: .././repair/xfs_repair.c:248 #, fuzzy msgid "-o ihash option has been removed and will be ignored\n" msgstr "-o bhash-Option kann nicht mit der -m-Option benutzt werden\n" #: .././repair/xfs_repair.c:253 msgid "-o bhash option cannot be used with -m option\n" msgstr "-o bhash-Option kann nicht mit der -m-Option benutzt werden\n" #: .././repair/xfs_repair.c:305 msgid "-m option cannot be used with -o bhash option\n" msgstr "-m-Option kann nicht mit der -o bhash-Option benutzt werden\n" #: .././repair/xfs_repair.c:347 #, c-format msgid "" "\n" "fatal error -- " msgstr "" "\n" "schwerwiegender Fehler -- " #: .././repair/xfs_repair.c:474 #, fuzzy, c-format msgid "sb root inode value % %sinconsistent with calculated value %u\n" msgstr "sb-Wurzel-Inode-Wert %llu %suneinheitlich mit berechnetem Wert %lu\n" #: .././repair/xfs_repair.c:481 #, fuzzy, c-format msgid "resetting superblock root inode pointer to %u\n" msgstr "Superblock-Wurzel-Inode-Zeiger wird auf %lu zurückgesetzt\n" #: .././repair/xfs_repair.c:485 #, fuzzy, c-format msgid "would reset superblock root inode pointer to %u\n" msgstr "Superblock-Wurzel-Inode-Zeiger könnte auf %lu zurückgesetzt werden\n" #: .././repair/xfs_repair.c:497 #, fuzzy, c-format msgid "" "sb realtime bitmap inode % %sinconsistent with calculated value %u\n" msgstr "" "sb-Echtzeit-Bitmap-Inode %llu %suneinheitlich mit berechnetem Wert %lu\n" #: .././repair/xfs_repair.c:504 #, fuzzy, c-format msgid "resetting superblock realtime bitmap ino pointer to %u\n" msgstr "Superblock-Echtzeit-Bitmap-ino-Zeiger wird auf %lu zurückgesetzt\n" #: .././repair/xfs_repair.c:508 #, fuzzy, c-format msgid "would reset superblock realtime bitmap ino pointer to %u\n" msgstr "" "Superblock-Echtzeit-Bitmap-ino-Zeiger könnte auf %lu zurückgesetzt werden\n" #: .././repair/xfs_repair.c:520 #, fuzzy, c-format msgid "" "sb realtime summary inode % %sinconsistent with calculated value %u\n" msgstr "" "sb-Echtzeit-Zusammenfassungs-Inode %llu %suneinheitlich mit berechnetem\n" "Wert %lu\n" #: .././repair/xfs_repair.c:527 #, fuzzy, c-format msgid "resetting superblock realtime summary ino pointer to %u\n" msgstr "" "Superblock-Echtzeit-Zusammenfassungs-ino-Zeiger wird auf %lu zurückgesetzt\n" #: .././repair/xfs_repair.c:531 #, fuzzy, c-format msgid "would reset superblock realtime summary ino pointer to %u\n" msgstr "" "Superblock-Echtzeit-Zusammenfassungs-ino-Zeiger könnte auf %lu\n" "zurückgesetzt werden\n" #: .././repair/xfs_repair.c:587 #, c-format msgid "Maximum metadata LSN (%d:%d) is ahead of log (%d:%d).\n" msgstr "" #: .././repair/xfs_repair.c:591 #, c-format msgid "Would format log to cycle %d.\n" msgstr "" #: .././repair/xfs_repair.c:595 #, c-format msgid "Format log to cycle %d.\n" msgstr "" #: .././repair/xfs_repair.c:663 msgid "" "Primary superblock would have been modified.\n" "Cannot proceed further in no_modify mode.\n" "Exiting now.\n" msgstr "" "Primärer Superblock könnte verändert worden sein.\n" "Es kann nicht im no_modify.Modus fortgefahren werden.\n" "Es wird nun beendet.\n" #: .././repair/xfs_repair.c:671 msgid "" "Primary superblock bad after phase 1!\n" "Exiting now.\n" msgstr "" #: .././repair/xfs_repair.c:682 #, fuzzy, c-format msgid "%s: couldn't stat \"%s\"\n" msgstr "%s: kann Quellenstatus »%s« nicht abfragen.\n" #: .././repair/xfs_repair.c:699 msgid "" "Cannot get host filesystem geometry.\n" "Repair may fail if there is a sector size mismatch between\n" "the image and the host filesystem.\n" msgstr "" #: .././repair/xfs_repair.c:711 msgid "" "Sector size on host filesystem larger than image sector size.\n" "Cannot turn off direct IO, so exiting.\n" msgstr "" #: .././repair/xfs_repair.c:728 #, c-format msgid "%s: cannot repair this filesystem. Sorry.\n" msgstr "%s: Dieses Dateisystem kann nicht repariert werden. Entschuldigung.\n" #: .././repair/xfs_repair.c:804 #, c-format msgid " - reporting progress in intervals of %s\n" msgstr " - Berichts-Prozess in Abständen von %s\n" #: .././repair/xfs_repair.c:849 #, fuzzy, c-format msgid "" " - max_mem = %lu, icount = %, imem = %, dblock = " "%, dmem = %\n" msgstr "" " - max_mem = %lu, icount = %llu, imem = %llu, dblock = %llu, dmem = " "%llu\n" #: .././repair/xfs_repair.c:858 #, fuzzy, c-format msgid "" "Required memory for repair is greater that the maximum specified\n" "with the -m option. Please increase it to at least %lu.\n" msgstr "" "Benötigter Speicher für die Reparatur ist größer als das mit der\n" "-m-Option angegebene Maximum. Bitte erhöhen Sie es auf mindestens %lu.\n" #: .././repair/xfs_repair.c:863 #, c-format msgid "" "Memory available for repair (%luMB) may not be sufficient.\n" "At least %luMB is needed to repair this filesystem efficiently\n" "If repair fails due to lack of memory, please\n" msgstr "" #: .././repair/xfs_repair.c:869 msgid "turn prefetching off (-P) to reduce the memory footprint.\n" msgstr "" #: .././repair/xfs_repair.c:872 #, c-format msgid "increase system RAM and/or swap space to at least %luMB.\n" msgstr "" #: .././repair/xfs_repair.c:887 #, c-format msgid " - block cache size set to %d entries\n" msgstr " - Block-Zwischenspeichergröße ist auf %d Einträge gesetzt\n" #: .././repair/xfs_repair.c:912 msgid "Found unsupported filesystem features. Exiting now.\n" msgstr "" "Es wurden nicht unterstützte Dateisystemmerkmale gefunden. Es wird nun\n" "beendet.\n" #: .././repair/xfs_repair.c:930 #, c-format msgid "No modify flag set, skipping phase 5\n" msgstr "Kein Veränderungskennzeichen gesetzt, Phase 5 wird übersprungen\n" #: .././repair/xfs_repair.c:950 msgid "Inode allocation btrees are too corrupted, skipping phases 6 and 7\n" msgstr "" "Inode-Allokations-btrees sind zu beschädigt, Phasen 6 und 7 werden\n" "übersprungen\n" #: .././repair/xfs_repair.c:956 msgid "Warning: no quota inodes were found. Quotas disabled.\n" msgstr "Warnung: Keine Quota-Inodes wurden gefunden. Quota ausgeschaltet\n" #: .././repair/xfs_repair.c:959 msgid "Warning: no quota inodes were found. Quotas would be disabled.\n" msgstr "" "Warnung: Keine Quota-Inodes wurden gefunden. Quota könnte ausgeschaltet\n" "sein\n" #: .././repair/xfs_repair.c:964 msgid "Warning: quota inodes were cleared. Quotas disabled.\n" msgstr "Warnung: Quota-Inodes wurden bereinigt. Quota ausgeschaltet\n" #: .././repair/xfs_repair.c:967 msgid "Warning: quota inodes would be cleared. Quotas would be disabled.\n" msgstr "" "Warnung: Quota-Inodes könnten bereinigt werden. Quota könnte\n" "ausgeschaltet sein\n" #: .././repair/xfs_repair.c:973 msgid "" "Warning: user quota information was cleared.\n" "User quotas can not be enforced until limit information is recreated.\n" msgstr "" "Warnung: Benutzer-Quota-Information wurde bereinigt.\n" "Benutzer-Quota können nicht erzwungen werden bis die\n" "Beschränkungsinformation neu erzeugt wurde.\n" #: .././repair/xfs_repair.c:977 msgid "" "Warning: user quota information would be cleared.\n" "User quotas could not be enforced until limit information was recreated.\n" msgstr "" "Warnung: Benutzer-Quota-Information könnte bereinigt werden.\n" "Benutzer-Quota kann nicht erzwungen werden bis die\n" "Beschränkungsinformation neu erzeugt wurde.\n" #: .././repair/xfs_repair.c:985 msgid "" "Warning: group quota information was cleared.\n" "Group quotas can not be enforced until limit information is recreated.\n" msgstr "" "Warnung: Gruppen-Quota-Information wurde bereinigt.\n" "Gruppen-Quota kann nicht erzwungen werden bis die\n" "Beschränkungsinformation neu erzeugt wurde.\n" #: .././repair/xfs_repair.c:989 msgid "" "Warning: group quota information would be cleared.\n" "Group quotas could not be enforced until limit information was recreated.\n" msgstr "" "Warnung: Gruppen-Quota-Information könnte bereinigt werden.\n" "Gruppen-Quota kann nicht erzwungen werden bis die\n" "Beschränkungsinformation neu erzeugt wurde.\n" #: .././repair/xfs_repair.c:997 msgid "" "Warning: project quota information was cleared.\n" "Project quotas can not be enforced until limit information is recreated.\n" msgstr "" "Warnung: Projekt-Quota-Information wurde bereinigt.\n" "Projekt-Quota kann nicht erzwungen werden bis die\n" "Beschränkungsinformation neu erzeugt wurde.\n" #: .././repair/xfs_repair.c:1001 msgid "" "Warning: project quota information would be cleared.\n" "Project quotas could not be enforced until limit information was recreated.\n" msgstr "" "Warnung: Projekt-Quota-Information könnte bereinigt werden.\n" "Projekt-Quota kann nicht erzwungen werden bis die\n" "Beschränkungsinformation neu erzeugt wurde.\n" #: .././repair/xfs_repair.c:1018 msgid "No modify flag set, skipping filesystem flush and exiting.\n" msgstr "" "Kein Änderungskennzeichen gesetzt, Leeren des Dateisystems wird\n" "übersprungen und es wird beendet\n" #: .././repair/xfs_repair.c:1037 msgid "Note - quota info will be regenerated on next quota mount.\n" msgstr "" "Anmerkung - Quota-Information wird beim nächsten Einhängen des Quotas neu\n" "erzeugt\n" #: .././repair/xfs_repair.c:1044 #, fuzzy, c-format msgid "" "Note - stripe unit (%d) and width (%d) were copied from a backup " "superblock.\n" "Please reset with mount -o sunit=,swidth= if necessary\n" msgstr "" "Beachten Sie - Stripe-Einheit (%d) und -Beite (%d) Felder wurden\n" "zurückgesetzt. Bitte setzen Sie mit mount -o sunit=,swidth=\n" #: .././repair/xfs_repair.c:1068 msgid "done\n" msgstr "erledigt\n" #: .././repair/xfs_repair.c:1072 msgid "Repair of readonly mount complete. Immediate reboot encouraged.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:30 #, fuzzy, c-format msgid "%s [-e extsize] [-p] [-V] source target\n" msgstr "%s [-e extsize] [-p] Quelle Ziel\n" #: .././rtcp/xfs_rtcp.c:69 #, c-format msgid "%s: must specify files to copy\n" msgstr "%s: Dateien zum Kopieren müssen angegeben werden\n" #: .././rtcp/xfs_rtcp.c:84 #, c-format msgid "%s: stat of %s failed\n" msgstr "%s: stat von %s fehlgeschlagen\n" #: .././rtcp/xfs_rtcp.c:91 #, c-format msgid "%s: final argument is not directory\n" msgstr "%s: letztes Argument ist kein Verzeichnis\n" #: .././rtcp/xfs_rtcp.c:138 #, c-format msgid "%s: failed stat on %s: %s\n" msgstr "%s: stat auf %s fehlgeschlagen: %s\n" #: .././rtcp/xfs_rtcp.c:159 #, c-format msgid "%s: %s filesystem has no realtime partition\n" msgstr "%s: %s-Dateisystem hat keine Echtzeit-Partition\n" #: .././rtcp/xfs_rtcp.c:180 .././rtcp/xfs_rtcp.c:208 #, c-format msgid "%s: open of %s failed: %s\n" msgstr "%s: Öffnen auf %s fehlgeschlagen: %s\n" #: .././rtcp/xfs_rtcp.c:197 #, c-format msgid "%s: set attributes on %s failed: %s\n" msgstr "%s: Setzen von Attributen auf %s fehlgeschlagen: %s\n" #: .././rtcp/xfs_rtcp.c:215 #, c-format msgid "%s: get attributes of %s failed: %s\n" msgstr "%s: Erhalten von Attributen auf %s fehlgeschlagen: %s\n" #: .././rtcp/xfs_rtcp.c:225 .././rtcp/xfs_rtcp.c:262 #, c-format msgid "%s: %s is not a realtime file.\n" msgstr "%s: %s ist keine Echtzeit-Datei.\n" #: .././rtcp/xfs_rtcp.c:235 #, c-format msgid "%s: %s file extent size is %d, instead of %d.\n" msgstr "%s: %s Dateiumfanggröße ist %d anstelle von %d.\n" #: .././rtcp/xfs_rtcp.c:248 .././rtcp/xfs_rtcp.c:271 #, c-format msgid "%s: open of %s source failed: %s\n" msgstr "%s: Öffnen von %s-Quelle fehlgeschlagen:%s\n" #: .././rtcp/xfs_rtcp.c:285 #, c-format msgid "%s: couldn't get direct I/O information: %s\n" msgstr "%s: direkte I/O-Information kann nicht erlangt werden: %s\n" #: .././rtcp/xfs_rtcp.c:295 #, c-format msgid "%s: extent size %d not a multiple of %d.\n" msgstr "%s: Umfanggröße %d ist kein Vielfaches von %d.\n" #: .././rtcp/xfs_rtcp.c:309 #, c-format msgid "The size of %s is not a multiple of %d.\n" msgstr "Die Größe von %s ist kein Vielfaches von %d.\n" #: .././rtcp/xfs_rtcp.c:312 #, c-format msgid "%s will be padded to %lld bytes.\n" msgstr "%s wird auf %lld Bytes aufgefüllt.\n" #: .././rtcp/xfs_rtcp.c:318 #, c-format msgid "" "Use the -p option to pad %s to a size which is a multiple of %d bytes.\n" msgstr "" "Benutzen Sie die -p-Option um %s auf eine Größe aufzufüllen, die ein\n" "Vielfaches von %d Bytes ist.\n" #: .././rtcp/xfs_rtcp.c:360 #, c-format msgid "%s: write error: %s\n" msgstr "%s: Schreibfehler: %s\n" #: .././rtcp/xfs_rtcp.c:388 #, c-format msgid "%s: could not open %s: %s\n" msgstr "%s: %s kann nicht geöffnet werden: %s\n" #: .././copy/xfs_copy.c:155 msgid "lseek64 error" msgstr "lseek64-Fehler" #: .././copy/xfs_copy.c:256 #, c-format msgid "%s: lseek64 error on target %d \"%s\" at offset %lld\n" msgstr "%s: lseek64-Fehler auf Ziel %d »%s« bei Versatz %lld\n" #: .././copy/xfs_copy.c:383 #, c-format msgid "%s: lseek64 failure at offset %lld\n" msgstr "%s: lseek64-Fehlschlag bei Versatz %lld\n" #: .././db/write.c:58 #, fuzzy msgid "" "\n" " The 'write' command takes on different personalities depending on the\n" " type of object being worked with.\n" "\n" " Write has 3 modes:\n" " 'struct mode' - is active anytime you're looking at a filesystem object\n" " which contains individual fields (ex: an inode).\n" " 'data mode' - is active anytime you set a disk address directly or set\n" " the type to 'data'.\n" " 'string mode' - only used for writing symlink blocks.\n" "\n" " Examples:\n" " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n" " 'write fname \"hello\\000\"' - write superblock fname.\n" " (note: in struct mode strings are not null terminated)\n" " 'write fname #6669736800' - write superblock fname with " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - write superblock uuid.\n" " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n" " 'write lshift 3' - shift the block 3 bytes to the left\n" " 'write sequence 1 5' - write a cycle of number [1-5] through\n" " the entire block.\n" " String mode: 'write \"This_is_a_filename\" - write null terminated " "string.\n" "\n" " In data mode type 'write' by itself for a list of specific commands.\n" "\n" " Specifying the -c option will allow writes of invalid (corrupt) data.\n" "\n" msgstr "" "\n" " Der »write«-Befehl nimmt abhängig vom Typ des Objekts, mit dem gearbeitet\n" " wird, unterschiedliche Persönlichkeiten an.\n" "\n" " Write hat drei Modi:\n" " »Strukturmodus« - ist jederzeit aktiv, wenn Sie ein\n" " Dateisystemobjekt ansehen, das individuelle\n" " Felder enthält (z.B.: Einen Inode.\n" " »Datenmodus« - ist jederzeit aktiv, wenn Sie eine Plattenadresse\n" " direkt setzen oder den Typ auf »data« setzen.\n" " »Zeichenkettenmodus« - nur benutzt, um symbolische Verweisblöcke zu\n" " schreiben.\n" "\n" " Beispiele:\n" " Strukturmodus: »write core.uid 23« - setzt eine Inode-uid-Feld\n" " auf 23.\n" " »write fname \"hello\\000\"«\n" " - schreibt Superblock fname.\n" " (Anmerkung: Zeichenketten werden in »struct mode« " "nicht\n" " mit Null beendet)\n" " »write fname #6669736800«\n" " - schreibt Superblock fname\n" " hexadezimal.\n" " »write uuid 00112233-4455-6677-8899-aabbccddeeff«\n" " - schreibt Superblock-uuid.\n" " Datenmodus: »write fill 0xff« - füllt den ganzen Block mit\n" " 0xffs\n" " »write lshift 3« - verschiebt den Block drei\n" " Bytes nach links\n" " »write sequence 1 5« - schreibt einen Zyklus von\n" " Nummern [1-5] durch den\n" " ganzen Block\n" " Zeichenkettenmodus: »write \"This_is_a_filename\"«\n" " - schreibt mit Null beendete\n" " Zeichenkette\n" "\n" " Tippen Sie im Datenmodus »write« ein, um eine Liste spezieller Befehle zu\n" " erhalten.\n" "\n" #: .././db/write.c:137 msgid "Allowing write of corrupted data\n" msgstr "" #: .././db/dquot.c:37 msgid "[projid|gid|uid]" msgstr "[projid|gid|uid]" #: .././db/dquot.c:38 msgid "set current address to project, group or user quota block" msgstr "aktuelle Adresse auf Projekt, Gruppe oder Benutzer-Quota setzen" #: .././growfs/xfs_growfs.c:64 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" msgstr "" "Metadaten =%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u\n" "Daten =%-22s bsize=%-6u Blöcke=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "Benennung =Version %-14u bsize=%-6u ascii-ci=%d\n" "Protokoll =%-22s bsize=%-6u Blöcke=%u, Version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "Echtzeit =%-22s extsz=%-6u Blöcke=%llu, rtextents=%llu\n" #: .././io/init.c:35 #, fuzzy, c-format msgid "Usage: %s [-adfmnrRstVx] [-p prog] [-c cmd]... file\n" msgstr "Aufruf: %s [-adFfmrRstx] [-p Programm] [-c Befehl]... Datei\n" #: .././io/reflink.c:85 #, c-format msgid "Extents did not match.\n" msgstr "" #: .././io/attr.c:58 #, c-format msgid "" "\n" " displays the set of extended inode flags associated with the current file\n" "\n" " Each individual flag is displayed as a single character, in this order:\n" " r -- file data is stored in the realtime section\n" " p -- file has preallocated extents (cannot be changed using chattr)\n" " i -- immutable, file cannot be modified\n" " a -- append-only, file can only be appended to\n" " s -- all updates are synchronous\n" " A -- the access time is not updated for this inode\n" " d -- do not include this file in a dump of the filesystem\n" " t -- child created in this directory has realtime bit set by default\n" " P -- child created in this directory has parents project ID by default\n" " n -- symbolic links cannot be created in this directory\n" " e -- for non-realtime files, observe the inode extent size value\n" " E -- children created in this directory inherit the extent size value\n" " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, but only list attributes on directories\n" " -a -- show all flags which can be set alongside those which are set\n" " -v -- verbose mode; show long names of flags, not single characters\n" "\n" msgstr "" "\n" " zeigt den Satz von erweiterten Inode-Markierungen an, die zu der\n" " aktuellen Datei zugehörig sind.\n" "\n" " Jede einzelne Markierung wird als einzelner Buchstabe in dieser\n" " Reihenfolge angezeigt:\n" " r -- Dateiinhalt ist im Echtzeit-Bereich gespeichert\n" " p -- Datei hat vorher zugeteilten Umfang (kann nicht mit chattr\n" " geändert werden)\n" " i -- unveränderlich, Datei kann nicht verändert werden\n" " a -- nur anhängen, Datei kann nur daran angehängt werden\n" " s -- alle Aktualisierungen sind synchron\n" " A -- die Zugriffszeit für diesen Inode ist nicht aktualisiert\n" " d -- diese Datei nicht in die Ausgabe des Dateisystems einschließen\n" " t -- das in diesem Verzeichnis erzeugte Kind hat standardmäßig ein\n" " gesetztes Echtzeit-Bit.\n" " P -- das in diesem Verzeichnis erzeugte Kind hat standardmäßig die\n" " Projekt-ID der Eltern.\n" " n -- in diesem Verzeichnis können keine symbolischen Verweise erstellt\n" " werden\n" " e -- für Nicht-Echtzeit-Dateien wird die Größe des Inode-Umfangs beachtet\n" " E -- in diesem Verzeichnis erzeugt Kinder erben die Größe des Umfangs\n" " f -- diese Datei nicht bei der Defragmentierung des Dateisystems\n" " einschließen\n" "\n" " Optionen:\n" " -R -- rekursiv absteigend (nützlich, wenn die aktuelle Datei ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, aber nur die Attribute von Verzeichnissen\n" " auflisten\n" " -a -- alle Merkmale zeigen, die neben denen gesetzt werden können, die\n" " gesetzt sind.\n" " -v -- gesprächiger Modus; zeige lange Namen der Merkmale, keine einzelnen\n" " Zeichen\n" "\n" #: .././io/attr.c:89 #, c-format msgid "" "\n" " modifies the set of extended inode flags associated with the current file\n" "\n" " Examples:\n" " 'chattr +a' - sets the append-only flag\n" " 'chattr -a' - clears the append-only flag\n" "\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, only modifying attributes on directories\n" " +/-r -- set/clear the realtime flag\n" " +/-i -- set/clear the immutable flag\n" " +/-a -- set/clear the append-only flag\n" " +/-s -- set/clear the sync flag\n" " +/-A -- set/clear the no-atime flag\n" " +/-d -- set/clear the no-dump flag\n" " +/-t -- set/clear the realtime inheritance flag\n" " +/-P -- set/clear the project ID inheritance flag\n" " +/-n -- set/clear the no-symbolic-links flag\n" " +/-e -- set/clear the extent-size flag\n" " +/-E -- set/clear the extent-size inheritance flag\n" " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " Note1: user must have certain capabilities to modify immutable/append-" "only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" " Note3: the realtime flag can only be set if the filesystem has a realtime\n" " section, and the (regular) file must be empty when the flag is set.\n" "\n" msgstr "" "\n" " verändert den Satz von erweiterten Inode-Merkmalen, die zu der\n" " aktuellen Datei zugehörig sind.\n" "\n" " Beispiele:\n" " »chattr +a« - setzt das Nur-anhängen-Merkmal\n" " »chattr -a« - löscht das Nur-anhängen-Merkmal\n" "\n" " -R -- rekursiv absteigend (nützlich, wenn die aktuelle Datei ein\n" " Verzeichnis ist)\n" " -D -- rekursiv absteigend, aber nur die Attribute von Verzeichnissen\n" " auflisten\n" " +/-r -- setzen/löschen des Echtzeit-Merkmals\n" " +/-i -- setzen/löschen des Unveränderlich-Merkmals\n" " +/-a -- setzen/löschen des Nur-anhängen-Merkmals\n" " +/-s -- setzen/löschen des Sync-Merkmals\n" " +/-A -- setzen/löschen des No-atime-Merkmals\n" " +/-d -- setzen/löschen des No-dump-Merkmals\n" " +/-t -- setzen/löschen des Echtzeit-Vererbungs-Merkmals\n" " +/-P -- setzen/löschen des Projekt-ID-Vererbungs-Merkmals\n" " +/-n -- setzen/löschen des Kein-symbolischer-Verweis-Merkmals\n" " +/-e -- setzen/löschen des Erweiterte-Größe-Merkmals\n" " +/-E -- setzen/löschen des Erweiterte-Größe-Vererbungs-Merkmals\n" " +/-f -- setzen/löschen des Nicht-Defragmentierungs-Merkmals\n" " +/-S -- setzen/löschen des Datenstrom-Zuteiler-Merkmals\n" " Anmerkung1: Der Anwender muss gewisse Fähigkeiten haben, um das zu ändern,\n" " das unveränderlich oder zum Nur-Ändern ist.\n" " Anmerkung2: Unveränderliche-/Nur-Ändern-Dateien können nicht gelöscht\n" " werden; diese Dateien zu entfernen erfordert das vorherige\n" " Löschen des Unveränderlich-/Nur-Ändern-Merkmals.\n" " Anmerkung3: Das Echtzeit-Merkmal kann nur gesetzt werden, wenn das\n" " Dateisystem einen Echtzeit-Bereich hat, und die (reguläre)\n" " Datei muss leer sein, wenn das Merkmal gesetzt wird.\n" "\n" #: .././io/bmap.c:30 #, fuzzy, c-format msgid "" "\n" " prints the block mapping for an XFS file's data or attribute forks\n" " Example:\n" " 'bmap -vp' - tabular format verbose map, including unwritten extents\n" "\n" " bmap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are " "unwritten.)\n" " -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" " Note: the bmap for non-regular files can be obtained provided the file\n" " was opened appropriately (in particular, must be opened read-only).\n" "\n" msgstr "" "\n" " gibt die Block-Kartierung für die Daten- oder Attribus-Verzweigungen einer\n" " XFS-Datei aus\n" " Beispiel:\n" " »bmap -vp« - aussagekräftige Karte im Tabellenformat, einschließlich\n" " ungeschriebenem Umfang\n" "\n" " »bmap« schreibt die Karte der Plattenblöcke, die von der derzeitigen Datei\n" " belegt werden.\n" " Die Karte listet jeden Bereich, der von der Datei belegt wird, sowie \n" " Regionen in der Datei, die keine zugehörigen Blöcke (Löcher) haben auf.\n" " Standardmäßig nimmt jede Zeile der Liste die folgende Form an:\n" " Bereich: [Startversatz..Endversatz]: Startblock..Endblock\n" " Löcher sind durch den Ersatz von Startblock..Endblock durch »Loch«\n" " markiert.\n" " Alle Datei-Offsets und Plattenblöcke sind Einheiten aus 512-Byte-Blöcken.\n" " -a -- gibt die Attributs-Verzweigungs-Karte statt der\n" " Daten-Verzweigung aus.\n" " -d -- unterdrückt ein DMAPI-Lese-Ereignis, Offline-Teile werden als Löcher\n" " betrachtet.\n" " -l -- zeigt außerdem die Länge von jedem Bereich in 512-Byte Blöcken.\n" " Anmerkung: Das »bmap« für irreguläre Dateien kann bereitgestellt werden,\n" " statt der Datei die passend geöffnet wurde (im Einzelnen darf sie\n" " Nur-Lesend geöffnet werden)\n" "\n" #: .././io/open.c:762 #, fuzzy msgid "[-acdrstxT] [path]" msgstr "[-acdrstx] [Pfad]" #: .././io/prealloc.c:349 #, fuzzy msgid "[-c] [-k] [-p] off len" msgstr "[-b bs] [-v] off len" #: .././io/mmap.c:135 #, c-format msgid "" "\n" " maps a range within the current file into memory\n" "\n" " Example:\n" " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" "\n" " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" " With no arguments, mmap shows the current mappings. The current mapping\n" " can be set by using the single argument form (mapping number or address).\n" " If two arguments are specified (a range), a new mapping is created and the\n" " following options are available:\n" " -r -- map with PROT_READ protection\n" " -w -- map with PROT_WRITE protection\n" " -x -- map with PROT_EXEC protection\n" " If no protection mode is specified, all are used by default.\n" "\n" msgstr "" "\n" " bildet einen Bereich innerhalb der aktuellen Datei im Speicher ab.\n" "\n" " Beispiel:\n" " »mmap -rw 0 1m« - bildet ein Megabyte vom Anfang der aktuellen Datei ab\n" "\n" " Speicher eines Dateibereiches für eine nachfolgende Benutzung durch andere\n" " xfs-io-Befehle abbilden.\n" " Ohne Argumente zeigt mmap die derzeitige Kartierung. Die derzeitige\n" " Kartierung kann durch Benutzung einer einzelnen Argument-Form\n" " (Kartierungsnummer oder Adresse) gesetzt werden.\n" " Wenn zwei Argumente angegeben wurden (ein Bereich) wird eine neue\n" " Kartierung erstellt und die folgenden Optionen sind verfügbar:\n" " -r -- Karte mit PROT_READ-Schutz\n" " -w -- Karte mit PROT_WRITE-Schutz\n" " -x -- Karte mit PROT_EXEC-Schutz\n" " Wenn kein Schutz-Modus angegeben wurde, werden standardmäßig alle benutzt.\n" "\n" #: .././io/mmap.c:584 #, c-format msgid "" "\n" " resizes the current memory mapping\n" "\n" " Examples:\n" " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" "\n" " Resizes the mappping, growing or shrinking from the current size.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -f -- use the MREMAP_FIXED flag\n" " -m -- use the MREMAP_MAYMOVE flag\n" "\n" msgstr "" #: .././io/mmap.c:650 msgid "[N] | [-rwx] [off len]" msgstr "[N] | [-rwx] [off len]" #: .././io/mmap.c:702 #, fuzzy msgid "[-m|-f] newsize" msgstr "[-D | -R] [extsize]" #: .././libxfs/rdwr.c:1036 #, c-format msgid "%s: pwrite64 failed: %s\n" msgstr "%s: pwrite64 fehlgeschlagen: %s\n" #: .././libxfs/rdwr.c:1042 #, fuzzy, c-format msgid "%s: error - pwrite64 only %d of %d bytes\n" msgstr "%s: Fehler - nur %d von %d Bytes wurden geschrieben\n" #: .././logprint/log_print_all.c:258 #, c-format msgid "\t\tmagic:%c%c mode:0x%x ver:%d format:%d onlink:%d\n" msgstr "\t\tmagische:%c%c Modus:0x%x ver:%d Format:%d onlink:%d\n" #: .././logprint/log_print_all.c:262 #, fuzzy, c-format msgid "\t\tuid:%d gid:%d nlink:%d projid:%u\n" msgstr "\t\tuid:%d gid:%d nlink:%d projid:%d\n" #: .././logprint/log_print_all.c:388 #, c-format msgid "\tEFD: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "\tEFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_print_all.c:420 #, c-format msgid "\tEFI: #regs:%d num_extents:%d id:0x%llx\n" msgstr "\tEFI: #regs:%d num_extents:%d id:0x%llx\n" #: .././logprint/log_print_trans.c:27 #, c-format msgid "TRANS: tid:0x%x type:%s #items:%d trans:0x%x q:0x%lx\n" msgstr "TRANS: tid:0x%x Typ:%s #items:%d trans:0x%x q:0x%lx\n" #: .././logprint/log_misc.c:236 #, c-format msgid " type: %s tid: %x num_items: %d\n" msgstr " Typ: %s tid: %x num_items: %d\n" #: .././logprint/log_misc.c:493 #, c-format msgid "EFD: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_misc.c:548 #, c-format msgid "EFI: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_misc.c:890 #, c-format msgid "%s: lseek64 to %lld failed: %s\n" msgstr "%s: lseek64 auf %lld fehlgeschlagen: %s\n" #: .././mkfs/xfs_mkfs.c:230 #, c-format msgid "data su/sw must not be used in conjunction with data sunit/swidth\n" msgstr "" "su-/sw-Daten müssen in Verbindung mit sunit-/swidth-Daten benutzt werden\n" #: .././mkfs/xfs_mkfs.c:246 #, c-format msgid "data sunit/swidth must not be used in conjunction with data su/sw\n" msgstr "" "sunit-/swidth-Daten müssen in Verbindung mit su-/sw-Daten benutzt werden\n" #: .././mkfs/xfs_mkfs.c:281 #, c-format msgid "log su should not be used in conjunction with log sunit\n" msgstr "" "su-Protokoll kann nicht in Verbindung mit sunit-Protokoll benutzt werden\n" #: .././mkfs/xfs_mkfs.c:290 #, c-format msgid "log sunit should not be used in conjunction with log su\n" msgstr "" "sunit-Protokoll kann nicht in Verbindung mit su-Protokoll benutzt werden\n" #: .././mkfs/xfs_mkfs.c:820 #, c-format msgid "existing superblock read failed: %s\n" msgstr "Lesen des bestehenden Superblocks fehlgeschlagen: %s\n" #: .././mkfs/xfs_mkfs.c:826 #, fuzzy, c-format msgid "warning: could not read existing superblock, skip zeroing\n" msgstr "Superblock kann nicht gelesen werden\n" #: .././mkfs/xfs_mkfs.c:1137 #, c-format msgid "%s: Specify data sunit in 512-byte blocks, no unit suffix\n" msgstr "" "%s: Geben Sie sunit-Daten in 512-Byte-Blöcken an, kein Einheit-Suffix\n" #: .././mkfs/xfs_mkfs.c:1153 #, c-format msgid "%s: Specify data swidth in 512-byte blocks, no unit suffix\n" msgstr "" "%s: Geben Sie swidth-Daten in 512-Byte-Blöcken an, kein Einheit-Suffix\n" #: .././mkfs/xfs_mkfs.c:1180 #, c-format msgid "%s: Specify data sw as multiple of su, no unit suffix\n" msgstr "%s: Geben Sie sw-Daten als Vielfaches von su an, kein Einheit-Suffix\n" #: .././mkfs/xfs_mkfs.c:1417 #, c-format msgid "Specify log sunit in 512-byte blocks, no size suffix\n" msgstr "Geben Sie sunit-Daten in 512-Byte-Blöcken an, kein Größe-Suffix\n" #: .././mkfs/xfs_mkfs.c:1726 #, c-format msgid "cannot specify both %s and -d name=%s\n" msgstr "es kann nicht beides angegeben werden %s und -d Name=%s\n" #: .././mkfs/xfs_mkfs.c:1880 #, fuzzy, c-format msgid "warning: finobt not supported without CRC support, disabled.\n" msgstr "Warnung: Keine Quota-Inodes wurden gefunden. Quota ausgeschaltet\n" #: .././mkfs/xfs_mkfs.c:1887 #, fuzzy, c-format msgid "warning: sparse inodes not supported without CRC support, disabled.\n" msgstr "Warnung: Keine Quota-Inodes wurden gefunden. Quota ausgeschaltet\n" #: .././mkfs/xfs_mkfs.c:1908 #, c-format msgid "both -d agcount= and agsize= specified, use one or the other\n" msgstr "" "beide -d agcount= und agsize= angegeben, benutzen Sie das eine oder\n" "das andere\n" #: .././mkfs/xfs_mkfs.c:1914 #, c-format msgid "if -d file then -d name and -d size are required\n" msgstr "wenn -d Datei, dann sind -d Name und -d Größe erforderlich\n" #: .././mkfs/xfs_mkfs.c:1951 #, c-format msgid "if -l file then -l name and -l size are required\n" msgstr "wenn -l Datei, dann sind -l Name und -l Größe erforderlich\n" #: .././mkfs/xfs_mkfs.c:1973 #, c-format msgid "if -r file then -r name and -r size are required\n" msgstr "wenn -r Datei, dann sind -r Name und -r Größe erforderlich\n" #: .././mkfs/xfs_mkfs.c:2008 #, c-format msgid "rt extent size %s too large, maximum %d\n" msgstr "rt-Erweiterungs-Länge %s zu groß, Maximum %d\n" #: .././mkfs/xfs_mkfs.c:2014 #, c-format msgid "rt extent size %s too small, minimum %d\n" msgstr "rt-Erweiterungs-Länge %s zu klein, Minimum %d\n" #: .././mkfs/xfs_mkfs.c:2567 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" msgstr "" "Metadaten =%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u\n" "Daten =%-22s bsize=%-6u Blöcke=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "Benennung =Version %-14u bsize=%-6u ascii-ci=%d\n" "Protokoll =%-22s bsize=%-6d Blöcke=%lld, Version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "Echtzeit =%-22s extsz=%-6d Blöcke=%lld, rtextents=%lld\n" #: .././mkfs/xfs_mkfs.c:3181 #, c-format msgid "blocksize not available yet.\n" msgstr "Blockgröße noch nicht verfügbar.\n" #: .././mkfs/xfs_mkfs.c:3207 #, fuzzy, c-format msgid "" "Usage: %s\n" "/* blocksize */\t\t[-b log=n|size=num]\n" "/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx]\n" "/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num|noalign),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* force overwrite */\t[-f]\n" "/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n" "\t\t\t projid32bit=0|1,sparse=0|1]\n" "/* no discard */\t[-K]\n" "/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* label */\t\t[-L label (maximum 12 characters)]\n" "/* naming */\t\t[-n log=n|size=num,version=2|ci,ftype=0|1]\n" "/* no-op info only */\t[-N]\n" "/* prototype file */\t[-p fname]\n" "/* quiet */\t\t[-q]\n" "/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* sectorsize */\t[-s log=n|size=num]\n" "/* version */\t\t[-V]\n" "\t\t\tdevicename\n" " is required unless -d name=xxx is given.\n" " is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " is xxx (512 byte blocks).\n" msgstr "" "Aufruf: %s\n" "/* Blockgröße */\t\t[-b log=n|size=num]\n" "/* Unter-Datenträger */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* Inode-Größe */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2]\n" "/* Protokoll-Datenträger */\t[-l agnum=n,internal,size=num,\n" "\t\t\t logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* Aufschrift */\t\t[-L label (maximal 12 Zeichen)]\n" "/* Benennung */\t\t[-n log=n|size=num,version=2|ci]\n" "/* Prototyp-Datei */\t[-p fname]\n" "/* ohne Ausgabe */\t\t[-q]\n" "/* Echtzeit-Unter-Datenträger */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* Sektorengröße */\t[-s log=n|size=num]\n" "/* Version */\t\t[-V]\n" "\t\t\tdevicename\n" " wird benötigt, außer wenn -d name=xxx angegeben ist.\n" " is xxx (Bytes), xxxs (Sektoren), xxxb (fs Blöcke), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " ist xxx (512 Byte-Blöcke).\n" #: .././quota/edit.c:689 msgid "[-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" msgstr "[-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" #: .././quota/edit.c:697 .././quota/report.c:33 .././quota/report.c:647 msgid "[-gpu] [-f file]" msgstr "[-gpu] [-f Datei]" #: .././quota/edit.c:704 .././quota/edit.c:712 msgid "[-bir] [-gpu] value -d|id|name" msgstr "[-bir] [-gpu] Ert -d|id|name" #: .././quota/edit.c:705 msgid "get/set quota enforcement timeouts" msgstr "ausgeben/setzen von Zeitbeschränkungen zum Erzwingen von Quotas" #: .././quota/free.c:371 msgid "[-bir] [-hn] [-f file]" msgstr "[-bir] [-hn] [-f Datei]" #: .././quota/init.c:48 #, fuzzy, c-format msgid "Usage: %s [-V] [-x] [-p prog] [-c cmd]... [-d project]... [path]\n" msgstr "Aufruf: %s [-p Programm] [-c Befehl]... [-d Projekt]... [Pfad]\n" #: .././quota/path.c:39 #, c-format msgid "%sFilesystem Pathname\n" msgstr "%sDateisystem Pfadname\n" #: .././quota/quot.c:419 msgid "[-bir] [-gpu] [-acv] [-f file]" msgstr "[-bir] [-gpu] [-acv] [-f Datei]" #: .././quota/quota.c:464 msgid "[-bir] [-gpu] [-hnNv] [-f file] [id|name]..." msgstr "[-bir] [-gpu] [-hnNv] [-f Datei] [id|name]..." #: .././quota/report.c:48 msgid "[-bir] [-gpu] [-ahntLNU] [-f file]" msgstr "[-bir] [-gpu] [-ahntLNU] [-f Datei]" #: .././quota/report.c:51 #, c-format msgid "" "\n" " report used space and inodes, and quota limits, for a filesystem\n" " Example:\n" " 'report -igh'\n" " (reports inode usage for all groups, in an easy-to-read format)\n" " This command is the equivalent of the traditional repquota command, which\n" " prints a summary of the disk usage and quotas for the current filesystem,\n" " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -L -- lower ID bound to report on\n" " -U -- upper ID bound to report on\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" " -u -- report user usage and quota information\n" " -b -- report blocks-used information only\n" " -i -- report inodes-used information only\n" " -r -- report realtime-blocks-used information only\n" "\n" msgstr "" "\n" " benutzten Speicher und Inodes und Quota-Beschränkungen für ein\n" " Dateisystem ausgeben\n" " Beispiel:\n" " 'report -igh'\n" " (gibt Inode-Nutzung für alle Gruppen in einfach lesbarem Format aus)\n" " Dieser Befehl entspricht dem traditionellen repquota-Befehl, der eine\n" " Zusammenfassung der Plattenbelegung und Quotas für das derzeitige\n" " Dateisystem oder alle Dateisysteme ausgibt.\n" " -a -- alle eingehängten Dateisysteme mit eingeschaltetem Quota\n" " anzeigen\n" " -h -- Anzeige in einem für Menschen lesbaren Format\n" " -n -- Übersetzung von Bezeichnern zu Namen überspringen, nur IDs\n" " ausgeben\n" " -N -- die Kopfzeilen in der Ausgabe unterdrücken\n" " -t -- kurzes Ausgabeformat, Zeilen, die nur Null enthalten, unterdrücken\n" " -L -- zeigt untere an den Bericht gebundene ID\n" " -U -- zeigt obere an den Bericht gebundene ID\n" " -g -- zeigt Gruppen-Nutzung und Quota-Information\n" " -p -- zeigt Projekt-Nutzung und Quota-Information\n" " -u -- zeigt Benutzer--Nutzung und Quota-Information\n" " -b -- zeigt nur Information über benutzte Blöcke\n" " -i -- zeigt nur Information über benutzte Inodes\n" " -r -- zeigt nur Information über benutzte Echtzeit-Blöcke\n" "\n" #: .././repair/phase5.c:1463 #, c-format msgid "lost %d blocks in ag %u\n" msgstr "%d Blöcke in ag %u verloren\n" #: .././repair/phase5.c:1466 #, c-format msgid "thought we were going to lose %d blocks in ag %u, actually lost %d\n" msgstr "" "man dachte, %d Blöcke würden in ag %u verloren gehen, aktuell verloren %d\n" #: .././repair/phase5.c:1685 #, c-format msgid "lost %d blocks in agno %d, sorry.\n" msgstr "%d Blöcke in agno %d verloren, Entschuldigung.\n" #: .././repair/versions.c:228 #, c-format msgid "" "WARNING: you have a V1 inode filesystem. It %s be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:84 #, c-format msgid "%s: stat64 of %s failed\n" msgstr "%s: stat64 von %s fehlgeschlagen\n" #: .././rtcp/xfs_rtcp.c:138 #, c-format msgid "%s: failed stat64 on %s: %s\n" msgstr "%s: stat64 auf %s fehlgeschlagen: %s\n" #~ msgid "%s: couldn't register atexit function.\n" #~ msgstr "%s: atexit-Funktion konnte nicht registriert werden.\n" #~ msgid "sb versionnum missing nlink bit %x\n" #~ msgstr "sb-Versionsnummer fehlt nlink-Bit %x\n" #~ msgid "bad directory leaf magic # %#x for dir ino %lld\n" #~ msgstr "falsche magische Verzeichnis-Blatt # %#x für dir ino %lld\n" #~ msgid "dir %lld entry %*.*s %lld\n" #~ msgstr "dir %lld Eintrag %*.*s %lld\n" #~ msgid "can't read root block for directory inode %lld\n" #~ msgstr "Block für Verzeichnis-Inode %lld kann nicht gelesen werden\n" #~ msgid "dir %llu size is %lld, should be %d\n" #~ msgstr "dir %llu Größe ist %lld, sollte %d sein\n" #~ msgid "can't seek in filesystem at bb %lld\n" #~ msgstr "im Dateisystem kann nicht bei bb %lld gesucht werden\n" #~ msgid "incomplete write, block: %lld\n" #~ msgstr "unvollständig geschrieben, Block: %lld\n" #~ msgid "incomplete read, block: %lld\n" #~ msgstr "unvollständig gelesen, Block: %lld\n" #~ msgid "%s: cannot read %s\n" #~ msgstr "%s: %s kann nicht gelesen werden\n" #~ msgid "could not open mtab file: %s\n" #~ msgstr "mtab-Datei könnte nicht geöffnet werden: %s\n" #~ msgid "chattr" #~ msgstr "chattr" #~ msgid "lsattr" #~ msgstr "lsattr" #~ msgid "fadvise" #~ msgstr "fadvise" #~ msgid "f" #~ msgstr "f" #~ msgid "print" #~ msgstr "ausgeben" #~ msgid "p" #~ msgstr "p" #~ msgid "fsync" #~ msgstr "fsync" #~ msgid "fdatasync" #~ msgstr "fdatasync" #~ msgid "ds" #~ msgstr "ds" #~ msgid "getrusage" #~ msgstr "getrusage" #~ msgid "g" #~ msgstr "g" #~ msgid "imap" #~ msgstr "imap" #~ msgid "inject" #~ msgstr "einspeisen" #~ msgid "madvise" #~ msgstr "madvise" #~ msgid "ma" #~ msgstr "ma" #~ msgid "mincore" #~ msgstr "mincore" #~ msgid "mi" #~ msgstr "mi" #~ msgid "pread" #~ msgstr "pread" #~ msgid "r" #~ msgstr "r" #~ msgid "resblks" #~ msgstr "resblks" #~ msgid "sendfile" #~ msgstr "sendfile" #~ msgid "send" #~ msgstr "senden" #~ msgid "shutdown" #~ msgstr "herunterfahren" #~ msgid "truncate" #~ msgstr "kürzen" #~ msgid "t" #~ msgstr "t" #~ msgid "freeze" #~ msgstr "sperren" #~ msgid "thaw" #~ msgstr "auftauen" #~ msgid "allocsp" #~ msgstr "allocsp" #~ msgid "freesp" #~ msgstr "freesp" #~ msgid "resvsp" #~ msgstr "resvsp" #~ msgid "unresvsp" #~ msgstr "unresvsp" #~ msgid "wrote %lld/%lld bytes at offset %lld\n" #~ msgstr "schrieb %lld/%lld Bytes ab Versatz %lld\n" #~ msgid "w" #~ msgstr "w" #~ msgid "bmap" #~ msgstr "bmap" #~ msgid "mmap" #~ msgstr "mmap" #~ msgid "mm" #~ msgstr "mm" #~ msgid "mread" #~ msgstr "mread" #~ msgid "mr" #~ msgstr "mr" #~ msgid "msync" #~ msgstr "msync" #~ msgid "ms" #~ msgstr "ms" #~ msgid "munmap" #~ msgstr "munmap" #~ msgid "mu" #~ msgstr "mu" #~ msgid "mwrite" #~ msgstr "mwrite" #~ msgid "mw" #~ msgstr "mw" #~ msgid "invalid setfl argument -- '%c'\n" #~ msgstr "ungültiges »setfl«-Argument -- »%c«\n" #~ msgid "open" #~ msgstr "öffnen" #~ msgid "o" #~ msgstr "o" #~ msgid "stat" #~ msgstr "stat" #~ msgid "close" #~ msgstr "schließen" #~ msgid "c" #~ msgstr "c" #~ msgid "setfl" #~ msgstr "setfl" #~ msgid "[-adx]" #~ msgstr "[-adx]" #~ msgid "set/clear append/direct flags on the open file" #~ msgstr "setzen-/löschen- anhängen-/direkt-Markierungen auf die offene Datei" #~ msgid "statfs" #~ msgstr "statfs" #~ msgid "chproj" #~ msgstr "chproj" #~ msgid "lsproj" #~ msgstr "lsproj" #~ msgid "extsize" #~ msgstr "extsize" #~ msgid "parent" #~ msgstr "Eltern" #~ msgid "help" #~ msgstr "Hilfe" #~ msgid "?" #~ msgstr "?" #~ msgid "quit" #~ msgstr "beenden" #~ msgid "q" #~ msgstr "q" #~ msgid "%s: warning - out of memory\n" #~ msgstr "%s: Warnung - außerhalb des Speichers\n" #~ msgid "%s: warning - cannot find %s: %s\n" #~ msgstr "%s: Warnung - %s kann nicht gefunden werden: %s\n" #~ msgid "%s: no mount table yet, so no projects\n" #~ msgstr "%s: noch keine Einhänge-Tabelle, deshalb keine Projekte\n" #~ msgid "%s: cannot reserve space: %s\n" #~ msgstr "%s: Speicher konnte nicht reserviert werden: %s\n" #~ msgid "%s: cannot read realtime bitmap inode (%d)\n" #~ msgstr "%s: Echtzeit-Bitmap-Inode (%d) kann nicht gelesen werden\n" #~ msgid "%s: cannot read realtime summary inode (%d)\n" #~ msgstr "" #~ "%s: Echtzeit-Zusammenfassungs-Inode (%d) kann nicht gelesen werden\n" #~ msgid "" #~ "%s: WARNING - filesystem uses v1 dirs,limited functionality provided.\n" #~ msgstr "" #~ "%s: WARNUNG - Dateisystem benutzt v1 dirs, begrenzte Funktionalität\n" #~ "bereitgestellt.\n" #~ msgid "%s: failed to alloc %ld bytes: %s\n" #~ msgstr "%s: Zuweisen von %ld Bytes fehlgeschlagen: %s\n" #~ msgid "%s: cannot read root inode (%d)\n" #~ msgstr "%s: Wurzel-Inode (%d) kann nicht gelesen werden\n" #~ msgid "EXTENTS inode attr\n" #~ msgstr "EXTENTS Inode attr\n" #~ msgid "BTREE inode attr\n" #~ msgstr "BTREE Inode attr\n" #~ msgid "LOCAL inode attr\n" #~ msgstr "LOCAL Inode attr\n" #~ msgid "xlog_print_trans_inode: illegal inode type" #~ msgstr "xlog_print_trans_inode: Illegaler Inode-Typ" #~ msgid "\t\ticount:%Ld ifree:%Ld " #~ msgstr "\t\ticount:%Ld ifree:%Ld " #~ msgid "fdblks:%Ld frext:%Ld\n" #~ msgstr "fdblks:%Ld frext:%Ld\n" #~ msgid "" #~ "Allocation group size (%lld) is not a multiple of the stripe unit (%d)\n" #~ msgstr "" #~ "Zuordnungsgruppengröße (%lld) ist kein Vielfaches der Stripe-Einheit " #~ "(%d)\n" #~ msgid "path" #~ msgstr "Pfad" #~ msgid "paths" #~ msgstr "Pfade" #~ msgid "limit" #~ msgstr "Beschränkung" #~ msgid "restore" #~ msgstr "wieder herstellen" #~ msgid "timer" #~ msgstr "Zeitnehmer" #~ msgid "warn" #~ msgstr "warnen" #~ msgid "df" #~ msgstr "df" #~ msgid "tree" #~ msgstr "Baum" #~ msgid "quot" #~ msgstr "quot" #~ msgid "quota" #~ msgstr "Quota" #~ msgid "l" #~ msgstr "l" #~ msgid "dump" #~ msgstr "Ausgabe" #~ msgid "report" #~ msgstr "Bericht" #~ msgid "repquota" #~ msgstr "repquota" #~ msgid "state" #~ msgstr "Status" #~ msgid "enable" #~ msgstr "einschalten" #~ msgid "disable" #~ msgstr "ausschalten" #~ msgid "remove" #~ msgstr "entfernen" #~ msgid "could not allocate expanded nlink array\n" #~ msgstr "erweiterte nlink-Matrix kann nicht alloziert werden.\n" #~ msgid "calloc failed in verify_set_primary_sb\n" #~ msgstr "calloc fehlgeschlagen in verify_set_primary_sb\n" #~ msgid "This filesystem is marked shared.\n" #~ msgstr "Dieses Dateisystem ist als gemeinsam nutzbar markiert.\n" #~ msgid "" #~ "WARNING: you have disallowed version 2 inodes but this filesystem\n" #~ "\thas version 2 inodes. The filesystem will be downgraded and\n" #~ "\tall version 2 inodes will be converted to version 1 inodes.\n" #~ "\tThis may cause some hard links to files to be destroyed\n" #~ msgstr "" #~ "WARNUNG: Sie haben Version-2-Inodes verboten, aber dieses Dateisystem " #~ "hat\n" #~ "\tVersion-2-Inodes. Das Dateisystem wird herabgestuft und alle\n" #~ "\tVersion-2-Inodes werden in Version-1-Inodes umgewandelt. Dies kann zur\n" #~ "\tFolge haben, dass einige Hardlinks auf Dateien zerstört werden.\n" #~ msgid "" #~ "WARNING: you have disallowed version 2 inodes but this filesystem\n" #~ "\thas version 2 inodes. The filesystem would be downgraded and\n" #~ "\tall version 2 inodes would be converted to version 1 inodes.\n" #~ "\tThis might cause some hard links to files to be destroyed\n" #~ msgstr "" #~ "WARNUNG: Sie haben Version-2-Inodes verboten, aber dieses Dateisystem " #~ "hat\n" #~ "\tVersion-2-Inodes. Das Dateisystem könnte herabgestuft und alle\n" #~ "\tVersion-2-Inodes in Version-1-Inodes umgewandelt erden. Dies könnte " #~ "zur\n" #~ "\tFolge haben, dass einige Hardlinks auf Dateien zerstört werden.\n" #~ msgid "realloc failed in blkent_append (%u bytes)\n" #~ msgstr "»realloc« in »blkent_append« fehlgeschlagen (%u Bytes)\n" #~ msgid "malloc failed in blkent_new (%u bytes)\n" #~ msgstr "»malloc« in »blkent_append« fehlgeschlagen (%u Bytes)\n" #~ msgid "malloc failed in blkent_prepend (%u bytes)\n" #~ msgstr "»malloc« in »blkent_prepend« fehlgeschlagen (%u Bytes)\n" #~ msgid "" #~ "nlinks %d will overflow v1 ino, ino %llu will be converted to version 2\n" #~ msgstr "" #~ "nlinks %d wird überlaufen v1 ino, ino %llu wird zu Version 2 umgewandelt\n" #~ msgid "bad magic # %#x in btcnt block %d/%d\n" #~ msgstr "falsche magische # %#x in btcnt-Block %d/%d\n" #~ msgid "expected level %d got %d in btcnt block %d/%d\n" #~ msgstr "erwartete Stufe %d hat %d in btcnt-Block %d/%d\n" #~ msgid "" #~ "bcnt freespace btree block claimed (state %d), agno %d, bno %d, suspect " #~ "%d\n" #~ msgstr "" #~ "bcnt freespace btree Block beansprucht (Status %d), agno %d, bno %d,\n" #~ "Suspekt %d\n" #~ msgid "block (%d,%d) already used, state %d\n" #~ msgstr "Block (%d,%d) bereits benutzt, Status %d\n" #~ msgid "can't read agf block for ag %d\n" #~ msgstr "agf-Block für ag %d kann nicht gelesen werden\n" #~ msgid "can't read agi block for ag %d\n" #~ msgstr "agi-Block für ag %d kann nicht gelesen werden\n" #~ msgid "invalid inode number %llu in directory %llu\n" #~ msgstr "ungültige Inode-Nummer %llu in Verzeichnis %llu\n" #~ msgid "entry in shortform dir %llu references rt bitmap inode %llu\n" #~ msgstr "Eintrag in Kurzform dir %llu bezieht sich auf Bitmap-Inode %llu\n" #~ msgid "entry in shortform dir %llu references rt summary inode %llu\n" #~ msgstr "" #~ "Eintrag in Kurzform dir %llu bezieht sich auf Zusammenfassungs-Inode " #~ "%llu\n" #~ msgid "entry in shortform dir %llu references user quota inode %llu\n" #~ msgstr "" #~ "Eintrag in Kurzform dir %llu bezieht sich auf\n" #~ "Benutzer-Quota-Inode %llu\n" #~ msgid "entry in shortform dir %llu references group quota inode %llu\n" #~ msgstr "" #~ "Eintrag in Kurzform dir %llu bezieht sich auf\n" #~ "Gruppen-Quota-Inode %llu\n" #~ msgid "entry references free inode %llu in shortform directory %llu\n" #~ msgstr "" #~ "Eintrag bezieht sich auf freien Inode %llu in Kurzform-Verzeichnis %llu\n" #~ msgid "entry references non-existent inode %llu in shortform dir %llu\n" #~ msgstr "" #~ "Eintrag bezieht sich auf nicht existierenden Inode %llu in\n" #~ "Kurzform-dir %llu\n" #~ msgid "zero length entry in shortform dir %llu, resetting to %d\n" #~ msgstr "" #~ "Eintrag mit Länge Null in Kurzform-dir %llu, wird auf %d zurückgesetzt\n" #~ msgid "zero length entry in shortform dir %llu, would set to %d\n" #~ msgstr "" #~ "Eintrag mit Länge Null in Kurzform-dir %llu, könnte auf %d zurückgesetzt\n" #~ "werden\n" #~ msgid "zero length entry in shortform dir %llu, " #~ msgstr "Eintrag mit Länge Null in Kurzform-dir %llu, " #~ msgid "junking %d entries\n" #~ msgstr "%d Einträge werden verworfen\n" #~ msgid "would junk %d entries\n" #~ msgstr "%d Einträge könnten verworfen werden\n" #~ msgid "size of last entry overflows space left in in shortform dir %llu, " #~ msgstr "" #~ "Größe des letzten Eintrag-Überlauf-Raums bleibt in Kurzform-dir %llu, " #~ msgid "resetting to %d\n" #~ msgstr "es wird auf %d zurückgesetzt\n" #~ msgid "would reset to %d\n" #~ msgstr "es könnte auf %d zurückgesetzt werden\n" #~ msgid "size of entry #%d overflows space left in in shortform dir %llu\n" #~ msgstr "" #~ "Größe des letzten Eintrag-#%d-Überlauf-Raums bleibt in Kurzform-dir %llu\n" #~ msgid "junking entry #%d\n" #~ msgstr "Eintrag #%d wird verworfen\n" #~ msgid "would junk entry #%d\n" #~ msgstr "Eintrag #%d könnte verworfen werden\n" #~ msgid "bad .. entry in dir ino %llu, points to self, " #~ msgstr "falscher ..-Eintrag in dir ino %llu, zeigt auf sich selbst, " #~ msgid "hole (start %d, len %d) out of range, block %d, dir ino %llu\n" #~ msgstr "" #~ "Loch (Start %d, len %d) außerhalb des Bereiches, Block %d, dir ino %llu\n" #~ msgid "hole claims used byte %d, block %d, dir ino %llu\n" #~ msgstr "Loch beansprucht benutztes Byte %d, Block %d, dir ino %llu\n" #~ msgid "- derived hole value %d, saw %d, block %d, dir ino %llu\n" #~ msgstr "- abgeleiteter Lochwert %d, gesehen %d, Block %d, dir ino %llu\n" #~ msgid "" #~ "- derived hole (base %d, size %d) in block %d, dir inode %llu not found\n" #~ msgstr "" #~ "- abgeleitetes Loch (Basis %d, Größe %d) in Block %d, dir Inode %llu\n" #~ "nicht gefunden\n" #~ msgid "can't read block %u (fsbno %llu) for attrbute fork of inode %llu\n" #~ msgstr "" #~ "Block %u(fsbno %llu) kann nicht gelesen werden für Attributs-" #~ "Unterelement\n" #~ "des Inodes %llu\n" #~ msgid "" #~ "bad dir/attr magic number in inode %llu, file bno = %u, fsbno = %llu\n" #~ msgstr "" #~ "falsche dir/attr magische Nummer in Inode %llu, Datei bno = %u,\n" #~ "fsbno = %llu\n" #~ msgid "bmap of block #%u of inode %llu failed\n" #~ msgstr "bmap des Blocks #%u des Inodes %llu fehlgeschlagen\n" #~ msgid "directory/attribute block used/count inconsistency - %d/%hu\n" #~ msgstr "" #~ "Verzeichnis-/Attributsblock benutzt/Unstimmigkeit gezählt - %d/%hu\n" #~ msgid "bad directory block in dir ino %llu\n" #~ msgstr "falscher Verzeichnis-Block in dir ino %llu\n" #~ msgid "" #~ "correcting bad hashval in non-leaf dir/attr block\n" #~ "\tin (level %d) in inode %llu.\n" #~ msgstr "" #~ "falscher hashval in non-leaf dir/attr-Block wird korrigiert\n" #~ "\tin (Stufe %d) in Inode %llu.\n" #~ msgid "" #~ "would correct bad hashval in non-leaf dir/attr block\n" #~ "\tin (level %d) in inode %llu.\n" #~ msgstr "" #~ "würde hashval in non-leaf dir/attr-Block korrigieren\n" #~ "\tin (Stufe %d) in Inode %llu.\n" #~ msgid "can't read block %u (%llu) for directory inode %llu\n" #~ msgstr "" #~ "Block %u (%llu) für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #~ msgid "bad magic number %x in block %u (%llu) for directory inode %llu\n" #~ msgstr "" #~ "falsche magische Nummer %x in Block %u (%llu) füu Verzeichnis-Inode %llu\n" #~ msgid "bad back pointer in block %u (%llu) for directory inode %llu\n" #~ msgstr "" #~ "falscher Rückwarts-Zeiger in Block %u (%llu) für Verzeichnis-Inode %llu\n" #~ msgid "" #~ "entry count %d too large in block %u (%llu) for directory inode %llu\n" #~ msgstr "" #~ "Eintragsanzahl %d zu groß in Block %u (%llu) für Verzeichnis-Inode %llu\n" #~ msgid "bad level %d in block %u (%llu) for directory inode %llu\n" #~ msgstr "falsche Stufe %d in Block %u (%llu) für Verzeichnis-Inode %llu\n" #~ msgid "" #~ "correcting bad hashval in interior dir/attr block\n" #~ "\tin (level %d) in inode %llu.\n" #~ msgstr "" #~ "falscher hashval in innerem dir/attr-Block wird berichtigt\n" #~ "\tin (Stufe %d) in Inode %llu.\n" #~ msgid "" #~ "would correct bad hashval in interior dir/attr block\n" #~ "\tin (level %d) in inode %llu.\n" #~ msgstr "" #~ "falscher hashval in innerem dir/attr-Block könnte berichtigt werden\n" #~ "\tin (Stufe %d) in Inode %llu.\n" #~ msgid "" #~ "directory block header conflicts with used space in directory inode %llu\n" #~ msgstr "" #~ "Kopf des Verzeichnisblocks hat einen Konflikt mit dem benutzten Raum im\n" #~ "Verzeichnis-Inode %llu\n" #~ msgid "" #~ "nameidx %d for entry #%d, bno %d, ino %llu > fs blocksize, deleting " #~ "entry\n" #~ msgstr "" #~ "nameidx %d für Eintrag #%d, bno %d, ino %llu > fs Blockgröße, Eintrag\n" #~ "wird gelöscht\n" #~ msgid "" #~ "nameidx %d, entry #%d, bno %d, ino %llu > fs blocksize, marking entry " #~ "bad\n" #~ msgstr "" #~ "nameidx %d, Eintrag #%d, bno %d, ino %llu > fs Blockgröße, falscher\n" #~ "Eintrag wird gekennzeichnet\n" #~ msgid "" #~ "nameidx %d, entry #%d, bno %d, ino %llu > fs blocksize, would delete " #~ "entry\n" #~ msgstr "" #~ "nameidx %d für Eintrag #%d, bno %d, ino %llu > fs Blockgröße, Eintrag\n" #~ "könnte gelöscht werden.\n" #~ msgid "invalid ino number %llu in dir ino %llu, entry #%d, bno %d\n" #~ msgstr "ungültige ino-Nummer %llu in dir ino %llu, Eintrag #%d, bno %d\n" #~ msgid "\tclearing ino number in entry %d...\n" #~ msgstr "\tino-Nummer in Eintrag %d wird bereinigt...\n" #~ msgid "\twould clear ino number in entry %d...\n" #~ msgstr "\tino-Nummer in Eintrag %d könnte bereinigt werden...\n" #~ msgid "" #~ "entry #%d, bno %d in directory %llu references realtime bitmap inode " #~ "%llu\n" #~ msgstr "" #~ "Eintrag #%d, bno %d in Verzeichnis %llu bezieht sich auf\n" #~ "Echtzeit-Bitmap-Inode %llu\n" #~ msgid "" #~ "entry #%d, bno %d in directory %llu references realtime summary inode " #~ "%llu\n" #~ msgstr "" #~ "Eintrag #%d, bno %d in Verzeichnis %llu bezieht sich auf\n" #~ "Echtzeit-Zusammenfassungs-Inode %llu\n" #~ msgid "" #~ "entry #%d, bno %d in directory %llu references user quota inode %llu\n" #~ msgstr "" #~ "Eintrag #%d, bno %d in Verzeichnis %llu bezieht sich auf\n" #~ "Benutzer-Quota-Inode %llu\n" #~ msgid "" #~ "entry #%d, bno %d in directory %llu references group quota inode %llu\n" #~ msgstr "" #~ "Eintrag #%d, bno %d in Verzeichnis %llu bezieht sich auf\n" #~ "Gruppen-Quota-Inode %llu\n" #~ msgid "" #~ "entry references free inode %llu in directory %llu, will clear entry\n" #~ msgstr "" #~ "Eintrag bezieht sich auf freien Inode %llu im Verzeichnis %llu, Eintrag\n" #~ "soll bereinigt werden\n" #~ msgid "" #~ "entry references free inode %llu in directory %llu, would clear entry\n" #~ msgstr "" #~ "Eintrag bezieht sich auf freien Inode %llu im Verzeichnis %llu, Eintrag\n" #~ "könnte bereinigt werden\n" #~ msgid "bad ino number %llu in dir ino %llu, entry #%d, bno %d\n" #~ msgstr "falsche ino-Nummer %llu in dir ino %llu, Eintrag #%d, bno %d\n" #~ msgid "clearing inode number...\n" #~ msgstr "Inode-Nummer wird bereinigt...\n" #~ msgid "would clear inode number...\n" #~ msgstr "Inode-Nummer könnte bereinigt werden...\n" #~ msgid "entry #%d, dir inode %llu, has zero-len name, deleting entry\n" #~ msgstr "" #~ "Eintrag #%d, dir Inode %llu, hat zero-len Name, Eintrag wird gelöscht\n" #~ msgid "entry #%d, dir inode %llu, has zero-len name, marking entry bad\n" #~ msgstr "" #~ "Eintrag #%d, dir Inode %llu, hat zero-len Name, Eintrag wird\n" #~ "gekennzeichnet\n" #~ msgid "" #~ "bad size, entry #%d in dir inode %llu, block %u -- entry overflows block\n" #~ msgstr "" #~ "falsche Größe, Eintrag #%d in dir Inode %llu, Block %u -- Eintrag\n" #~ "überflutet Block\n" #~ msgid "" #~ "dir entry slot %d in block %u conflicts with used space in dir inode " #~ "%llu\n" #~ msgstr "" #~ "dir-Eintrag-Slot %d in Block %u hat einen Konflikt mit dem benutzten\n" #~ "Raum im Verzeichnis-Inode %llu\n" #~ msgid "illegal name \"%s\" in directory inode %llu, entry will be cleared\n" #~ msgstr "" #~ "unerlaubter Name »%s« im Verzeichnis-Inode %llu, Eintrag soll bereinigt\n" #~ "werden\n" #~ msgid "" #~ "illegal name \"%s\" in directory inode %llu, entry would be cleared\n" #~ msgstr "" #~ "unerlaubter Name »%s« im Verzeichnis-Inode %llu, Eintrag könnte " #~ "bereinigt\n" #~ "werden\n" #~ msgid "\tmismatched hash value for entry \"%s\"\n" #~ msgstr "\tnicht übereinstimmender Hash-Wert für Eintrag »%s«\n" #~ msgid "\t\tin directory inode %llu. resetting hash value.\n" #~ msgstr "\t\tin Verzeichnis-Inode %llu. Hash-Wert wird zurückgesetzt.\n" #~ msgid "\t\tin directory inode %llu. would reset hash value.\n" #~ msgstr "" #~ "\t\tin Verzeichnis-Inode %llu. Hash-Wert könnte zurückgesetzt werden.\n" #~ msgid "\tbad hash ordering for entry \"%s\"\n" #~ msgstr "\t falsche Hash-Anforderung für Eintrag »%s«\n" #~ msgid "\t\tin directory inode %llu. will clear entry\n" #~ msgstr "\t\tin Verzeichnis-Inode %llu. Eintrag soll bereinigt werden\n" #~ msgid "\t\tin directory inode %llu. would clear entry\n" #~ msgstr "\t\tin Verzeichnis-Inode %llu. Eintrag könnte bereinigt werden\n" #~ msgid "" #~ "name \"%s\" (block %u, slot %d) conflicts with used space in dir inode " #~ "%llu\n" #~ msgstr "" #~ "Name »%s« (Block %u, Slot %d) hat einen Konflikt mit benutztem Raum in\n" #~ "dir-Inode %llu\n" #~ msgid "will clear entry \"%s\" (#%d) in directory inode %llu\n" #~ msgstr "Eintrag »%s« (#%d) soll gelöscht werden in Verzeichnis-Inode %llu\n" #~ msgid "would clear entry \"%s\" (#%d)in directory inode %llu\n" #~ msgstr "" #~ "Eintrag »%s« (#%d) könnte gelöscht werden in Verzeichnis-Inode %llu\n" #~ msgid "bad .. entry in dir ino %llu, points to self" #~ msgstr "falscher ..-Eintrag in dir ino %llu, zeigt auf sich selbst" #~ msgid "will clear entry\n" #~ msgstr "Eintrag soll gelöscht werden\n" #~ msgid "correcting .. entry in root inode %llu, was %llu\n" #~ msgstr "wird berichtigt .. Eintrag in Wurzel-Inode %llu, war %llu\n" #~ msgid "bad .. entry (%llu) in root inode %llu should be %llu\n" #~ msgstr "falscher .. Eintrag (%llu) in Wurzel-Inode %llu könnte %llu sein\n" #~ msgid "" #~ "multiple .. entries in directory inode %llu, will clear second entry\n" #~ msgstr "" #~ "mehrfache .. Einträge in Verzeichnis-Inode %llu, zweiter Eintrag wird\n" #~ "bereinigt werden\n" #~ msgid "" #~ "multiple .. entries in directory inode %llu, would clear second entry\n" #~ msgstr "" #~ "mehrfache .. Einträge in Verzeichnis-Inode %llu, zweiter Eintrag könnte\n" #~ "bereinigt werden\n" #~ msgid ". in directory inode %llu has wrong value (%llu), fixing entry...\n" #~ msgstr "" #~ ". in Verzeichnis-Inode %llu hat falschen Wert (%llu), stelle Eintrag\n" #~ "wieder her ..\n" #~ msgid ". in directory inode %llu has wrong value (%llu)\n" #~ msgstr ". in Verzeichnis-Inode %llu hat falschen Wert (%llu)\n" #~ msgid "multiple . entries in directory inode %llu\n" #~ msgstr "mehrfache .. Einträge in Verzeichnis-Inode %llu\n" #~ msgid "will clear one . entry in directory inode %llu\n" #~ msgstr "ein . Eintrag in Verzeichnis-Inode %llu wird bereinigt\n" #~ msgid "would clear one . entry in directory inode %llu\n" #~ msgstr "ein . Eintrag in Verzeichnis-Inode %llu könnte bereinigt werden\n" #~ msgid "entry \"%s\" in directory inode %llu points to self, " #~ msgstr "Eintrag »%s« in Verzeichnis-Inode %llu zeigt auf sich selbst, " #~ msgid "" #~ "- resetting first used heap value from %d to %d in block %u of dir ino " #~ "%llu\n" #~ msgstr "" #~ "- zuerst benutzter heap-Wert wird von %d auf %d in Block %u von \n" #~ "dir ino %llu zurückgesetzt\n" #~ msgid "" #~ "- would reset first used value from %d to %d in block %u of dir ino %llu\n" #~ msgstr "" #~ "- zuerst benutzter heap-Wert könnte von %d auf %d in Block %u von \n" #~ "dir ino %llu zurückgesetzt werden\n" #~ msgid "" #~ "- resetting namebytes cnt from %d to %d in block %u of dir inode %llu\n" #~ msgstr "" #~ "- Namensbytes cnt werden von %d auf %d in Block %u von dir ino %llu\n" #~ "zurückgesetzt\n" #~ msgid "" #~ "- would reset namebytes cnt from %d to %d in block %u of dir inode %llu\n" #~ msgstr "" #~ "- Namensbytes cnt könnten von %d auf %d in Block %u von dir ino %llu\n" #~ "zurückgesetzt werden\n" #~ msgid "- found unexpected lost holes in block %u, dir inode %llu\n" #~ msgstr "" #~ "- unerwartet verlorene Löcher in Block %u, dir-Inode %llu gefunden\n" #~ msgid "- hole info non-optimal in block %u, dir inode %llu\n" #~ msgstr "- Loch-Info nicht optimal in Block %u, dir-Inode %llu\n" #~ msgid "- hole info incorrect in block %u, dir inode %llu\n" #~ msgstr "- Loch-Info falsch in Block %u, dir-Inode %llu\n" #~ msgid "- existing hole info for block %d, dir inode %llu (base, size) - \n" #~ msgstr "" #~ "- existierende Loch-Info für Block %d, dir-Inode %llu (Basis, Größe) - \n" #~ msgid "- holes flag = %d\n" #~ msgstr "- Loch-Kennzeichner = %d\n" #~ msgid "- compacting block %u in dir inode %llu\n" #~ msgstr "- Block %u in dir-Inode %llu wird verdichtet\n" #~ msgid "not enough space in block %u of dir inode %llu for all entries\n" #~ msgstr "" #~ "nicht genug Platz in Block %u von dir-Inode %llu für alle Einträge\n" #~ msgid "- would compact block %u in dir inode %llu\n" #~ msgstr "- Block %u in dir-Inode %llu könnte verdichtet werden\n" #~ msgid "" #~ "can't read file block %u (fsbno %llu, daddr %lld) for directory inode " #~ "%llu\n" #~ msgstr "" #~ "Block %u (fsbno %llu, daddr %lld) für Verzeichnis-Inode %llu kann nicht\n" #~ "gelesen werden\n" #~ msgid "bad directory leaf magic # %#x for dir ino %llu\n" #~ msgstr "falsches Verzeichnis-Blatt magische # %#x für dir ino %llu\n" #~ msgid "" #~ "bad sibling back pointer for directory block %u in directory inode %llu\n" #~ msgstr "" #~ "falscher Geschwister-Rückwärts-Zeiger für Verzeichnis-Block %u in\n" #~ "Verzeichnis-Inode %llu\n" #~ msgid "out of range internal directory block numbers (inode %llu)\n" #~ msgstr "" #~ "interne Verzeichnis-Blocknummern (Inode %llu) außerhalb des Bereichs\n" #~ msgid "setting directory inode (%llu) size to %llu bytes, was %lld bytes\n" #~ msgstr "" #~ "Größe des Verzeichnis-Inodes (%llu) wird auf %llu Bytes gesetzt,\n" #~ "war %lld Bytes\n" #~ msgid "block 0 for directory inode %llu is missing\n" #~ msgstr "Block 0 für Verzeichnis-Inode %llu fehlt\n" #~ msgid "can't read block 0 for directory inode %llu\n" #~ msgstr "Block 0 für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #~ msgid "clearing forw/back pointers for directory inode %llu\n" #~ msgstr "" #~ "Vorwärts-/Rückwärtszeiger für Verzeichnis-Inode %llu werden bereinigt\n" #~ msgid "would clear forw/back pointers for directory inode %llu\n" #~ msgstr "" #~ "Vorwärts-/Rückwärtszeiger für Verzeichnis-Inode %llu könnten bereinigt\n" #~ "werden.\n" #~ msgid "couldn't malloc dup extent tree descriptor\n" #~ msgstr "" #~ "malloc dup extent konnte nicht für Baum-Deskriptor ausgeführt werden\n" #~ msgid "couldn't malloc dir2 buffer header\n" #~ msgstr "malloc dir2 Pufferkopfzeilen konnte nicht ausgeführt werden\n" #~ msgid "couldn't malloc dir2 buffer data\n" #~ msgstr "malloc dir2 Pufferdaten konnte nicht ausgeführt werden\n" #~ msgid "release_dir2_cursor_int got unexpected non-null bp, dabno = %u\n" #~ msgstr "" #~ "release_dir2_cursor_int hat unerwartetes Nicht-Null-bp, dabno = %u\n" #~ msgid "block %llu for directory inode %llu is missing\n" #~ msgstr "Block %llu für Verzeichnis-Inode %llu fehlt\n" #~ msgid "can't read block %llu for directory inode %llu\n" #~ msgstr "Block %llu für Verzeichnis-Inode %llu kann nicht gelesen werden\n" #~ msgid "" #~ "bad directory block magic # %#x in block %llu for directory inode %llu\n" #~ msgstr "" #~ "falsches Verzeichnisblatt magische # %#x in Block %llu für\n" #~ "Verzeichnis-Inode %llu\n" #~ msgid "ts_alloc: cannot allocate thread specific storage\n" #~ msgstr "" #~ "ts_alloc: Thread-spezifischer Speicher kann nicht zugewiesen werden\n" #~ msgid "couldn't allocate block map, size = %d\n" #~ msgstr "Blockkarten kann nicht alloziert werden, Größe = %d\n" #~ msgid "" #~ "inode %llu - extent offset too large - start %llu, count %llu, offset " #~ "%llu\n" #~ msgstr "" #~ "Inode %llu - falsche Erweiterungs-Versatz zu groß - Start %llu,\n" #~ "Anzahl %llu, Versatz %llu\n" #~ msgid "cannot read bmap block %llu\n" #~ msgstr "»bmap«-Block %llu kann nicht gelesen werden\n" #~ msgid "# of bmap records in inode %llu exceeds max (%u, max - %u)\n" #~ msgstr "" #~ "# der »bmap«-Aufzeichnungen in Inode %llu überschreiten Maximum (%u,\n" #~ "max - %u)\n" #~ msgid "" #~ "- # of bmap records in inode %llu less than minimum (%u, min - %u), " #~ "proceeding ...\n" #~ msgstr "" #~ "- # der »bmap«-Aufzeichnungen in Inode %llu weniger als das Minimum\n" #~ "(%u, min - %u), fortsetzen ...\n" #~ msgid "" #~ "# of bmap records in inode %llu greater than maximum (%u, max - %u)\n" #~ msgstr "" #~ "# der »bmap«-Aufzeichnungen in Inode %llu größer als das Maximum (%u, \n" #~ "max - %u)\n" #~ msgid "" #~ "- # of bmap records in inode %llu less than minimum (%u, min - %u), " #~ "continuing...\n" #~ msgstr "" #~ "- # der »bmap«-Aufzeichnungen in Inode %llu weniger als das Minimum\n" #~ "(%u, min - %u), fortfahren ...\n" #~ msgid "could not map block %llu\n" #~ msgstr "Block %llu kann nicht kartiert werden\n" #~ msgid "get_bmapi() called for local inode %llu\n" #~ msgstr "get_bmapi() für lokalen Inode %llu aufgerufen\n" #~ msgid "bad inode format for inode %llu\n" #~ msgstr "falsches Inode-Format für Inode %llu\n" #~ msgid "component of symlink in inode %llu too long\n" #~ msgstr "Bestandteil des symbolischen Verweises in Inode %llu zu lang\n" #~ msgid "version 2 inode %llu claims > %u links, " #~ msgstr "Version 2 Inode %llu beansprucht > %u Verweise, " #~ msgid "updating superblock version number\n" #~ msgstr "Superblock-Versionsnummer wird aktualisiert\n" #~ msgid "would update superblock version number\n" #~ msgstr "Superblock-Versionsnummer könnte aktualisiert werden\n" #~ msgid "WARNING: version 2 inode %llu claims > %u links, " #~ msgstr "WARNUNG: Version 2 Inode %llu beansprucht > %u Verweise, " #~ msgid "" #~ "converting back to version 1,\n" #~ "this may destroy %d links\n" #~ msgstr "" #~ "es wird zu Version 1 zurück umgewandelt,\n" #~ "das kann %d Verweise zerstören\n" #~ msgid "" #~ "would convert back to version 1,\n" #~ "\tthis might destroy %d links\n" #~ msgstr "" #~ "es könnte zu Version 1 zurück umgewandelt werden,\n" #~ "\tdas könnte %d Verweise zerstören\n" #~ msgid "found version 2 inode %llu, " #~ msgstr "Version-2-Inode %llu gefunden, " #~ msgid "converting back to version 1\n" #~ msgstr "wird zu Version 1 zurück verwandelt\n" #~ msgid "would convert back to version 1\n" #~ msgstr "es könnte zu Version 1 zurück umgewandelt werden\n" #~ msgid "bad shared version number in superblock %d\n" #~ msgstr "falsche geteilte Versionsnummer im Superblock %d\n" #~ msgid "error following ag %d unlinked list\n" #~ msgstr "Fehler folgt ag %d unverknüpfter Liste\n" #~ msgid "dir" #~ msgstr "dir" #~ msgid "" #~ "can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n" #~ msgstr "" #~ "Block %d in %s Inode %llu kann nicht kartiert werden, xfs_bmapi gibt %d\n" #~ "zurück, nmap = %d\n" #~ msgid "block %d in %s ino %llu doesn't exist\n" #~ msgstr "Block %d in %s ino %llu existiert nicht\n" #~ msgid "can't map block %d in %s ino %llu, xfs_bmapi returns %d, nmap = %d\n" #~ msgstr "" #~ "Block %d in %s ino %llu kann nicht kartiert werden, xfs_bmapi gibt %d\n" #~ "zurück, nmap = %d\n" #~ msgid "block %d in %s inode %llu doesn't exist\n" #~ msgstr "Block %d in %s Inode %llu existiert nicht\n" #~ msgid "entry \"%s\" in dir inode %llu points to non-existent inode %llu" #~ msgstr "" #~ "Eintrag »%s« in dir-Inode %llu zeigt auf nicht existierenden Inode %llu" #~ msgid "entry \"%s\" in dir inode %llu points to free inode %llu" #~ msgstr "Eintrag »%s« in dir-Inode %llu zeigt auf freien Inode %llu" #~ msgid "" #~ "entry \"%s\" in dir %llu points to an already connected dir inode %llu,\n" #~ msgstr "" #~ "Eintrag »%s« in dir %llu zeigt auf einen bereits verbundenen\n" #~ "dir-Inode %llu,\n" #~ msgid "" #~ "entry \"%s\" in dir ino %llu not consistent with .. value (%llu) in ino " #~ "%llu,\n" #~ msgstr "" #~ "Eintrag »%s« in dir ino %llu nicht vollständig mit ..-Wert (%llu) in ino " #~ "%llu,\n" #~ msgid "cannot map block 0 of directory inode %llu\n" #~ msgstr "Block 0 des Verzeichnis-Inodes %llu kann nicht kartiert werden\n" #~ msgid "bad magic # (0x%x) for dir ino %llu leaf block (bno %u fsbno %llu)\n" #~ msgstr "" #~ "falsche magische # (0x%x) für ino %llu Blatt-Block (bno %u fsbno %llu)\n" #~ msgid "" #~ "can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n" #~ msgstr "" #~ "Blatt-Block %d in dir %llu kann nicht kartiert werden, xfs_bmapi gibt %d\n" #~ "zurück, nmap = %d\n" #~ msgid "realloc failed in longform_dir2_entry_check_data (%u bytes)\n" #~ msgstr "" #~ "realloc fehlgeschlagen in longform_dir2_entry_check_data (%u Bytes)\n" #~ msgid "malloc failed in longform_dir2_entry_check (%u bytes)\n" #~ msgstr "malloc fehlgeschlagen in longform_dir2_entry_check (%u Bytes)\n" #~ msgid "realloc failed in longform_dir2_entry_check (%u bytes)\n" #~ msgstr "realloc fehlgeschlagen in longform_dir2_entry_check (%u Bytes)\n" #~ msgid "shortform dir inode %llu has null data entries \n" #~ msgstr "Kurzform dir-Inode %llu hat Null-Daten-Einträge \n" #~ msgid "entry \"%s\" in shortform dir %llu references non-existent ino %llu" #~ msgstr "" #~ "Eintrag »%s« in Kurzform dir-Inode %llu bezieht sich auf nicht\n" #~ "existierenden ino %llu" #~ msgid "entry \"%s\" in shortform dir inode %llu points to free inode %llu" #~ msgstr "" #~ "Eintrag »%s« in Kurzform dir-Inode %llu bezieht sich auf einen freien\n" #~ "Inode %llu" #~ msgid "" #~ "entry \"%s\" in dir %llu references already connected dir ino %llu,\n" #~ msgstr "" #~ "Eintrag »%s« in dir %llu bezieht sich auf einen bereits verbundenen\n" #~ "dir ino %llu\n" #~ msgid "" #~ "entry \"%s\" in dir %llu not consistent with .. value (%llu) in dir ino " #~ "%llu" #~ msgstr "" #~ "Eintrag »%s« in dir %llu nicht übereinstimmend mit ..-Wert (%llu) in\n" #~ "dir ino %llu" #~ msgid "missing root directory .. entry, cannot fix in V1 dir filesystem\n" #~ msgstr "" #~ "fehlender Wurzelverzeichnis-..-Eintrag, kann nicht in V1 dir-Dateisystem\n" #~ "behoben werden\n" #~ msgid "" #~ "%d bad entries found in dir inode %llu, cannot fix in V1 dir filesystem\n" #~ msgstr "" #~ "%d falsche Einträge in dir-Inode %llu gefunden, kann nicht in V1\n" #~ "dir-Dateisystem behoben werden\n" #~ msgid "" #~ "missing \".\" entry in dir ino %llu, cannot in fix V1 dir filesystem\n" #~ msgstr "" #~ "fehlender ».«-Eintrag in dir ino %llu, kann nicht in V1 dir-Dateisystem\n" #~ "behoben werden\n" #~ msgid "cannot fix in V1 dir filesystem\n" #~ msgstr "kann nicht in V1 dir-Dateisystem behoben werden\n" #~ msgid "" #~ "need to reinitialize root directory, but not supported on V1 dir " #~ "filesystem\n" #~ msgstr "" #~ "Neuinitialisierung des Wurzelverzeichnisses nötig, aber nicht auf\n" #~ "V1 dir-Dateisystem unterstützt\n" xfsprogs-4.9.0+nmu1ubuntu2/po/pl.po0000644000000000000000000172500613063067174014101 0ustar # Polish translation for xfsprogs. # This file is distributed under the same license as the xfsprogs package. # Jakub Bogusz , 2006-2014. # msgid "" msgstr "" "Project-Id-Version: xfsprogs 3.2.0+git20140709\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-01-08 07:15+1100\n" "PO-Revision-Date: 2014-07-09 20:45+0200\n" "Last-Translator: Jakub Bogusz \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: .././copy/xfs_copy.c:115 #, c-format msgid "Check logfile \"%s\" for more details\n" msgstr "WiÄ™cej szczegółów w pliku logu \"%s\"\n" #: .././copy/xfs_copy.c:121 #, c-format msgid "%s: could not write to logfile \"%s\".\n" msgstr "%s: nie udaÅ‚o siÄ™ zapisać pliku logu \"%s\".\n" #: .././copy/xfs_copy.c:124 #, c-format msgid "Aborting XFS copy -- logfile error -- reason: %s\n" msgstr "Przerwano XFS copy - błąd pliku logu - przyczyna: %s\n" #: .././copy/xfs_copy.c:139 .././copy/xfs_copy.c:292 .././copy/xfs_copy.c:605 #: .././copy/xfs_copy.c:612 msgid "Aborting XFS copy - reason" msgstr "Przerwano XFS copy - przyczyna" #: .././copy/xfs_copy.c:159 msgid "THE FOLLOWING COPIES FAILED TO COMPLETE\n" msgstr "NASTĘPUJÄ„CYCH KOPII NIE UDAÅO SIĘ UKOŃCZYĆ\n" #: .././copy/xfs_copy.c:163 msgid "write error" msgstr "błąd zapisu" #: .././copy/xfs_copy.c:165 msgid "lseek error" msgstr "błąd lseek" #: .././copy/xfs_copy.c:166 #, c-format msgid " at offset %lld\n" msgstr " pod offsetem %lld\n" #: .././copy/xfs_copy.c:170 #, c-format msgid "All copies completed.\n" msgstr "Wszystkie kopie ukoÅ„czone.\n" #: .././copy/xfs_copy.c:173 #, c-format msgid "See \"%s\" for more details.\n" msgstr "WiÄ™cej szczegółów w \"%s\".\n" #: .././copy/xfs_copy.c:261 #, c-format msgid "%s: write error on target %d \"%s\" at offset %lld\n" msgstr "%s: błąd zapisu przy celu %d \"%s\" pod offsetem %lld\n" #: .././copy/xfs_copy.c:266 #, c-format msgid "%s: lseek error on target %d \"%s\" at offset %lld\n" msgstr "%s: błąd lseek przy celu %d \"%s\" pod offsetem %lld\n" #: .././copy/xfs_copy.c:272 #, c-format msgid "Aborting target %d - reason" msgstr "Przerywano zapis celu %d - przyczyna" #: .././copy/xfs_copy.c:276 msgid "Aborting XFS copy - no more targets.\n" msgstr "Przerwano XFS copy - nie ma wiÄ™cej celów.\n" #: .././copy/xfs_copy.c:287 #, c-format msgid "%s: thread %d died unexpectedly, target \"%s\" incomplete\n" msgstr "%s: wÄ…tek %d zmarÅ‚ nieoczekiwanie, cel \"%s\" niekompletny\n" #: .././copy/xfs_copy.c:289 #, c-format msgid "%s: offset was probably %lld\n" msgstr "%s: offset prawdopodobnie %lld\n" #: .././copy/xfs_copy.c:300 #, c-format msgid "%s: Unknown child died (should never happen!)\n" msgstr "%s: Nieznany potomek zmarÅ‚ (nie powinno siÄ™ zdarzyć!)\n" #: .././copy/xfs_copy.c:310 #, c-format msgid "Usage: %s [-bdV] [-L logfile] source target [target ...]\n" msgstr "SkÅ‚adnia: %s [-bdV] [-L plik_logu] źródÅ‚o cel [cel ...]\n" #: .././copy/xfs_copy.c:393 #, c-format msgid "%s: lseek failure at offset %lld\n" msgstr "%s: niepowodzenie lseek pod offsetem %lld\n" #: .././copy/xfs_copy.c:408 #, c-format msgid "assert error: buf->length = %d, buf->size = %d\n" msgstr "błąd zapewnienia: buf->length = %d, buf->size = %d\n" #: .././copy/xfs_copy.c:414 #, c-format msgid "%s: read failure at offset %lld\n" msgstr "%s: błąd odczytu pod offsetem %lld\n" #: .././copy/xfs_copy.c:444 msgid "ag header buffer invalid!\n" msgstr "błędny bufor nagłówka ag!\n" #: .././copy/xfs_copy.c:585 .././db/init.c:96 .././estimate/xfs_estimate.c:144 #: .././fsr/xfs_fsr.c:295 .././growfs/xfs_growfs.c:190 .././io/init.c:199 #: .././logprint/logprint.c:206 .././mkfs/xfs_mkfs.c:1925 #: .././quota/init.c:181 .././repair/xfs_repair.c:322 .././rtcp/xfs_rtcp.c:55 #, c-format msgid "%s version %s\n" msgstr "%s wersja %s\n" #: .././copy/xfs_copy.c:603 #, c-format msgid "%s: couldn't open log file \"%s\"\n" msgstr "%s: nie udaÅ‚o siÄ™ otworzyć pliku logu \"%s\"\n" #: .././copy/xfs_copy.c:610 #, c-format msgid "%s: couldn't set up logfile stream\n" msgstr "%s: nie udaÅ‚o siÄ™ ustanowić strumienia pliku logu\n" #: .././copy/xfs_copy.c:622 msgid "Couldn't allocate target array\n" msgstr "Nie udaÅ‚o siÄ™ przydzielić tablicy celów\n" #: .././copy/xfs_copy.c:641 #, c-format msgid "%s: couldn't open source \"%s\"\n" msgstr "%s: nie udaÅ‚o siÄ™ otworzyć źródÅ‚a \"%s\"\n" #: .././copy/xfs_copy.c:647 #, c-format msgid "%s: couldn't stat source \"%s\"\n" msgstr "%s: nie udaÅ‚o siÄ™ wykonać stat na źródle \"%s\"\n" #: .././copy/xfs_copy.c:657 #, c-format msgid "%s: Cannot set direct I/O flag on \"%s\".\n" msgstr "%s: Nie można ustawić flagi bezpoÅ›redniego we/wy na \"%s\".\n" #: .././copy/xfs_copy.c:662 #, c-format msgid "%s: xfsctl on file \"%s\" failed.\n" msgstr "%s: xfsctl na pliku \"%s\" nie powiodÅ‚o siÄ™.\n" #: .././copy/xfs_copy.c:685 #, c-format msgid "%s: Warning -- a filesystem is mounted on the source device.\n" msgstr "%s: Uwaga - system plików jest podmontowany na urzÄ…dzeniu źródÅ‚owym.\n" #: .././copy/xfs_copy.c:688 msgid "\t\tGenerated copies may be corrupt unless the source is\n" msgstr "\t\tWygenerowane kopie mogÄ… być uszkodzone o ile źródÅ‚o nie jest\n" #: .././copy/xfs_copy.c:690 msgid "\t\tunmounted or mounted read-only. Copy proceeding...\n" msgstr "" "\t\todmontowane lub podmontowane tylko do odczytu. Kopiowanie w trakcie...\n" #: .././copy/xfs_copy.c:707 #, c-format msgid "" "%s: couldn't initialize XFS library\n" "%s: Aborting.\n" msgstr "" "%s: nie udaÅ‚o siÄ™ zainicjować biblioteki XFS\n" "%s: Przerwano.\n" #: .././copy/xfs_copy.c:731 #, c-format msgid "" "%s: %s filesystem failed to initialize\n" "%s: Aborting.\n" msgstr "" "%s: Nie powiodÅ‚a siÄ™ inicjalizacja systemu plików %s\n" "%s: Przerwano.\n" #: .././copy/xfs_copy.c:735 #, c-format msgid "" "%s %s filesystem failed to initialize\n" "%s: Aborting.\n" msgstr "" "%s: Nie powiodÅ‚a siÄ™ inicjalizacja systemu plików %s\n" "%s: Przerwano.\n" #: .././copy/xfs_copy.c:739 #, c-format msgid "" "%s: %s has an external log.\n" "%s: Aborting.\n" msgstr "" "%s: %s ma zewnÄ™trzny log.\n" "%s: Przerwano.\n" #: .././copy/xfs_copy.c:743 #, c-format msgid "" "%s: %s has a real-time section.\n" "%s: Aborting.\n" msgstr "" "%s: %s ma sekcjÄ™ real-time.\n" "%s: Przerwano.\n" #: .././copy/xfs_copy.c:762 msgid "" "Error: source filesystem log is dirty. Mount the filesystem to replay the\n" "log, unmount and retry xfs_copy.\n" msgstr "" #: .././copy/xfs_copy.c:767 msgid "" "Error: could not determine the log head or tail of the source filesystem.\n" "Mount the filesystem to replay the log or run xfs_repair.\n" msgstr "" #: .././copy/xfs_copy.c:783 msgid "" "Error: filesystem block size is smaller than the disk sectorsize.\n" "Aborting XFS copy now.\n" msgstr "" "Błąd: rozmiar bloku systemu plików jest mniejszy niż rozmiar sektora dysku.\n" "Przerwano XFS copy.\n" #: .././copy/xfs_copy.c:800 #, c-format msgid "Creating file %s\n" msgstr "Tworzenie pliku %s\n" #: .././copy/xfs_copy.c:818 #, c-format msgid "" "%s: a filesystem is mounted on target device \"%s\".\n" "%s cannot copy to mounted filesystems. Aborting\n" msgstr "" "%s: na urzÄ…dzeniu docelowym \"%s\" jest podmontowany system plików.\n" "%s nie może kopiować na podmontowane systemy plików. Przerwano.\n" #: .././copy/xfs_copy.c:829 #, c-format msgid "%s: couldn't open target \"%s\"\n" msgstr "%s: nie udaÅ‚o siÄ™ otworzyć celu \"%s\"\n" #: .././copy/xfs_copy.c:839 #, c-format msgid "%s: cannot grow data section.\n" msgstr "%s: nie można powiÄ™kszyć sekcji danych.\n" #: .././copy/xfs_copy.c:847 #, c-format msgid "%s: xfsctl on \"%s\" failed.\n" msgstr "%s: xfsctl na \"%s\" nie powiodÅ‚o siÄ™.\n" #: .././copy/xfs_copy.c:866 #, c-format msgid "%s: failed to write last block\n" msgstr "%s: nie udaÅ‚o siÄ™ zapisać ostatniego bloku\n" #: .././copy/xfs_copy.c:868 #, c-format msgid "\tIs target \"%s\" too small?\n" msgstr "\tCzy cel \"%s\" jest zbyt maÅ‚y?\n" #: .././copy/xfs_copy.c:878 msgid "Couldn't initialize global thread mask\n" msgstr "Nie udaÅ‚o siÄ™ zainicjować globalnej maski wÄ…tków\n" #: .././copy/xfs_copy.c:885 msgid "Error initializing wbuf 0\n" msgstr "Błąd inicjalizacji wbuf 0\n" #: .././copy/xfs_copy.c:893 msgid "Error initializing btree buf 1\n" msgstr "Błąd inicjalizacji btree buf 1\n" #: .././copy/xfs_copy.c:898 msgid "Error creating first semaphore.\n" msgstr "Błąd tworzenia pierwszego semafora.\n" #: .././copy/xfs_copy.c:913 msgid "Couldn't malloc space for thread args\n" msgstr "Nie udaÅ‚o siÄ™ przydzielić miejsca na argumenty wÄ…tku\n" #: .././copy/xfs_copy.c:925 #, c-format msgid "Error creating thread mutex %d\n" msgstr "Błąd podczas tworzenia sekcji krytycznej %d wÄ…tku\n" #: .././copy/xfs_copy.c:942 #, c-format msgid "Error creating thread for target %d\n" msgstr "Błąd podczas tworzenia wÄ…tku dla celu %d\n" #: .././copy/xfs_copy.c:996 #, c-format msgid "Error: current level %d >= btree levels %d\n" msgstr "Błąd: bieżący poziom %d >= poziomów b-drzewa %d\n" #: .././copy/xfs_copy.c:1015 #, c-format msgid "Bad btree magic 0x%x\n" msgstr "NiewÅ‚aÅ›ciwa liczba magiczna b-drzewa 0x%x\n" #: .././copy/xfs_copy.c:1042 msgid "WARNING: source filesystem inconsistent.\n" msgstr "UWAGA: źródÅ‚owy system plików niespójny.\n" #: .././copy/xfs_copy.c:1044 msgid " A leaf btree rec isn't a leaf. Aborting now.\n" msgstr " Liść rekordu b-drzewa nie jest liÅ›ciem. Przerwano.\n" #: .././db/addr.c:35 msgid "[field-expression]" msgstr "[wyrażenie-pól]" #: .././db/addr.c:36 msgid "set current address" msgstr "ustawienie bieżącego adresu" #: .././db/addr.c:42 msgid "" "\n" " 'addr' uses the given field to set the filesystem address and type\n" "\n" " Examples:\n" "\n" " sb\n" " a rootino - set the type to inode and set position to the root inode\n" " a u.bmx[0].startblock (for inode with blockmap)\n" "\n" msgstr "" "\n" " 'addr' wykorzystuje podane pole do ustawienia adresu w systemie plików i " "typu\n" "\n" " PrzykÅ‚ady:\n" "\n" " sb\n" " a rootino - ustawienie typu na i-wÄ™zeÅ‚ i pozycji na i-wÄ™zeÅ‚ główny\n" " a u.bmx[0].startblock (dla i-wÄ™zÅ‚a z mapÄ… bloków)\n" "\n" #: .././db/addr.c:72 .././db/attrset.c:86 .././db/attrset.c:189 #: .././db/crc.c:76 .././db/print.c:74 .././db/type.c:208 .././db/write.c:110 msgid "no current type\n" msgstr "brak bieżącego typu\n" #: .././db/addr.c:82 #, c-format msgid "no fields for type %s\n" msgstr "brak pól dla typu %s\n" #: .././db/addr.c:94 msgid "array not allowed for addr command\n" msgstr "tablica nie jest dozwolona dla polecenia addr\n" #: .././db/addr.c:103 #, c-format msgid "no next type for field %s\n" msgstr "brak nastÄ™pnego typu dla pola %s\n" #: .././db/addr.c:110 #, c-format msgid "no addr function for field %s (type %s)\n" msgstr "brak funkcji addr dla pola %s (typu %s)\n" #: .././db/agf.c:35 .././db/agfl.c:36 .././db/agi.c:35 .././db/sb.c:44 msgid "[agno]" msgstr "[agno]" #: .././db/agf.c:36 msgid "set address to agf header" msgstr "ustawienie adresu na nagłówek agf" #: .././db/agf.c:100 msgid "" "\n" " set allocation group free block list\n" "\n" " Example:\n" "\n" " agf 2 - move location to AGF in 2nd filesystem allocation group\n" "\n" " Located in the second sector of each allocation group, the AGF\n" " contains the root of two different freespace btrees:\n" " The 'cnt' btree keeps track freespace indexed on section size.\n" " The 'bno' btree tracks sections of freespace indexed on block number.\n" msgstr "" "\n" " ustawienie listy wolnych bloków grupy alokacji\n" "\n" " PrzykÅ‚ad:\n" "\n" " agf 2 - zmiana pozycji na AGF w 2. grupie alokacji systemu plików\n" "\n" " PoÅ‚ożony w drugim sektorze każdej grupy alokacji AGF zawiera korzeÅ„\n" " dwóch różnych b-drzew wolnej przestrzeni:\n" " b-drzewo 'cnt' Å›ledzi wolne miejsce indeksowane rozmiarem sekcji\n" " b-drzewo 'bno' Å›ledzi sekcje wolnego miejsca indeksowane numerem bloku.\n" #: .././db/agf.c:125 .././db/agfl.c:106 .././db/agi.c:94 .././db/sb.c:167 #, c-format msgid "bad allocation group number %s\n" msgstr "błędny numer grupy alokacji %s\n" #: .././db/agfl.c:37 msgid "set address to agfl block" msgstr "ustawienie adresu na blok agfl" #: .././db/agfl.c:79 msgid "" "\n" " set allocation group freelist\n" "\n" " Example:\n" "\n" " agfl 5\n" " Located in the fourth sector of each allocation group,\n" " the agfl freelist for internal btree space allocation is maintained\n" " for each allocation group. This acts as a reserved pool of space\n" " separate from the general filesystem freespace (not used for user data).\n" "\n" msgstr "" "\n" " ustawienie listy wolnego miejsca grupy alokacji\n" "\n" " PrzykÅ‚ad:\n" "\n" " agfl 5\n" " PoÅ‚ożona w 4. sektorze każdej grupy alokacji lista wolnego miejsca agfl\n" " sÅ‚użąca do wewnÄ™trznego przydzielania miejsca dla b-drzew jest utrzymywana\n" " dla każdej grupy alokacji. DziaÅ‚a jako zarezerwowana pula miejsca " "oddzielona\n" " od ogólnego wolnego miejsca w systemie plików (nie używana dla danych\n" " użytkownika).\n" "\n" #: .././db/agi.c:36 msgid "set address to agi header" msgstr "ustawienie adresu na nagłówek agi" #: .././db/agi.c:69 msgid "" "\n" " set allocation group inode btree\n" "\n" " Example:\n" "\n" " agi 3 (set location to 3rd allocation group inode btree and type to 'agi')\n" "\n" " Located in the 3rd 512 byte block of each allocation group,\n" " the agi inode btree tracks all used/free inodes in the allocation group.\n" " Inodes are allocated in 16k 'chunks', each btree entry tracks a 'chunk'.\n" "\n" msgstr "" "\n" " ustawienie b-drzewa i-wÄ™zÅ‚a grupy alokacji\n" "\n" " PrzykÅ‚ad:\n" "\n" " agi 3 (ustawienie poÅ‚ożenia na b-drzewo i-wÄ™zÅ‚a 3. grupy alokacji i typu na " "'agi')\n" "\n" " PoÅ‚ożone w 3. 512-bajtowym bloku każdej grupy alokacji, b-drzewo i-wÄ™zÅ‚a " "agi\n" " Å›ledzi wszystkie używane i wolne i-wÄ™zÅ‚y w grupie alokacji.\n" " I-wÄ™zÅ‚y sÄ… przydzielane w 16k porcjach (chunk), każdy wpis b-drzewa Å›ledzi\n" " jednÄ….\n" "\n" #: .././db/attr.c:556 msgid "Unknown attribute buffer type!\n" msgstr "Nieznany typ bufora atrybutów!\n" #: .././db/attr.c:568 msgid "Writing unknown attribute buffer type!\n" msgstr "Zapis nieznanego typu bufora atrybutów!\n" #: .././db/attrset.c:38 msgid "[-r|-s|-p|-u] [-n] [-R|-C] [-v n] name" msgstr "[-r|-s|-p|-u] [-n] [-R|-C] [-v n] nazwa" #: .././db/attrset.c:39 msgid "set the named attribute on the current inode" msgstr "ustawienie atrybutu o podanej nazwie w bieżącym i-węźle" #: .././db/attrset.c:42 msgid "[-r|-s|-p|-u] [-n] name" msgstr "[-r|-s|-p|-u] [-n] nazwa" #: .././db/attrset.c:43 msgid "remove the named attribute from the current inode" msgstr "usuniÄ™cie atrybutu o podanej nazwie z bieżącego i-wÄ™zÅ‚a" #: .././db/attrset.c:49 msgid "" "\n" " The 'attr_set' and 'attr_remove' commands provide interfaces for debugging\n" " the extended attribute allocation and removal code.\n" " Both commands require an attribute name to be specified, and the attr_set\n" " command allows an optional value length (-v) to be provided as well.\n" " There are 4 namespace flags:\n" " -r -- 'root'\n" " -u -- 'user'\t\t(default)\n" " -s -- 'secure'\n" "\n" " For attr_set, these options further define the type of set operation:\n" " -C -- 'create' - create attribute, fail if it already exists\n" " -R -- 'replace' - replace attribute, fail if it does not exist\n" " The backward compatibility mode 'noattr2' can be emulated (-n) also.\n" "\n" msgstr "" "\n" " Polecenia 'attr_set' i 'attr_remove' udostÄ™pniajÄ… interfejsy do " "diagnostyki\n" " kodu przydzielania i usuwania rozszerzonych atrybutów.\n" " Oba polecenia wymagajÄ… podania nazwy atrybutu, a polecenie attr_set\n" " pozwala dodatkowo podać opcjonalnÄ… dÅ‚ugość wartoÅ›ci (-v).\n" " SÄ… 4 flagi przestrzeni nazw:\n" " -r - 'root'\n" " -u - 'user' (domyÅ›lna)\n" " -s - 'secure'\n" "\n" " Dla attr_set poniższe opcje okreÅ›lajÄ… rodzaj operacji ustawiania:\n" " -C - 'create' - utworzenie atrybutu; nie powiedzie siÄ™, jeÅ›li już " "istnieje\n" " -R - 'replace' - zastÄ…pienie atrybutu; nie powiedzie siÄ™, jeÅ›li nie " "istnieje\n" " Możliwa jest także emulacja trybu kompatybilnoÅ›ci wstecznej 'noattr2' (-" "n).\n" "\n" #: .././db/attrset.c:90 .././db/attrset.c:193 msgid "current type is not inode\n" msgstr "bieżący typ nie jest i-wÄ™zÅ‚em\n" #: .././db/attrset.c:125 #, c-format msgid "bad attr_set valuelen %s\n" msgstr "błędna dÅ‚ugość wartoÅ›ci %s dla attr_set\n" #: .././db/attrset.c:131 msgid "bad option for attr_set command\n" msgstr "błędna opcja dla polecenia attr_set\n" #: .././db/attrset.c:137 msgid "too few options for attr_set (no name given)\n" msgstr "za maÅ‚o opcji dla attr_set (nie podano nazwy)\n" #: .././db/attrset.c:146 #, c-format msgid "cannot allocate buffer (%d)\n" msgstr "nie udaÅ‚o siÄ™ przydzielić bufora (%d)\n" #: .././db/attrset.c:155 .././db/attrset.c:230 #, c-format msgid "failed to iget inode %llu\n" msgstr "operacja iget na i-węźle %llu nie powiodÅ‚a siÄ™\n" #: .././db/attrset.c:162 #, c-format msgid "failed to set attr %s on inode %llu\n" msgstr "ustawianie atrybutu %s w i-węźle %llu nie powiodÅ‚o siÄ™\n" #: .././db/attrset.c:217 msgid "bad option for attr_remove command\n" msgstr "błędna opcja dla polecenia attr_remove\n" #: .././db/attrset.c:223 msgid "too few options for attr_remove (no name given)\n" msgstr "za maÅ‚o opcji dla attr_remove (nie podano nazwy)\n" #: .././db/attrset.c:236 #, c-format msgid "failed to remove attr %s from inode %llu\n" msgstr "usuniÄ™cie atrybutu %s z i-wÄ™zÅ‚a %llu nie powiodÅ‚o siÄ™\n" #: .././db/block.c:43 .././db/block.c:49 msgid "filoff" msgstr "filoff" #: .././db/block.c:44 msgid "set address to file offset (attr fork)" msgstr "ustawienie adresu na offset w pliku (gałąź atrybutów)" #: .././db/block.c:46 msgid "[d]" msgstr "[d]" #: .././db/block.c:47 msgid "set address to daddr value" msgstr "ustawienie adresu na wartość daddr" #: .././db/block.c:50 msgid "set address to file offset (data fork)" msgstr "ustawienie adresu na offset w pliku (gałąź danych)" #: .././db/block.c:52 msgid "[fsb]" msgstr "[fsb]" #: .././db/block.c:53 msgid "set address to fsblock value" msgstr "ustawienie adresu na wartość fsblock" #: .././db/block.c:59 msgid "" "\n" " Example:\n" "\n" " 'ablock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's attribute fork. The filesystem block size is specified in\n" " the superblock.\n" "\n" msgstr "" "\n" " PrzykÅ‚ad:\n" "\n" " 'ablock 23' ustawia pozycjÄ™ w pliku na 23. blok systemu plików w gałęzi\n" " atrybutów i-wÄ™zÅ‚a. Rozmiar bloku systemu plików jest okreÅ›lony w " "superbloku.\n" "\n" #: .././db/block.c:82 .././db/block.c:177 #, c-format msgid "bad block number %s\n" msgstr "błędny numer bloku %s\n" #: .././db/block.c:90 msgid "no attribute data for file\n" msgstr "brak danych atrybutów dla pliku\n" #: .././db/block.c:96 msgid "file attr block is unmapped\n" msgstr "blok atrybutów pliku nie ma odwzorowania\n" #: .././db/block.c:119 msgid "" "\n" " Example:\n" "\n" " 'daddr 102' - sets position to the 102nd absolute disk block\n" " (512 byte block).\n" msgstr "" "\n" " PrzykÅ‚ad:\n" "\n" " 'daddr 102' ustawia pozycjÄ™ na 102. (bezwzglÄ™dnie) blok dysku\n" " (blok 512-bajtowy).\n" #: .././db/block.c:135 #, c-format msgid "current daddr is %lld\n" msgstr "bieżący daddr to %lld\n" #: .././db/block.c:141 #, c-format msgid "bad daddr %s\n" msgstr "błędny daddr %s\n" #: .././db/block.c:153 msgid "" "\n" " Example:\n" "\n" " 'dblock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's data fork. The filesystem block size is specified in the\n" " superblock.\n" "\n" msgstr "" "\n" " PrzykÅ‚ad:\n" "\n" " 'dblock 23' ustawia pozycjÄ™ w pliku na 23. blok systemu plików w gałęzi\n" " danych i-wÄ™zÅ‚a. Rozmiar bloku systemu plików jest okreÅ›lony w superbloku.\n" "\n" #: .././db/block.c:185 msgid "no type for file data\n" msgstr "brak typu dla danych pliku\n" #: .././db/block.c:192 msgid "file data block is unmapped\n" msgstr "blok danych plików nie ma odwzorowania\n" #: .././db/block.c:210 msgid "" "\n" " Example:\n" "\n" " 'fsblock 1023' - sets the file position to the 1023rd filesystem block.\n" " The filesystem block size is specified in the superblock and set during\n" " mkfs time. Offset is absolute (not AG relative).\n" "\n" msgstr "" "\n" " PrzykÅ‚ad:\n" "\n" " 'fsblock 1023' ustawia pozycjÄ™ w pliku na 1023. blok systemu plików.\n" " Rozmiar bloku systemu plików jest okreÅ›lony w superbloku i ustawiany w\n" " trakcie wykonywania mkfs. Offset jest bezwzglÄ™dny (nie wzglÄ™dem AG).\n" "\n" #: .././db/block.c:229 #, c-format msgid "current fsblock is %lld\n" msgstr "bieżący fsblock to %lld\n" #: .././db/block.c:235 .././db/block.c:241 #, c-format msgid "bad fsblock %s\n" msgstr "błędny fsblock %s\n" #: .././db/bmap.c:39 msgid "[-ad] [block [len]]" msgstr "[-ad] [blok [dÅ‚ugość]]" #: .././db/bmap.c:40 msgid "show block map for current file" msgstr "pokazanie mapy bloków dla bieżącego pliku" #: .././db/bmap.c:152 .././db/inode.c:424 msgid "no current inode\n" msgstr "brak bieżącego i-wÄ™zÅ‚a\n" #: .././db/bmap.c:165 msgid "bad option for bmap command\n" msgstr "błędna opcja dla polecenia bmap\n" #: .././db/bmap.c:182 #, c-format msgid "bad block number for bmap %s\n" msgstr "błędny numer bloku dla bmap %s\n" #: .././db/bmap.c:190 #, c-format msgid "bad len for bmap %s\n" msgstr "błędna dÅ‚ugość dla bmap %s\n" #: .././db/bmap.c:213 #, c-format msgid "%s offset %lld startblock %llu (%u/%u) count %llu flag %u\n" msgstr "%s oofset %lld blok-pocz %llu (%u/%u) liczba %llu flaga %u\n" #: .././db/bmap.c:215 .././db/check.c:2224 .././db/check.c:2236 #: .././db/check.c:2263 .././repair/dinode.c:52 msgid "data" msgstr "danych" #: .././db/bmap.c:215 .././db/check.c:2224 .././db/check.c:2236 #: .././db/check.c:2263 .././repair/dinode.c:53 msgid "attr" msgstr "atrybutów" #: .././db/check.c:378 msgid "free block usage information" msgstr "informacje o wykorzystaniu wolnych bloków" #: .././db/check.c:381 msgid "[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..." msgstr "[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..." #: .././db/check.c:382 msgid "get block usage and check consistency" msgstr "uzyskanie informacji o wykorzystaniu bloków i sprawdzenie spójnoÅ›ci" #: .././db/check.c:385 msgid "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ..." msgstr "[-n liczba] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t typ] ..." #: .././db/check.c:386 msgid "trash randomly selected block(s)" msgstr "zaÅ›miecenie losowo wybranych bloków" #: .././db/check.c:389 msgid "[-n] [-c blockcount]" msgstr "[-n] [-c liczba-bloków]" #: .././db/check.c:390 msgid "print usage for current block(s)" msgstr "wypisanie wykorzystania bieżących bloków" #: .././db/check.c:393 msgid "[-s] [-i ino] ..." msgstr "[-s] [-i ino] ..." #: .././db/check.c:394 msgid "print inode-name pairs" msgstr "wypisanie par i-wÄ™zeÅ‚ - nazwa" #: .././db/check.c:414 #, c-format msgid "-i %lld bad inode number\n" msgstr "-i %lld - błędny numer i-wÄ™zÅ‚a\n" #: .././db/check.c:426 #, c-format msgid "inode %lld add link, now %u\n" msgstr "i-wÄ™zeÅ‚ %lld - dodano dowiÄ…zanie, teraz %u\n" #: .././db/check.c:453 #, c-format msgid "inode %lld parent %lld\n" msgstr "i-wÄ™zeÅ‚ %lld - rodzic %lld\n" #: .././db/check.c:766 msgid "block usage information not allocated\n" msgstr "informacja o wykorzystaniu bloków nie przydzielona\n" #: .././db/check.c:804 msgid "already have block usage information\n" msgstr "już istnieje informacja o wykorzystaniu bloków\n" #: .././db/check.c:821 .././db/check.c:922 msgid "WARNING: this may be a newer XFS filesystem.\n" msgstr "UWAGA: to może być nowszy system plików XFS.\n" #: .././db/check.c:857 #, c-format msgid "sb_icount %lld, counted %lld\n" msgstr "sb_icount %lld, naliczono %lld\n" #: .././db/check.c:863 #, c-format msgid "sb_ifree %lld, counted %lld\n" msgstr "sb_ifree %lld, naliczono %lld\n" #: .././db/check.c:869 #, c-format msgid "sb_fdblocks %lld, counted %lld\n" msgstr "sb_fdblocks %lld, naliczono %lld\n" #: .././db/check.c:875 #, c-format msgid "sb_fdblocks %lld, aggregate AGF count %lld\n" msgstr "sb_fdblocks %lld, łączny licznik AGF %lld\n" #: .././db/check.c:881 #, c-format msgid "sb_frextents %lld, counted %lld\n" msgstr "sb_frextents %lld, naliczono %lld\n" #: .././db/check.c:888 #, c-format msgid "sb_features2 (0x%x) not same as sb_bad_features2 (0x%x)\n" msgstr "sb_features2 (0x%x) różni siÄ™ od sb_bad_features2 (0x%x)\n" #: .././db/check.c:897 #, c-format msgid "sb versionnum missing attr bit %x\n" msgstr "sb versionnum - brak bitu atrybutu %x\n" #: .././db/check.c:904 #, c-format msgid "sb versionnum missing quota bit %x\n" msgstr "sb versionnum - brak bitu quota %x\n" #: .././db/check.c:911 #, c-format msgid "sb versionnum extra align bit %x\n" msgstr "sb versionnum - nadmiarowy bit align %x\n" #: .././db/check.c:950 msgid "zeroed" msgstr "wyzerowano" #: .././db/check.c:950 msgid "set" msgstr "ustawiono" #: .././db/check.c:950 msgid "flipped" msgstr "przełączono" #: .././db/check.c:950 msgid "randomized" msgstr "ulosowiono" #: .././db/check.c:958 #, fuzzy, c-format msgid "zero-length block %u/%u buffer to trash??\n" msgstr "ustawianie bloku %u/%u na %s\n" #: .././db/check.c:977 #, c-format msgid "can't read block %u/%u for trashing\n" msgstr "nie można odczytać bloku %u/%u w celu zaÅ›miecenia\n" #: .././db/check.c:1006 #, c-format msgid "blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n" msgstr "blocktrash: %u/%u %s blok %d bit%s poczÄ…tek %d:%d %s\n" #: .././db/check.c:1085 #, c-format msgid "bad blocktrash count %s\n" msgstr "błędna liczba bloków do zaÅ›miecenia %s\n" #: .././db/check.c:1097 #, fuzzy, c-format msgid "bad blocktrash offset %s\n" msgstr "błędna liczba bloków do zaÅ›miecenia %s\n" #: .././db/check.c:1114 #, c-format msgid "bad blocktrash type %s\n" msgstr "błędny typ zaÅ›miecania %s\n" #: .././db/check.c:1123 #, c-format msgid "bad blocktrash min %s\n" msgstr "błędny poczÄ…tek zaÅ›miecania %s\n" #: .././db/check.c:1131 #, c-format msgid "bad blocktrash max %s\n" msgstr "błędny koniec zaÅ›miecania %s\n" #: .././db/check.c:1139 msgid "bad option for blocktrash command\n" msgstr "błędna opcja polecenia blocktrash\n" #: .././db/check.c:1144 .././db/check.c:1235 msgid "must run blockget first\n" msgstr "najpierw trzeba wykonać blockget\n" #: .././db/check.c:1148 #, fuzzy msgid "nothing on stack\n" msgstr "nie ma nic do zapisania\n" #: .././db/check.c:1152 msgid "bad min/max for blocktrash command\n" msgstr "błędny poczÄ…tek/koniec polecenia blocktrash\n" #: .././db/check.c:1170 #, c-format msgid "blocktrash: seed %u\n" msgstr "blocktash: zarodek %u\n" #: .././db/check.c:1186 msgid "blocktrash: no matching blocks\n" msgstr "blocktrash: brak pasujÄ…cych bloków\n" #: .././db/check.c:1250 #, c-format msgid "bad blockuse count %s\n" msgstr "błędna liczba bloków dla blockuse: %s\n" #: .././db/check.c:1256 .././db/check.c:1980 msgid "must run blockget -n first\n" msgstr "najpierw trzeba wykonać blockget -n\n" #: .././db/check.c:1262 msgid "bad option for blockuse command\n" msgstr "błędna opcja dla polecenia blockuse\n" #: .././db/check.c:1269 #, c-format msgid "block %llu (%u/%u) type %s" msgstr "blok %llu (%u/%u) typu %s" #: .././db/check.c:1273 #, c-format msgid " inode %lld" msgstr " i-wÄ™zeÅ‚ %lld" #: .././db/check.c:1317 #, c-format msgid "block %u/%u expected type %s got %s\n" msgstr "blok %u/%u: oczekiwano typu %s, otrzymano %s\n" #: .././db/check.c:1350 #, c-format msgid "blocks %u/%u..%u claimed by inode %lld\n" msgstr "blok %u/%u..%u przypisany do i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:1358 #, c-format msgid "block %u/%u claimed by inode %lld, previous inum %lld\n" msgstr "blok %u/%u przypisany do i-wÄ™zÅ‚a %lld, poprzedni inum %lld\n" #: .././db/check.c:1387 #, c-format msgid "link count mismatch for inode %lld (name %s), nlink %d, counted %d\n" msgstr "" "niezgodność liczby dowiÄ…zaÅ„ dla i-wÄ™zÅ‚a %lld (nazwa %s), nlink %d, naliczono " "%d\n" #: .././db/check.c:1395 #, c-format msgid "disconnected inode %lld, nlink %d\n" msgstr "odłączony i-wÄ™zeÅ‚ %lld, nlink %d\n" #: .././db/check.c:1399 #, c-format msgid "allocated inode %lld has 0 link count\n" msgstr "przydzielony i-wÄ™zeÅ‚ %lld ma zerowÄ… liczbÄ™ dowiÄ…zaÅ„\n" #: .././db/check.c:1409 #, c-format msgid "inode %lld name %s\n" msgstr "i-wÄ™zeÅ‚ %lld o nazwie %s\n" #: .././db/check.c:1443 .././db/check.c:1458 #, c-format msgid "block %u/%u out of range\n" msgstr "blok %u/%u poza zakresem\n" #: .././db/check.c:1446 .././db/check.c:1461 #, c-format msgid "blocks %u/%u..%u out of range\n" msgstr "bloki %u/%u..%u poza zakresem\n" #: .././db/check.c:1484 #, c-format msgid "rtblock %llu expected type %s got %s\n" msgstr "rtblok %llu - oczekiwano typu %s, otrzymano %s\n" #: .././db/check.c:1504 #, c-format msgid "rtblocks %llu..%llu claimed by inode %lld\n" msgstr "rtbloki %llu..%llu przypisane do i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:1513 #, c-format msgid "rtblock %llu claimed by inode %lld, previous inum %lld\n" msgstr "rtblok %llu przypisany do i-wÄ™złą %lld, poprzedni inum %lld\n" #: .././db/check.c:1531 #, c-format msgid "root inode %lld is missing\n" msgstr "brak głównego i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:1536 #, c-format msgid "root inode %lld is not a directory\n" msgstr "główny i-wÄ™zeÅ‚ %lld nie jest katalogiem\n" #: .././db/check.c:1552 #, c-format msgid "rtblock %llu out of range\n" msgstr "rtblok %llu poza zakresem\n" #: .././db/check.c:1596 #, c-format msgid "blocks %u/%u..%u claimed by block %u/%u\n" msgstr "bloki %u/%u..%u przypisane do bloku %u/%u\n" #: .././db/check.c:1610 #, c-format msgid "setting block %u/%u to %s\n" msgstr "ustawianie bloku %u/%u na %s\n" #: .././db/check.c:1633 #, c-format msgid "setting rtblock %llu to %s\n" msgstr "ustawianie rtbloku %llu na %s\n" #: .././db/check.c:1654 .././repair/rt.c:151 #, c-format msgid "rt summary mismatch, size %d block %llu, file: %d, computed: %d\n" msgstr "" "opis rt nie zgadza siÄ™, rozmiar %d bloku %llu, plik: %d, obliczono: %d\n" #: .././db/check.c:1679 #, c-format msgid "block %u/%u type %s not expected\n" msgstr "blok %u/%u typu %s nie oczekiwany\n" #: .././db/check.c:1700 #, c-format msgid "rtblock %llu type %s not expected\n" msgstr "rtblok %llu typu %s nie oczekiwany\n" #: .././db/check.c:1737 #, c-format msgid "dir ino %lld missing leaf entry for %x/%x\n" msgstr "i-wÄ™zeÅ‚ katalogu %lld - brak wpisu liÅ›cia dla %x/%x\n" #: .././db/check.c:1856 #, c-format msgid "bad superblock magic number %x, giving up\n" msgstr "błędna liczba magiczna superbloku %x, poddajÄ™ siÄ™\n" #: .././db/check.c:1910 msgid "bad option for blockget command\n" msgstr "błędna opcja dla polecenia blockget\n" #: .././db/check.c:1997 #, c-format msgid "bad option -%c for ncheck command\n" msgstr "błędna opcja -%c dla polecenia ncheck\n" #: .././db/check.c:2071 #, c-format msgid "block 0 for directory inode %lld is missing\n" msgstr "brak bloku 0 dla i-wÄ™zÅ‚a katalogu %lld\n" #: .././db/check.c:2091 #, c-format msgid "can't read block 0 for directory inode %lld\n" msgstr "nie można odczytać bloku 0 dla i-wÄ™zÅ‚a katalogu %lld\n" #: .././db/check.c:2137 #, c-format msgid "inode %lld extent [%lld,%lld,%lld,%d]\n" msgstr "ekstent i-wÄ™zÅ‚a %lld [%lld,%lld,%lld,%d]\n" #: .././db/check.c:2140 #, c-format msgid "bmap rec out of order, inode %lld entry %d\n" msgstr "błędna kolejność bmap rec - i-wÄ™zeÅ‚ %lld, wpis %d\n" #: .././db/check.c:2146 #, c-format msgid "inode %lld bad rt block number %lld, offset %lld\n" msgstr "i-wÄ™zeÅ‚ %lld - błędny numer bloku rt %lld, offset %lld\n" #: .././db/check.c:2156 .././db/check.c:2162 #, c-format msgid "inode %lld bad block number %lld [%d,%d], offset %lld\n" msgstr "i-wÄ™zeÅ‚ %lld - błędny numer bloku %lld [%d,%d], offset %lld\n" #: .././db/check.c:2180 .././db/check.c:2194 #, c-format msgid "inode %lld block %lld at offset %lld\n" msgstr "i-wÄ™zeÅ‚ %lld: blok %lld pod offsetem %lld\n" #: .././db/check.c:2221 #, c-format msgid "level for ino %lld %s fork bmap root too large (%u)\n" msgstr "i-wÄ™zeÅ‚ %lld: poziom bmap root odgałęzienia %s zbyt duży (%u)\n" #: .././db/check.c:2233 #, c-format msgid "numrecs for ino %lld %s fork bmap root too large (%u)\n" msgstr "" "i-wÄ™zeÅ‚ %lld: liczba rekordów bmap root odgałęzienia %s zbyt duża (%u)\n" #: .././db/check.c:2260 #, c-format msgid "extent count for ino %lld %s fork too low (%d) for file format\n" msgstr "" "i-wÄ™zeÅ‚ %lld: liczba ekstentów dla odgałęzienia %s zbyt maÅ‚a (%d) dla " "formatu pliku\n" #: .././db/check.c:2312 .././db/check.c:3338 #, c-format msgid "bad directory data magic # %#x for dir ino %lld block %d\n" msgstr "" "błędna liczba magiczna danych katalogu %#x dla i-wÄ™zÅ‚a katalogu %lld, blok " "%d\n" #: .././db/check.c:2330 #, c-format msgid "bad block directory tail for dir ino %lld\n" msgstr "błędny koniec katalogu bloku dla i-wÄ™zÅ‚a katalogu %lld\n" #: .././db/check.c:2375 #, c-format msgid "dir %lld block %d bad free entry at %d\n" msgstr "katalog %lld, blok %d: błędny wolny wpis pod %d\n" #: .././db/check.c:2399 #, c-format msgid "dir %lld block %d zero length entry at %d\n" msgstr "katalog %lld, blok %d: wpis zerowej dÅ‚ugoÅ›ci pod %d\n" #: .././db/check.c:2408 #, c-format msgid "dir %lld block %d bad entry at %d\n" msgstr "katalog %lld, blok %d: błędny wpis pod %d\n" #: .././db/check.c:2426 #, c-format msgid "dir %lld block %d entry %*.*s %lld\n" msgstr "katalog %lld, blok %d, wpis %*.*s %lld\n" #: .././db/check.c:2433 #, c-format msgid "dir %lld block %d entry %*.*s bad inode number %lld\n" msgstr "katalog %lld, blokd %d, epis %*.*s: błędny number i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2443 #, c-format msgid "multiple .. entries in dir %lld (%lld, %lld)\n" msgstr "wiele wpisów .. w katalogu %lld (%lld, %lld)\n" #: .././db/check.c:2460 #, c-format msgid "dir %lld entry . inode number mismatch (%lld)\n" msgstr "katalog %lld, wpis .: niezgodność numeru i-wÄ™zÅ‚a (%lld)\n" #: .././db/check.c:2474 #, c-format msgid "dir %lld block %d bad count %u\n" msgstr "katalog %lld, blok %d: błędny licznik %u\n" #: .././db/check.c:2485 .././db/check.c:3352 #, c-format msgid "dir %lld block %d extra leaf entry %x %x\n" msgstr "katalog %lld, blok %d: nadmiarowy wpis liÅ›cia %x %x\n" #: .././db/check.c:2497 #, c-format msgid "dir %lld block %d bad bestfree data\n" msgstr "katalog %lld, blok %d: błędne dane bestfree\n" #: .././db/check.c:2505 #, c-format msgid "dir %lld block %d bad block tail count %d (stale %d)\n" msgstr "katalog %lld, blok %d: błędny licznik koÅ„ca bloku %d (stale %d)\n" #: .././db/check.c:2515 #, c-format msgid "dir %lld block %d bad stale tail count %d\n" msgstr "katalog %lld, blok %d: błędny licznik koÅ„ca stale %d\n" #: .././db/check.c:2521 #, c-format msgid "dir %lld block %d consecutive free entries\n" msgstr "katalog %lld, blok %d: kolejne wolne wpisy\n" #: .././db/check.c:2527 #, c-format msgid "dir %lld block %d entry/unused tag mismatch\n" msgstr "katalog %lld, blok %d: niezgodność znacznika wpis/nieużywany\n" #: .././db/check.c:2576 #, c-format msgid "no . entry for directory %lld\n" msgstr "brak wpisu . dla katalogu %lld\n" #: .././db/check.c:2581 #, c-format msgid "no .. entry for directory %lld\n" msgstr "brak wpisu .. dla katalogu %lld\n" #: .././db/check.c:2585 #, c-format msgid ". and .. same for non-root directory %lld\n" msgstr ". i .. sÄ… takie same dla katalogu %lld (nie bÄ™dÄ…cego głównym)\n" #: .././db/check.c:2590 #, c-format msgid "root directory %lld has .. %lld\n" msgstr "główny katalog %lld ma .. %lld\n" #: .././db/check.c:2623 #, c-format msgid "bad size (%lld) or format (%d) for directory inode %lld\n" msgstr "błędny rozmiar (%lld) lub format (%d) dla i-wÄ™zÅ‚a katalogu %lld\n" #: .././db/check.c:2651 #, c-format msgid "bad number of extents %d for inode %lld\n" msgstr "błędna liczba ekstentów %d dla i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2723 #, c-format msgid "bad magic number %#x for inode %lld\n" msgstr "błędna liczba magiczna %#x dla i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2730 #, c-format msgid "bad version number %#x for inode %lld\n" msgstr "błędny numer wersji %#x dla i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2738 #, c-format msgid "bad nblocks %lld for free inode %lld\n" msgstr "błędna liczba bloków %lld dla wolnego i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2745 #, c-format msgid "bad nlink %d for free inode %lld\n" msgstr "błądna liczba dowiÄ…zaÅ„ %d dla wolnego i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2751 #, c-format msgid "bad mode %#o for free inode %lld\n" msgstr "błędne uprawnienia %#o dla wolnego i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2760 #, c-format msgid "bad next unlinked %#x for inode %lld\n" msgstr "błędny nastÄ™pny niedowiÄ…zany %#x dla i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2771 #, c-format msgid "bad format %d for inode %lld type %#o\n" msgstr "błędny format %d dla i-wÄ™zÅ‚a %lld typu %#o\n" #: .././db/check.c:2779 #, c-format msgid "bad fork offset %d for inode %lld\n" msgstr "błędny offset odgałęzienia %d dla i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2786 #, c-format msgid "bad attribute format %d for inode %lld\n" msgstr "błędny format atrybutu %d dla i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:2792 #, c-format msgid "" "inode %lld mode %#o fmt %s afmt %s nex %d anex %d nblk %lld sz %lld%s%s%s%s%s" "%s%s\n" msgstr "" "i-wÄ™zeÅ‚ %lld mode %#o fmt %s afmt %s nex %d anex %d nblk %lld sz %lld%s%s%s%s" "%s%s%s\n" #: .././db/check.c:2911 #, c-format msgid "bad nblocks %lld for inode %lld, counted %lld\n" msgstr "błędna liczba bloków %lld dla i-wÄ™zÅ‚a %lld, naliczono %lld\n" #: .././db/check.c:2918 #, c-format msgid "bad nextents %d for inode %lld, counted %d\n" msgstr "błędna liczba ekstentów %d dla i-wÄ™zÅ‚a %lld, naliczono %d\n" #: .././db/check.c:2924 #, c-format msgid "bad anextents %d for inode %lld, counted %d\n" msgstr "błędne anextents %d dla i-wÄ™zÅ‚a %lld, naliczono %d\n" #: .././db/check.c:2976 #, c-format msgid "local inode %lld data is too large (size %lld)\n" msgstr "dane lokalnego i-wÄ™zÅ‚a %lld zbyt duże (rozmiar %lld)\n" #: .././db/check.c:2985 #, c-format msgid "local inode %lld attr is too large (size %d)\n" msgstr "atrybuty lokalnego i-wÄ™zÅ‚a %lld zbyt duże (rozmiar %d)\n" #: .././db/check.c:3034 #, c-format msgid "dir inode %lld block %u=%llu\n" msgstr "i-wÄ™zeÅ‚ katalogu %lld, blok %u=%llu\n" #: .././db/check.c:3046 #, c-format msgid "can't read block %u for directory inode %lld\n" msgstr "nie można odczytać bloku %u dla i-wÄ™zÅ‚a katalogu %lld\n" #: .././db/check.c:3060 #, c-format msgid "multiple .. entries in dir %lld\n" msgstr "wiele wpisów .. w katalogu %lld\n" #: .././db/check.c:3082 #, c-format msgid "missing free index for data block %d in dir ino %lld\n" msgstr "" "brak indeksu wolnego miejsca dla bloku danych %d w i-węźle katalogu %lld\n" #: .././db/check.c:3110 .././db/check.c:3188 #, c-format msgid "bad free block firstdb %d for dir ino %lld block %d\n" msgstr "błędne firstdb wolnego bloku %d dla i-wÄ™zÅ‚a katalogu %lld, blok %d\n" #: .././db/check.c:3121 .././db/check.c:3201 #, c-format msgid "bad free block nvalid/nused %d/%d for dir ino %lld block %d\n" msgstr "" "błędne liczby nvalid/nused (%d/%d) wolnych bloków w i-węźle katalogu %lld, " "blok %d\n" #: .././db/check.c:3135 .././db/check.c:3215 #, c-format msgid "bad free block ent %d is %d should be %d for dir ino %lld block %d\n" msgstr "" "błędna liczba ent %d (równa %d, powinna być %d) wolnego bloku w i-węźle " "katalogu %lld, blok %d\n" #: .././db/check.c:3149 .././db/check.c:3229 #, c-format msgid "bad free block nused %d should be %d for dir ino %lld block %d\n" msgstr "" "błędna liczba nused (%d, powinna być %d) wolnego bloku w i-węźle katalogu " "%lld, blok %d\n" #: .././db/check.c:3174 #, c-format msgid "bad free block magic # %#x for dir ino %lld block %d\n" msgstr "" "błędna liczba magiczna wolnego bloku %#x dla i-wÄ™zÅ‚a katalogu %lld, blok %d\n" #: .././db/check.c:3283 #, c-format msgid "bad leaf block forw/back pointers %d/%d for dir ino %lld block %d\n" msgstr "" "błędne wskaźniki przód/tyÅ‚ (%d/%d) bloku liÅ›cia w i-węźle katalogu %lld, " "blok %d\n" #: .././db/check.c:3292 #, c-format msgid "single leaf block for dir ino %lld block %d should be at block %d\n" msgstr "" "blok pojedynczego liÅ›cia dla i-wÄ™zÅ‚u katalogu %lld, blok %d powinien być w " "bloku %d\n" #: .././db/check.c:3304 #, c-format msgid "bestfree %d for dir ino %lld block %d doesn't match table value %d\n" msgstr "" "bestfree %d dla i-wÄ™zÅ‚a katalogu %lld, blok %d nie zgadza siÄ™ z wartoÅ›ciÄ… w " "tablicy %d\n" #: .././db/check.c:3329 #, c-format msgid "bad node block level %d for dir ino %lld block %d\n" msgstr "błędny poziom bloku wÄ™zÅ‚a %d dla i-wÄ™zÅ‚a katalogu %lld, blok %d\n" #: .././db/check.c:3361 #, fuzzy, c-format msgid "dir3 %lld block %d stale mismatch %d/%d\n" msgstr "katalog %lld, blok %d: niezgodność liczby stale %d/%d\n" #: .././db/check.c:3368 #, c-format msgid "dir %lld block %d stale mismatch %d/%d\n" msgstr "katalog %lld, blok %d: niezgodność liczby stale %d/%d\n" #: .././db/check.c:3424 #, c-format msgid "can't read block %lld for %s quota inode (fsblock %lld)\n" msgstr "nie można odczytać bloku %lld i-wÄ™zÅ‚a limitów %s (blok fs %lld)\n" #: .././db/check.c:3434 #, c-format msgid "%s dqblk %lld entry %d id %u bc %lld ic %lld rc %lld\n" msgstr "%s dqblk %lld wpis %d id %u bc %lld ic %lld rc %lld\n" #: .././db/check.c:3442 #, c-format msgid "bad magic number %#x for %s dqblk %lld entry %d id %u\n" msgstr "błędna liczba magiczna %#x dla dqblk %s %lld, wpis %d, id %u\n" #: .././db/check.c:3451 #, c-format msgid "bad version number %#x for %s dqblk %lld entry %d id %u\n" msgstr "błędny numer wersji %#x dla dqblk %s %lld, wpis %d, id %u\n" #: .././db/check.c:3461 #, c-format msgid "bad flags %#x for %s dqblk %lld entry %d id %u\n" msgstr "błędne flagi %#x dla dqblk %s %lld, wpis %d, id %u\n" #: .././db/check.c:3470 #, c-format msgid "bad id %u for %s dqblk %lld entry %d id %u\n" msgstr "błędne id %u dla dqblk %s %lld, wpis %d, id %u\n" #: .././db/check.c:3516 #, c-format msgid "block %lld for rtbitmap inode is missing\n" msgstr "brak bloku %lld dla i-wÄ™zÅ‚a rtbitmapy\n" #: .././db/check.c:3527 #, c-format msgid "can't read block %lld for rtbitmap inode\n" msgstr "nie można odczytać bloku %lld dla i-wÄ™zÅ‚a rtbitmapy\n" #: .././db/check.c:3583 #, c-format msgid "block %lld for rtsummary inode is missing\n" msgstr "brak bloku %lld dla i-wÄ™zÅ‚a rtsummary\n" #: .././db/check.c:3594 #, c-format msgid "can't read block %lld for rtsummary inode\n" msgstr "nie można odczytać bloku %lld dla i-wÄ™zÅ‚a rtsummary\n" #: .././db/check.c:3627 #, c-format msgid "dir %lld entry . %lld\n" msgstr "katalog %lld, wpis . %lld\n" #: .././db/check.c:3635 #, c-format msgid "dir %llu bad size in entry at %d\n" msgstr "katalog %llu: błędny rozmiar we wpisie przy %d\n" #: .././db/check.c:3647 #, c-format msgid "dir %lld entry %*.*s bad inode number %lld\n" msgstr "katalog %lld wpis %*.*s: błędny numer i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:3659 #, c-format msgid "dir %lld entry %*.*s offset %d %lld\n" msgstr "katalog %lld wpis %*.*s offset %d %lld\n" #: .././db/check.c:3664 #, c-format msgid "dir %lld entry %*.*s bad offset %d\n" msgstr "katalog %lld wpis %*.*s błędny offset %d\n" #: .././db/check.c:3677 #, c-format msgid "dir %llu size is %lld, should be %u\n" msgstr "katalog %llu: rozmiar %lld, powinien być %u\n" #: .././db/check.c:3685 #, c-format msgid "dir %llu offsets too high\n" msgstr "katalog %llu: offsety zbyt duże\n" #: .././db/check.c:3696 #, c-format msgid "dir %lld entry .. bad inode number %lld\n" msgstr "katalog %lld wpis .. - błędny numer i-wÄ™zÅ‚a %lld\n" #: .././db/check.c:3701 #, c-format msgid "dir %lld entry .. %lld\n" msgstr "katalog %lld wpis .. %lld\n" #: .././db/check.c:3704 #, c-format msgid "dir %lld i8count mismatch is %d should be %d\n" msgstr "katalog %lld: niezgodność i8count: jest %d, powinno być %d\n" #: .././db/check.c:3786 #, c-format msgid "%s quota id %u, have/exp" msgstr "limit %s id %u: jest/exp" #: .././db/check.c:3789 #, c-format msgid " bc %lld/%lld" msgstr " bc %lld/%lld" #: .././db/check.c:3793 #, c-format msgid " ic %lld/%lld" msgstr " ic %lld/%lld" #: .././db/check.c:3797 #, c-format msgid " rc %lld/%lld" msgstr " rc %lld/%lld" #: .././db/check.c:3853 #, c-format msgid "can't read superblock for ag %u\n" msgstr "nie można odczytać superbloku dla ag %u\n" #: .././db/check.c:3862 #, c-format msgid "bad sb magic # %#x in ag %u\n" msgstr "błędna liczba magiczna %#x superbloku w ag %u\n" #: .././db/check.c:3868 #, c-format msgid "bad sb version # %#x in ag %u\n" msgstr "błędny numer wersji %#x superbloku w ag %u\n" #: .././db/check.c:3878 .././db/sb.c:217 msgid "mkfs not completed successfully\n" msgstr "mkfs nie zakoÅ„czony pomyÅ›lnie\n" #: .././db/check.c:3890 .././db/frag.c:370 #, c-format msgid "can't read agf block for ag %u\n" msgstr "nie można odczytać bloku agf dla ag %u\n" #: .././db/check.c:3896 #, c-format msgid "bad agf magic # %#x in ag %u\n" msgstr "błędna liczba magiczna agf %#x w ag %u\n" #: .././db/check.c:3902 #, c-format msgid "bad agf version # %#x in ag %u\n" msgstr "błędny numer wersji agf %#x w ag %u\n" #: .././db/check.c:3918 .././db/frag.c:379 #, c-format msgid "can't read agi block for ag %u\n" msgstr "nie można odczytać bloku agi w ag %u\n" #: .././db/check.c:3924 #, c-format msgid "bad agi magic # %#x in ag %u\n" msgstr "błędna liczba magiczna agi %#x w ag %u\n" #: .././db/check.c:3930 #, c-format msgid "bad agi version # %#x in ag %u\n" msgstr "błędny numer wersji agi # %#x w ag %u\n" #: .././db/check.c:3973 .././repair/scan.c:2252 #, c-format msgid "agf_freeblks %u, counted %u in ag %u\n" msgstr "agf_freeblks %u, naliczono %u w ag %u\n" #: .././db/check.c:3980 .././repair/scan.c:2257 #, c-format msgid "agf_longest %u, counted %u in ag %u\n" msgstr "agf_longest %u, naliczono %u w ag %u\n" #: .././db/check.c:3988 #, c-format msgid "agf_btreeblks %u, counted %u in ag %u\n" msgstr "agf_btreeblks %u, naliczono %u w ag %u\n" #: .././db/check.c:3996 .././repair/scan.c:2306 #, c-format msgid "agi_count %u, counted %u in ag %u\n" msgstr "agi_count %u, naliczono %u w ag %u\n" #: .././db/check.c:4003 .././repair/scan.c:2311 #, c-format msgid "agi_freecount %u, counted %u in ag %u\n" msgstr "agi_freecount %u, naliczono %u w ag %u\n" #: .././db/check.c:4012 #, c-format msgid "agi unlinked bucket %d is %u in ag %u (inode=%lld)\n" msgstr "agi unlinked bucket %d is %u in ag %u (inode=%lld)\n" #: .././db/check.c:4050 #, c-format msgid "can't read agfl block for ag %u\n" msgstr "nie można odczytać bloku agfl dla ag %u\n" #: .././db/check.c:4060 .././db/freesp.c:255 .././repair/scan.c:2142 #, c-format msgid "agf %d freelist blocks bad, skipping freelist scan\n" msgstr "" "błędne bloki listy wolnych agf %d, pominiÄ™to przeszukanie listy wolnych\n" #: .././db/check.c:4082 #, c-format msgid "freeblk count %u != flcount %u in ag %u\n" msgstr "liczba freeblk %u != flcount %u w ag %u\n" #: .././db/check.c:4111 .././db/check.c:4139 .././db/frag.c:402 #: .././db/frag.c:425 .././db/freesp.c:289 #, c-format msgid "can't read btree block %u/%u\n" msgstr "nie można odczytać bloku b-drzewa %u/%u\n" #: .././db/check.c:4173 #, c-format msgid "bad magic # %#x in inode %lld bmbt block %u/%u\n" msgstr "błędna liczba magiczna %#x w i-węźle %lld, blok bmbt %u/%u\n" #: .././db/check.c:4180 #, c-format msgid "expected level %d got %d in inode %lld bmbt block %u/%u\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w i-węźle %lld, blok bmbt %u/%u\n" #: .././db/check.c:4192 .././db/check.c:4209 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in inode %lld bmap block %lld\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w i-węźle %lld, blok " "bitmapy %lld\n" #: .././db/check.c:4238 #, c-format msgid "bad magic # %#x in btbno block %u/%u\n" msgstr "błędna liczba magiczna %#x w bloku btbno %u/%u\n" #: .././db/check.c:4247 #, c-format msgid "expected level %d got %d in btbno block %u/%u\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku btbno %u/%u\n" #: .././db/check.c:4256 .././db/check.c:4284 .././db/check.c:4330 #: .././db/check.c:4361 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in btbno block %u/%u\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w bloku btbno %u/%u\n" #: .././db/check.c:4271 .././repair/scan.c:666 #, c-format msgid "out-of-order bno btree record %d (%u %u) block %u/%u\n" msgstr "rekord b-drzewa bno poza kolejnoÅ›ciÄ…: %d (%u %u), blok %u/%u\n" #: .././db/check.c:4312 #, c-format msgid "bad magic # %#x in btcnt block %u/%u\n" msgstr "błędna liczba magiczna %#x w bloku btcbt %u/%u\n" #: .././db/check.c:4321 #, c-format msgid "expected level %d got %d in btcnt block %u/%u\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku btcnt %u/%u\n" #: .././db/check.c:4349 .././repair/scan.c:678 #, c-format msgid "out-of-order cnt btree record %d (%u %u) block %u/%u\n" msgstr "rekord b-drzewa cnt poza kolejnoÅ›ciÄ…: %d (%u %u), blok %u/%u\n" #: .././db/check.c:4407 #, c-format msgid "bad magic # %#x in inobt block %u/%u\n" msgstr "błędna liczba magiczna %#x w bloku inobt %u/%u\n" #: .././db/check.c:4414 #, c-format msgid "expected level %d got %d in inobt block %u/%u\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku inobt %u/%u\n" #: .././db/check.c:4423 .././db/check.c:4509 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in inobt block %u/%u\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w bloku inobt %u/%u\n" #: .././db/check.c:4466 .././db/frag.c:494 #, c-format msgid "can't read inode block %u/%u\n" msgstr "nie można odczytać bloku i-wÄ™zÅ‚a %u/%u\n" #: .././db/check.c:4497 #, c-format msgid "ir_freecount/free mismatch, inode chunk %u/%u, freecount %d nfree %d\n" msgstr "" "niezgodność ir_freecount/free, porcja i-wÄ™złów %u/%u, freecount %d nfree %d\n" #: .././db/check.c:4550 #, fuzzy, c-format msgid "bad magic # %#x in finobt block %u/%u\n" msgstr "błędna liczba magiczna %#x w bloku inobt %u/%u\n" #: .././db/check.c:4557 #, fuzzy, c-format msgid "expected level %d got %d in finobt block %u/%u\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku inobt %u/%u\n" #: .././db/check.c:4566 .././db/check.c:4609 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in finobt block %u/%u\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w bloku inobt %u/%u\n" #: .././db/check.c:4636 #, fuzzy, c-format msgid "bad magic # %#x in rmapbt block %u/%u\n" msgstr "błędna liczba magiczna %#x w bloku inobt %u/%u\n" #: .././db/check.c:4643 #, fuzzy, c-format msgid "expected level %d got %d in rmapbt block %u/%u\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku inobt %u/%u\n" #: .././db/check.c:4656 .././db/check.c:4680 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in rmapbt block %u/%u\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w bt%s, blok %u/%u\n" #: .././db/check.c:4668 #, fuzzy, c-format msgid "out-of-order rmap btree record %d (%u %u) block %u/%u\n" msgstr "rekord b-drzewa bno poza kolejnoÅ›ciÄ…: %d (%u %u), blok %u/%u\n" #: .././db/check.c:4708 #, fuzzy, c-format msgid "bad magic # %#x in refcntbt block %u/%u\n" msgstr "błędna liczba magiczna %#x w bloku inobt %u/%u\n" #: .././db/check.c:4715 #, fuzzy, c-format msgid "expected level %d got %d in refcntbt block %u/%u\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku inobt %u/%u\n" #: .././db/check.c:4724 .././db/check.c:4765 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in refcntbt block %u/%u\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w bloku inobt %u/%u\n" #: .././db/check.c:4736 .././repair/scan.c:1350 #, c-format msgid "leftover CoW extent (%u/%u) len %u\n" msgstr "" #: .././db/check.c:4752 #, fuzzy, c-format msgid "out-of-order refcnt btree record %d (%u %u) block %u/%u\n" msgstr "rekord b-drzewa cnt poza kolejnoÅ›ciÄ…: %d (%u %u), blok %u/%u\n" #: .././db/check.c:4808 #, c-format msgid "setting inode to %lld for block %u/%u\n" msgstr "ustawianie i-wÄ™zÅ‚a na %lld dla bloku %u/%u\n" #: .././db/check.c:4840 #, c-format msgid "setting inode to %lld for rtblock %llu\n" msgstr "ustawianie i-wÄ™zÅ‚a na %lld dla rtbloku %llu\n" #: .././db/check.c:4856 #, c-format msgid "inode %lld nlink %u %s dir\n" msgstr "i-wÄ™zeÅ‚ %lld nlink %u katalog %s\n" #: .././db/command.c:85 .././db/help.c:56 .././libxcmd/help.c:50 #, c-format msgid "command %s not found\n" msgstr "nie znaleziono polecenia %s\n" #: .././db/command.c:89 #, c-format msgid "bad argument count %d to %s, expected " msgstr "błędny argument liczby %d dla %s, oczekiwano " #: .././db/command.c:91 #, c-format msgid "at least %d" msgstr "przynajmniej %d" #: .././db/command.c:95 #, c-format msgid "between %d and %d" msgstr "od %d do %d" #: .././db/command.c:96 msgid " arguments\n" msgstr " argumentów\n" #: .././db/convert.c:171 #, c-format msgid "bad argument count %d to convert, expected 3,5,7,9 arguments\n" msgstr "" "błędna liczba argumentów %d do konwersji, oczekiwano 3,5,7,9 argumentów\n" #: .././db/convert.c:176 .././db/convert.c:183 #, c-format msgid "unknown conversion type %s\n" msgstr "nieznany rodzaj konwersji %s\n" #: .././db/convert.c:187 msgid "result type same as argument\n" msgstr "typ wyniku taki sam jak argument\n" #: .././db/convert.c:191 #, c-format msgid "conflicting conversion type %s\n" msgstr "konflikt typu konwersji %s\n" #: .././db/convert.c:269 #, c-format msgid "%s is not a number\n" msgstr "%s nie jest liczbÄ…\n" #: .././db/crc.c:37 msgid "manipulate crc values for V5 filesystem structures" msgstr "" #: .././db/crc.c:50 msgid "" "\n" " 'crc' validates, invalidates, or recalculates the crc value for\n" " the current on-disk metadata structures in Version 5 filesystems.\n" "\n" " Usage: \"crc [-i|-r|-v]\"\n" "\n" msgstr "" #: .././db/crc.c:81 #, fuzzy, c-format msgid "current type (%s) is not a structure\n" msgstr "bieżący typ nie jest i-wÄ™zÅ‚em\n" #: .././db/crc.c:98 #, fuzzy msgid "bad option for crc command\n" msgstr "błędna opcja dla polecenia frag\n" #: .././db/crc.c:105 msgid "crc command accepts only one option\n" msgstr "" #: .././db/crc.c:111 #, fuzzy, c-format msgid "%s not in expert mode, writing disabled\n" msgstr "%s: nie w trybie expert, zapis wyłączony\n" #: .././db/crc.c:128 #, fuzzy, c-format msgid "No CRC field found for type %s\n" msgstr "brak pól dla typu %s\n" #: .././db/crc.c:135 .././db/write.c:693 msgid "parsing error\n" msgstr "błąd skÅ‚adni\n" #: .././db/crc.c:171 msgid "Invalidating CRC:\n" msgstr "" #: .././db/crc.c:173 msgid "Recalculating CRC:\n" msgstr "" #: .././db/crc.c:181 msgid "Verifying CRC:\n" msgstr "" #: .././db/debug.c:27 msgid "[flagbits]" msgstr "[bity flag]" #: .././db/debug.c:28 msgid "set debug option bits" msgstr "ustawienie bitów opcji diagnostycznych" #: .././db/debug.c:42 #, c-format msgid "bad value for debug %s\n" msgstr "błędna wartość diagnostyki %s\n" #: .././db/dir2.c:1023 msgid "Unknown directory buffer type!\n" msgstr "Nieznany typ bufora katalogu!\n" #: .././db/dir2.c:1035 msgid "Writing unknown directory buffer type!\n" msgstr "Zapis nieznanego typu bufora katalogu!\n" #: .././db/dquot.c:37 msgid "[-g|-p|-u] id" msgstr "" #: .././db/dquot.c:38 #, fuzzy msgid "" "set current address to a group, project or user quota block for given ID" msgstr "" "ustawienie bieżącego adresu na blok limitu projektu, grupy lub użytkownika" #: .././db/dquot.c:129 msgid "bad option for dquot command\n" msgstr "błędna opcja dla polecenia dquot\n" #: .././db/dquot.c:133 msgid "project" msgstr "projekt" #: .././db/dquot.c:133 msgid "group" msgstr "grupÄ™" #: .././db/dquot.c:133 msgid "user" msgstr "użytkownika" #: .././db/dquot.c:135 #, c-format msgid "dquot command requires one %s id argument\n" msgstr "polecenie dquot wymaga jednego argumentu identyfikujÄ…cego %s\n" #: .././db/dquot.c:145 #, c-format msgid "no %s quota inode present\n" msgstr "i-wÄ™zeÅ‚ limitów na %s nie jest dostÄ™pny\n" #: .././db/dquot.c:150 #, c-format msgid "bad %s id for dquot %s\n" msgstr "błędna liczba identyfikujÄ…ca %s dla dquot %s\n" #: .././db/dquot.c:162 #, c-format msgid "no %s quota data for id %d\n" msgstr "brak danych limitów na %s dla id %d\n" #: .././db/echo.c:27 msgid "[args]..." msgstr "[argumenty]..." #: .././db/echo.c:28 msgid "echo arguments" msgstr "wypisanie argumentów" #: .././db/faddr.c:40 .././db/faddr.c:63 msgid "no current allocation group, cannot set new addr\n" msgstr "brak bieżącej grupy alokacji, nie można ustawić nowego adresu\n" #: .././db/faddr.c:45 .././db/faddr.c:117 .././db/faddr.c:148 #: .././db/faddr.c:180 .././db/faddr.c:202 .././db/faddr.c:232 #: .././db/faddr.c:262 .././db/faddr.c:316 .././db/faddr.c:335 msgid "null block number, cannot set new addr\n" msgstr "pusty numer bloku, nie można ustawić nowego adresu\n" #: .././db/faddr.c:68 .././db/faddr.c:353 .././db/faddr.c:370 #: .././db/faddr.c:387 msgid "null inode number, cannot set new addr\n" msgstr "pusty numer i-wÄ™zÅ‚a, nie można ustawić nowego adresu\n" #: .././db/faddr.c:88 msgid "null attribute block number, cannot set new addr\n" msgstr "pusty number bloku atrybutów, nie można ustawić nowego adresu\n" #: .././db/faddr.c:94 msgid "attribute block is unmapped\n" msgstr "blok atrybutów jest nieodwzorowany\n" #: .././db/faddr.c:123 .././db/faddr.c:155 .././db/faddr.c:208 #: .././db/faddr.c:239 msgid "file block is unmapped\n" msgstr "blok pliku jest nieodwzorowany\n" #: .././db/faddr.c:285 msgid "null directory block number, cannot set new addr\n" msgstr "pusty numer bloku katalogu, nie można ustawić nowego adresu\n" #: .././db/faddr.c:292 msgid "directory block is unmapped\n" msgstr "blok katalogu jest nieodwzorowany\n" #: .././db/flist.c:149 #, c-format msgid "field %s not found\n" msgstr "nie znaleziono pola %s\n" #: .././db/flist.c:159 #, c-format msgid "no elements in %s\n" msgstr "brak elementów w %s\n" #: .././db/flist.c:165 #, c-format msgid "indices %d-%d for field %s out of range %d-%d\n" msgstr "indeksy %d-%d dla pola %s sÄ… poza zakresem %d-%d\n" #: .././db/flist.c:173 #, c-format msgid "index %d for field %s out of range %d-%d\n" msgstr "indeks %d dla pola %s jest poza zakresem %d-%d\n" #: .././db/flist.c:187 #, c-format msgid "field %s is not an array\n" msgstr "pole %s nie jest tablicÄ…\n" #: .././db/flist.c:200 #, c-format msgid "field %s has no subfields\n" msgstr "pole %s nie ma podpól\n" #: .././db/flist.c:220 #, c-format msgid "fl@%p:\n" msgstr "fl@%p:\n" #: .././db/flist.c:221 #, c-format msgid "\tname=%s, fld=%p, child=%p, sibling=%p\n" msgstr "\tnazwa=%s, fld=%p, child=%p, sibling=%p\n" #: .././db/flist.c:223 #, c-format msgid "\tlow=%d, high=%d, flags=%d (%s%s), offset=%d\n" msgstr "\tlow=%d, high=%d, flagi=%d (%s%s), offset=%d\n" #: .././db/flist.c:225 msgid "oklow " msgstr "oklow " #: .././db/flist.c:226 msgid "okhigh" msgstr "okhigh" #: .././db/flist.c:227 #, c-format msgid "\tfld->name=%s, fld->ftyp=%d (%s)\n" msgstr "\tfld->name=%s, fld->ftyp=%d (%s)\n" #: .././db/flist.c:230 #, c-format msgid "\tfld->flags=%d (%s%s%s%s%s)\n" msgstr "\tfld->flags=%d (%s%s%s%s%s)\n" #: .././db/flist.c:322 #, c-format msgid "bad syntax in field name %s\n" msgstr "błędna skÅ‚adnia w nazwie pola %s\n" #: .././db/flist.c:378 #, c-format msgid "missing closing quote %s\n" msgstr "brak cudzysÅ‚owu zamykajÄ…cego %s\n" #: .././db/flist.c:395 #, c-format msgid "bad character in field %s\n" msgstr "błędny znak w polu %s\n" #: .././db/fprint.c:99 msgid "null" msgstr "nic" #: .././db/frag.c:173 #, c-format msgid "actual %llu, ideal %llu, fragmentation factor %.2f%%\n" msgstr "obecnie %llu, idealnie %llu, współczynnik fragmentacji %.2f%%\n" #: .././db/frag.c:175 msgid "Note, this number is largely meaningless.\n" msgstr "" #: .././db/frag.c:177 #, fuzzy, c-format msgid "Files on this filesystem average %.2f extents per file\n" msgstr "statystyki dla systemu plików aktualnie otwartego pliku" #: .././db/frag.c:218 msgid "bad option for frag command\n" msgstr "błędna opcja dla polecenia frag\n" #: .././db/frag.c:354 #, c-format msgid "inode %lld actual %lld ideal %lld\n" msgstr "i-wÄ™zeÅ‚ %lld obecnie %lld idealnie %lld\n" #: .././db/frag.c:448 .././db/frag.c:458 #, c-format msgid "invalid numrecs (%u) in %s block\n" msgstr "błędne numrecs (%u) w bloku %s\n" #: .././db/freesp.c:110 #, c-format msgid "total free extents %lld\n" msgstr "razem wolnych ekstentów: %lld\n" #: .././db/freesp.c:111 #, c-format msgid "total free blocks %lld\n" msgstr "razem wolnych bloków: %lld\n" #: .././db/freesp.c:112 #, c-format msgid "average free extent size %g\n" msgstr "Å›redni rozmiar wolnego ekstentu: %g\n" #: .././db/freesp.c:203 msgid "" "freesp arguments: [-bcds] [-a agno] [-e binsize] [-h h1]... [-m binmult]\n" msgstr "" "argumenty freesp: [-bcds] [-a agno] [-e binsize] [-h h1]... [-m binmult]\n" #: .././db/freesp.c:427 msgid "from" msgstr "od" #: .././db/freesp.c:427 msgid "to" msgstr "do" #: .././db/freesp.c:427 .././repair/progress.c:26 msgid "extents" msgstr "ekstentów" #: .././db/freesp.c:427 .././repair/progress.c:18 msgid "blocks" msgstr "bloków" #: .././db/freesp.c:427 msgid "pct" msgstr "proc." #: .././db/fsmap.c:39 #, c-format msgid "" "%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n" msgstr "" #: .././db/fsmap.c:86 #, c-format msgid "Error %d while reading AGF.\n" msgstr "" #: .././db/fsmap.c:93 #, fuzzy msgid "Not enough memory.\n" msgstr "%s: brak pamiÄ™ci\n" #: .././db/fsmap.c:103 #, c-format msgid "Error %d while querying fsmap btree.\n" msgstr "" #: .././db/fsmap.c:127 msgid "Filesystem does not support reverse mapping btree.\n" msgstr "" #: .././db/fsmap.c:134 #, fuzzy msgid "Bad option for fsmap command.\n" msgstr "błędna opcja dla polecenia bmap\n" #: .././db/fsmap.c:142 #, c-format msgid "Bad fsmap start_fsb %s.\n" msgstr "" #: .././db/fsmap.c:150 #, c-format msgid "Bad fsmap end_fsb %s.\n" msgstr "" #: .././db/fsmap.c:162 msgid "[start_fsb] [end_fsb]" msgstr "" #: .././db/fsmap.c:163 msgid "display reverse mapping(s)" msgstr "" #: .././db/hash.c:30 msgid "string" msgstr "Å‚aÅ„cuch" #: .././db/hash.c:31 msgid "calculate hash value" msgstr "obliczenie wartoÅ›ci skrótu" #: .././db/hash.c:37 msgid "" "\n" " 'hash' prints out the calculated hash value for a string using the\n" "directory/attribute code hash function.\n" "\n" " Usage: \"hash \"\n" "\n" msgstr "" "\n" " 'hash' wypisuje wartość skrótu dla Å‚aÅ„cucha obliczonÄ… przy użyciu funkcji\n" " haszujÄ…cej dla katalogów/atrybutów.\n" "\n" " SkÅ‚adnia: \"hash <Å‚aÅ„cuch>\"\n" "\n" #: .././db/help.c:30 .././db/io.c:49 .././libxcmd/help.c:93 msgid "[command]" msgstr "[polecenie]" #: .././db/help.c:31 .././libxcmd/help.c:94 msgid "help for one or all commands" msgstr "opis dla jednego lub wszystkich poleceÅ„" #: .././db/help.c:40 .././libxcmd/help.c:34 #, c-format msgid "" "\n" "Use 'help commandname' for extended help.\n" msgstr "" "\n" "Rozszerzony opis można uzyskać przez 'help nazwa_polecenia'.\n" #: .././db/help.c:89 #, c-format msgid "(or %s) " msgstr "(lub %s) " #: .././db/init.c:49 #, c-format msgid "Usage: %s [-ifFrxV] [-p prog] [-l logdev] [-c cmd]... device\n" msgstr "" "SkÅ‚adnia: %s [-ifFrxV] [-p prog] [-l urz-log] [-c polecenie]... urzÄ…dzenie\n" #: .././db/init.c:116 msgid "" "\n" "fatal error -- couldn't initialize XFS library\n" msgstr "" "\n" "błąd krytyczny - nie udaÅ‚o siÄ™ zainicjować biblioteki XFS\n" #: .././db/init.c:131 #, c-format msgid "%s: %s is invalid (cannot read first 512 bytes)\n" msgstr "%s: %s jest nieprawidÅ‚owy (nie można odczytać pierwszych 512 bajtów)\n" #: .././db/init.c:143 #, c-format msgid "" "%s: %s is not a valid XFS filesystem (unexpected SB magic number 0x%08x)\n" msgstr "" "%s: %s nie jest poprawnym systemem plików XFS (nieoczekiwana liczba magiczna " "SB 0x%08x)\n" #: .././db/init.c:146 #, c-format msgid "Use -F to force a read attempt.\n" msgstr "Opcja -F pozwala wymusić próbÄ™ odczytu.\n" #: .././db/init.c:155 #, c-format msgid "%s: device %s unusable (not an XFS filesystem?)\n" msgstr "" "%s: urzÄ…dzenie %s nie nadaje siÄ™ do użycia (to nie jest system plików XFS?)\n" #: .././db/init.c:170 #, c-format msgid "%s: cannot init perag data (%d). Continuing anyway.\n" msgstr "" "%s: nie można zainicjować danych perag (%d). Kontynuacja mimo wszystko.\n" #: .././db/inode.c:419 #, c-format msgid "bad value for inode number %s\n" msgstr "błędna wartość numeru i-wÄ™zÅ‚a %s\n" #: .././db/inode.c:426 #, c-format msgid "current inode number is %lld\n" msgstr "numer bieżącego i-wÄ™zÅ‚a to %lld\n" #: .././db/inode.c:660 #, c-format msgid "bad inode number %lld\n" msgstr "błędny numer i-wÄ™zÅ‚a %lld\n" #: .././db/inode.c:707 #, fuzzy, c-format msgid "Metadata CRC error detected for ino %lld\n" msgstr "błędna liczba ekstentów %d dla i-wÄ™zÅ‚a %lld\n" #: .././db/input.c:43 msgid "source-file" msgstr "plik-źródÅ‚owy" #: .././db/input.c:44 msgid "get commands from source-file" msgstr "odczyt poleceÅ„ z pliku-źródÅ‚owego" #: .././db/input.c:320 #, c-format msgid "can't open %s\n" msgstr "nie można otworzyć %s\n" #: .././db/io.c:47 msgid "pop location from the stack" msgstr "odtworzenie pozycji ze stosu" #: .././db/io.c:50 msgid "push location to the stack" msgstr "zapisanie pozycji na stos" #: .././db/io.c:53 msgid "view the location stack" msgstr "podejrzenie stosu pozycji" #: .././db/io.c:56 msgid "move forward to next entry in the position ring" msgstr "przejÅ›cie na nastÄ™pnÄ… pozycjÄ™ w krÄ™gu" #: .././db/io.c:59 msgid "move to the previous location in the position ring" msgstr "przejÅ›cie na poprzedniÄ… pozycjÄ™ w krÄ™gu" #: .././db/io.c:62 msgid "show position ring or move to a specific entry" msgstr "pokazanie krÄ™gu pozycji lub przejÅ›cie do okreÅ›lonego wpisu" #: .././db/io.c:92 #, c-format msgid "can't set block offset to %d\n" msgstr "nie można ustawić offsetu bloku na %d\n" #: .././db/io.c:105 msgid "can't pop anything from I/O stack\n" msgstr "nie można pobrać nic ze stosu we/wy\n" #: .././db/io.c:139 msgid "" "\n" " Changes the address and data type to the first entry on the stack.\n" "\n" msgstr "" "\n" " Zmiana adresu i typu danych na pierwszy wpis ze stosu.\n" "\n" #: .././db/io.c:153 #, c-format msgid "\tbyte offset %lld, length %d\n" msgstr "\toffset w bajtach %lld, dÅ‚ugość %d\n" #: .././db/io.c:154 #, c-format msgid "\tbuffer block %lld (fsbno %lld), %d bb%s\n" msgstr "\tblok bufora %lld (fsbno %lld), %d bb%s\n" #: .././db/io.c:158 .././db/io.c:544 #, c-format msgid "\tblock map" msgstr "\tmapa bloków" #: .././db/io.c:164 #, c-format msgid "\tinode %lld, dir inode %lld, type %s\n" msgstr "\ti-wÄ™zeÅ‚ %lld, i-wÄ™zeÅ‚ katalogu %lld, typ %s\n" #: .././db/io.c:165 .././growfs/xfs_growfs.c:88 .././logprint/log_misc.c:107 #: .././mkfs/xfs_mkfs.c:2366 #, c-format msgid "none" msgstr "brak" #: .././db/io.c:175 msgid "no entries in location ring.\n" msgstr "brak wpisów w krÄ™gu pozycji.\n" #: .././db/io.c:179 msgid " type bblock bblen fsbno inode\n" msgstr " typ bblok bblen fsbno i-wÄ™zeÅ‚\n" #: .././db/io.c:233 #, c-format msgid "no such command %s\n" msgstr "nieznane polecenie %s\n" #: .././db/io.c:237 #, c-format msgid "no push form allowed for %s\n" msgstr "forma push niedozwolona dla %s\n" #: .././db/io.c:261 msgid "" "\n" " Allows you to push the current address and data type on the stack for\n" " later return. 'push' also accepts an additional command to execute after\n" " storing the current address (ex: 'push a rootino' from the superblock).\n" "\n" msgstr "" "\n" " Pozwala zapisać bieżący adres i typ danych na stos w celu późniejszego\n" " powrotu. 'push' akceptuje także dodatkowe polecenie do wykonania po " "zapisaniu\n" " bieżącego adresu (np. 'push a rootino' z superbloku).\n" "\n" #: .././db/io.c:277 .././db/io.c:317 msgid "ring is empty\n" msgstr "krÄ…g jest pusty\n" #: .././db/io.c:281 msgid "no further entries\n" msgstr "brak dalszych wpisów\n" #: .././db/io.c:300 msgid "" "\n" " The 'forward' ('f') command moves to the next location in the position\n" " ring, updating the current position and data type. If the current " "location\n" " is the top entry in the ring, then the 'forward' command will have\n" " no effect.\n" "\n" msgstr "" "\n" " Polecenie 'forward' ('f') przechodzi do nastÄ™pnej pozycji w krÄ™gu,\n" " uaktualniajÄ…c bieżącÄ… pozycjÄ™ i typ danych. JeÅ›li bieżąca pozycja\n" " jest szczytowym wpisem w krÄ™gu, polecenie nie przyniesie efektu.\n" "\n" #: .././db/io.c:321 msgid "no previous entries\n" msgstr "brak poprzednich wpisów\n" #: .././db/io.c:340 msgid "" "\n" " The 'back' ('b') command moves to the previous location in the position\n" " ring, updating the current position and data type. If the current " "location\n" " is the last entry in the ring, then the 'back' command will have no " "effect.\n" "\n" msgstr "" "\n" " Polecenie 'back' ('b') przechodzi do poprzedniej pozycji w krÄ™gu,\n" " uaktualniajÄ…c bieżącÄ… pozycjÄ™ i typ danych. JeÅ›li bieżąca pozycja\n" " jest ostatnim wpisem w krÄ™gu, polecenie nie przyniesie efektu.\n" "\n" #: .././db/io.c:363 #, c-format msgid "invalid entry: %d\n" msgstr "błędny wpis: %d\n" #: .././db/io.c:382 #, c-format msgid "" "\n" " The position ring automatically keeps track of each disk location and\n" " structure type for each change of position you make during your xfs_db\n" " session. The last %d most recent entries are kept in the ring.\n" "\n" " To display the current list of ring entries type 'ring' by itself on\n" " the command line. The entry highlighted by an asterisk ('*') is the\n" " current entry.\n" "\n" " To move to another entry in the ring type 'ring ' where is\n" " your desired entry from the ring position list.\n" "\n" " You may also use the 'forward' ('f') or 'back' ('b') commands to move\n" " to the previous or next entry in the ring, respectively.\n" "\n" " Note: Unlike the 'stack', 'push' and 'pop' commands, the ring tracks your\n" " location implicitly. Use the 'push' and 'pop' commands if you wish to\n" " store a specific location explicitly for later return.\n" "\n" msgstr "" "\n" " KrÄ…g pozycji automatycznie Å›ledzi każde poÅ‚ożenie na dysku i typ struktury\n" " dla każdej zmiany pozycji wykonywanej podczas sesji xfs_db. Ostatenie %d\n" " pozycji jest trzymane w krÄ™gu.\n" "\n" " Aby wyÅ›wietlić bieżącÄ… listÄ™ wpisów w krÄ™gu należy napisać w linii poleceÅ„\n" " po prostu 'ring'. Wpis oznaczony gwiazdkÄ… ('*') jest wpisem bieżącym.\n" "\n" " Aby przejść do innego wpisu w krÄ™gu, należy wpisać 'ring ', gdzie\n" " jest numerem pożądanego wpisu na liÅ›cie pozycji.\n" "\n" " Można także używać poleceÅ„ 'forward' ('f') i 'back' ('b'), aby przenieść\n" " siÄ™ odpowiednio na poprzedni lub nastÄ™pny wpis w krÄ™gu.\n" "\n" " Uwaga: w przeciwieÅ„stwie do poleceÅ„ 'stack', 'push' i 'pop', krÄ…g Å›ledzi\n" " pozycje niejawnie. Aby zapisać jawnie dane poÅ‚ożenie w celu późniejszego\n" " powrotu, należy użyć poleceÅ„ 'push' i 'pop'.\n" "\n" #: .././db/io.c:435 .././db/io.c:451 #, c-format msgid "write error: %s\n" msgstr "błąd zapisu: %s\n" #: .././db/io.c:441 .././db/io.c:457 #, c-format msgid "read error: %s\n" msgstr "błąd odczytu: %s\n" #: .././db/io.c:480 msgid "nothing to write\n" msgstr "nie ma nic do zapisania\n" #: .././db/io.c:529 msgid "set_cur no stack element to set\n" msgstr "set_cur: brak elementu stosu do ustawienia\n" #: .././db/io.c:543 #, c-format msgid "xfs_db got a bbmap for %lld\n" msgstr "xfs_db ma bbmap dla %lld\n" #: .././db/io.c:619 msgid "" "\n" " The stack is used to explicitly store your location and data type\n" " for later return. The 'push' operation stores the current address\n" " and type on the stack, the 'pop' operation returns you to the\n" " position and datatype of the top entry on the stack.\n" "\n" " The 'stack' allows explicit location saves, see 'ring' for implicit\n" " position tracking.\n" "\n" msgstr "" "\n" " Stos sÅ‚uży do jawnego zapisania pozycji i typu danych w celu późniejszego\n" " powrotu. Operacja 'push' zapisuje bieżący adres i typ na stosie, a " "operacja\n" " 'pop' odtwarza bieżący adres i typ danych z wierzchu stosu.\n" "\n" " Stos ('stack') pozwala na jawne zapisywanie pozycji; domyÅ›lnie pozycje sÄ…\n" " Å›ledzone poprzez krÄ…g (p. 'ring').\n" "\n" #: .././db/logformat.c:89 msgid "The log is dirty. Please mount to replay the log.\n" msgstr "" #: .././db/logformat.c:121 msgid "" "\n" " The 'logformat' command reformats (clears) the log to the specified log\n" " cycle and log stripe unit. If the log cycle is not specified, the log is\n" " reformatted to the current cycle. If the log stripe unit is not specified,\n" " the stripe unit from the filesystem superblock is used.\n" "\n" msgstr "" #: .././db/logformat.c:137 msgid "[-c cycle] [-s sunit]" msgstr "" #: .././db/logformat.c:138 msgid "reformat the log" msgstr "" #: .././db/malloc.c:27 #, c-format msgid "%s: out of memory\n" msgstr "%s: brak pamiÄ™ci\n" #: .././db/metadump.c:60 #, fuzzy msgid "[-a] [-e] [-g] [-m max_extent] [-w] [-o] filename" msgstr "[-e] [-g] [-m max_extent] [-w] [-o] nazwa-pliku" #: .././db/metadump.c:61 msgid "dump metadata to a file" msgstr "zrzut metadanych do pliku" #: .././db/metadump.c:92 #, fuzzy, c-format msgid "" "\n" " The 'metadump' command dumps the known metadata to a compact file suitable\n" " for compressing and sending to an XFS maintainer for corruption analysis \n" " or xfs_repair failures.\n" "\n" " Options:\n" " -a -- Copy full metadata blocks without zeroing unused space\n" " -e -- Ignore read errors and keep going\n" " -g -- Display dump progress\n" " -m -- Specify max extent size in blocks to copy (default = %d blocks)\n" " -o -- Don't obfuscate names and extended attributes\n" " -w -- Show warnings of bad metadata information\n" "\n" msgstr "" "\n" " Polecenie 'metadump' zrzuca znane metadane do zwiÄ™zÅ‚ego pliku nadajÄ…cego " "siÄ™\n" " do skompresowania i wysÅ‚ania prowadzÄ…cym projekt XFS w celu analizy " "uszkodzeÅ„\n" " lub błędów xfs_repair.\n" "\n" " Opcje:\n" " -e - ignorowanie błędów odczytu i kontynuowanie\n" " -g - wyÅ›wietlanie postÄ™pu\n" " -m - okreÅ›lenie maksymalnego rozmiaru ekstentu (w blokach) do " "skopiowania\n" " (domyÅ›lnie %d bloków)\n" " -o - bez zaciemniania nazw i rozszerzonych atrybutów\n" " -w - wyÅ›wietlanie ostrzeżeÅ„ o błędnych metadanych\n" "\n" #: .././db/metadump.c:2728 msgid "" "Filesystem log is dirty; image will contain unobfuscated metadata in log." msgstr "" #: .././db/metadump.c:2734 msgid "Could not discern log; image will contain unobfuscated metadata in log." msgstr "" #: .././db/output.c:30 msgid "[stop|start ]" msgstr "[stop|start ]" #: .././db/output.c:31 msgid "start or stop logging to a file" msgstr "rozpoczÄ™cie lub zakoÅ„czenie logowania do pliku" #: .././db/output.c:68 #, c-format msgid "logging to %s\n" msgstr "logowanie do %s\n" #: .././db/output.c:70 .././db/output.c:77 msgid "no log file\n" msgstr "brak pliku logu\n" #: .././db/output.c:80 #, c-format msgid "already logging to %s\n" msgstr "już ustawiono logowanie do %s\n" #: .././db/output.c:84 #, c-format msgid "can't open %s for writing\n" msgstr "nie można otworzyć %s do zapisu\n" #: .././db/output.c:90 msgid "bad log command, ignored\n" msgstr "błędne polecenie logowania, zignorowano\n" #: .././db/print.c:41 msgid "[value]..." msgstr "[wartość]..." #: .././db/print.c:42 msgid "print field values" msgstr "wypisanie wartoÅ›ci pól" #: .././db/print.c:79 #, c-format msgid "no print function for type %s\n" msgstr "brak funkcji wypisujÄ…cej dla typu %s\n" #: .././db/print.c:156 msgid "(empty)\n" msgstr "(puste)\n" #: .././db/print.c:218 msgid "(empty)" msgstr "(puste)" #: .././db/print.c:278 msgid "no arguments allowed\n" msgstr "argumenty nie sÄ… dozwolone\n" #: .././db/quit.c:27 msgid "exit xfs_db" msgstr "zakoÅ„czenie xfs_db" #: .././db/sb.c:45 msgid "set current address to sb header" msgstr "ustawienie bieżącego adresu na nagłówek sb" #: .././db/sb.c:47 msgid "[uuid]" msgstr "[uuid]" #: .././db/sb.c:48 msgid "write/print FS uuid" msgstr "zapisanie/wypisanie uuida FS" #: .././db/sb.c:50 msgid "[label]" msgstr "[etykieta]" #: .././db/sb.c:51 msgid "write/print FS label" msgstr "zapisanie/wypisanie etykiety FS" #: .././db/sb.c:53 msgid "[feature | [vnum fnum]]" msgstr "[cecha | [vnum fnum]]" #: .././db/sb.c:54 msgid "set feature bit(s) in the sb version field" msgstr "ustawienie bitów cech w polu wersji sb" #: .././db/sb.c:140 msgid "" "\n" " set allocation group superblock\n" "\n" " Example:\n" "\n" " 'sb 7' - set location to 7th allocation group superblock, set type to 'sb'\n" "\n" " Located in the first sector of each allocation group, the superblock\n" " contains the base information for the filesystem.\n" " The superblock in allocation group 0 is the primary. The copies in the\n" " remaining allocation groups only serve as backup for filesystem recovery.\n" " The icount/ifree/fdblocks/frextents are only updated in superblock 0.\n" "\n" msgstr "" "\n" " ustawienie superbloku grupy alokacji\n" "\n" " PrzykÅ‚ad:\n" "\n" " 'sb 7' - ustawienie pozycji na superblok 7. grupy alokacji i typu na 'sb'\n" "\n" " PoÅ‚ożony w 1. sektorze każdej grupy alokacji superblok zawiera podstawowe\n" " informacje o systemie plików.\n" " Superblok w grupie alokacji 0 jest główny. Kopie w pozostaÅ‚ych grupach\n" " alokacji sÅ‚użą tylko jako kopie zapasowe do odtwarzania systemu plików.\n" " Liczby icount/ifree/fdblocks/frextents sÄ… uaktualniane tylko w superbloku " "0.\n" "\n" #: .././db/sb.c:199 #, c-format msgid "can't read superblock for AG %u\n" msgstr "nie można odczytać superbloku dla AG %u\n" #: .././db/sb.c:207 #, c-format msgid "bad sb magic # %#x in AG %u\n" msgstr "błędna liczba magiczna superbloku %#x w AG %u\n" #: .././db/sb.c:212 #, c-format msgid "bad sb version # %#x in AG %u\n" msgstr "błędny numer wersji superbloku %#x w AG %u\n" #: .././db/sb.c:236 msgid "aborting - external log specified for FS with an internal log\n" msgstr "" "przerwano - podano log zewnÄ™trzny dla systemu plików z logiem wewnÄ™trznym\n" #: .././db/sb.c:242 msgid "aborting - no external log specified for FS with an external log\n" msgstr "" "przerwano - nie podano logu zewnÄ™trznego dla systemu plików z logiem " "zewnÄ™trznym\n" #: .././db/sb.c:252 msgid "ERROR: cannot find log head/tail, run xfs_repair\n" msgstr "" "BÅÄ„D: nie odnaleziono poczÄ…tku/koÅ„ca logu, proszÄ™ uruchomić xfs_repair\n" #: .././db/sb.c:256 #, c-format msgid "" "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running %s. If you are unable to mount the filesystem, then use\n" "the xfs_repair -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n" msgstr "" "BÅÄ„D: system plików zawiera wartoÅ›ciowe zmiany metadanych w logu, który\n" "musi być odtworzony. Należy podmontować system plików, aby odtworzyć log,\n" "a nastÄ™pnie odmontować go przed ponownym uruchomieniem %s. JeÅ›li\n" "systemu plików nie da siÄ™ podmontować, można użyć opcji -L, aby zniszczyć\n" "log i spróbować naprawić system plików.\n" "Należy zauważyć, że zniszczenie logu może spowodować uszkodzenia danych -\n" "proszÄ™ najpierw spróbować podmontować system plików.\n" #: .././db/sb.c:284 msgid "Clearing log and setting UUID\n" msgstr "Czyszczenei logu i ustawianie UUID-a\n" #: .././db/sb.c:293 msgid "ERROR: cannot clear the log\n" msgstr "BÅÄ„D: nie można wyczyÅ›cić logu\n" #: .././db/sb.c:305 msgid "" "\n" " write/print FS uuid\n" "\n" " Example:\n" "\n" " 'uuid' - print UUID\n" " 'uuid 01234567-0123-0123-0123-0123456789ab' - write UUID\n" " 'uuid generate' - generate and write\n" " 'uuid rewrite' - copy UUID from SB 0\n" "\n" "The print function checks the UUID in each SB and will warn if the UUIDs\n" "differ between AGs (the log is not checked). The write commands will\n" "set the uuid in all AGs to either a specified value, a newly generated\n" "value or the value found in the first superblock (SB 0) respectively.\n" "As a side effect of writing the UUID, the log is cleared (which is fine\n" "on a CLEANLY unmounted FS).\n" "\n" msgstr "" "\n" " zapisanie/wypisanie uuida systemu plików\n" "\n" "PrzykÅ‚ad:\n" "\n" " 'uuid' - wypisanie UUID-a\n" " 'uuid 01234567-0123-0123-0123-0123456789ab' - zapisanie UUID-a\n" " 'uuid generate' - wygenerowanie i zapisanie\n" " 'uuid rewrite' - skopiowanie UUID-a z sb 0\n" "\n" "Funkcja wypisujÄ…ca sprawdza UUID w każdym superbloku i ostrzega, jeÅ›li UUID-" "y\n" "siÄ™ różniÄ… miÄ™dzy AG (log nie jest sprawdzany). Polecenia zapisu ustawiajÄ…\n" "UUID we wszystkich AG odpowiednio na okreÅ›lonÄ… wartość, nowo wygenerowanÄ…\n" "wartość lub wartość znalezionÄ… w pierwszym superbloku (SB 0).\n" "Jako efekt uboczny zapisu UUID-a czyszczony jest log (co nie jest problemem\n" "przy CZYSTO odmontowanym systemie plików).\n" "\n" #: .././db/sb.c:383 .././db/sb.c:546 msgid "invalid parameters\n" msgstr "błędne parametry\n" #: .././db/sb.c:390 .././db/sb.c:553 .././db/sb.c:720 #, c-format msgid "%s: not in expert mode, writing disabled\n" msgstr "%s: nie w trybie expert, zapis wyłączony\n" #: .././db/sb.c:402 msgid "failed to read UUID from AG 0\n" msgstr "nie udaÅ‚o siÄ™ odczytać UUID-a z AG 0\n" #: .././db/sb.c:407 #, c-format msgid "old UUID = %s\n" msgstr "stary UUID = %s\n" #: .././db/sb.c:421 msgid "invalid UUID\n" msgstr "błędny UUID\n" #: .././db/sb.c:430 .././db/sb.c:558 .././db/sb.c:806 msgid "writing all SBs\n" msgstr "zapisywanie wszystkich superbloków\n" #: .././db/sb.c:433 #, c-format msgid "failed to set UUID in AG %d\n" msgstr "nie udaÅ‚o siÄ™ ustawić UUID-a w AG %d\n" #: .././db/sb.c:438 #, c-format msgid "new UUID = %s\n" msgstr "nowy UUID = %s\n" #: .././db/sb.c:446 #, c-format msgid "failed to read UUID from AG %d\n" msgstr "nie udaÅ‚o siÄ™ odczytać UUID-a z AG %d\n" #: .././db/sb.c:452 #, c-format msgid "warning: UUID in AG %d differs to the primary SB\n" msgstr "uwaga: UUID w AG %d różni siÄ™ od głównego SB\n" #: .././db/sb.c:463 msgid "warning - external log specified for FS with an internal log\n" msgstr "uwaga: podano log zewnÄ™trzny dla systemu plików z logiem wewnÄ™trznym\n" #: .././db/sb.c:466 msgid "warning - no external log specified for FS with an external log\n" msgstr "" "uwaga: nie podano logu zewnÄ™trznego dla systemu plików z logiem zewnÄ™trznym\n" #: .././db/sb.c:471 #, c-format msgid "UUID = %s\n" msgstr "UUID = %s\n" #: .././db/sb.c:482 msgid "" "\n" " write/print FS label\n" "\n" " Example:\n" "\n" " 'label' - print label\n" " 'label 123456789012' - write label\n" " 'label --' - write an empty label\n" "\n" "The print function checks the label in each SB and will warn if the labels\n" "differ between AGs. The write commands will set the label in all AGs to the\n" "specified value. The maximum length of a label is 12 characters - use of a\n" "longer label will result in truncation and a warning will be issued.\n" "\n" msgstr "" "\n" " zapisanie/wypisanie etykiety systemu plików\n" "\n" " PrzykÅ‚ad:\n" "\n" " 'label' - wypisanie etykiety\n" " 'label 123456789012' - zapisanie etykiety\n" " 'label --' - zapisanie etykiety pustej\n" "\n" "Funkcja wypisujÄ…ca sprawdza etykietÄ™ w każdym superbloku i ostrzega, jeÅ›li\n" "etykiety różniÄ… siÄ™ miÄ™dzy AG. Polecenia zapisu ustawiajÄ… etykietw we\n" "wszystkich AG na okreÅ›lonÄ… wartość. Maksymalna dÅ‚ugość etykiety to 12 " "znaków;\n" "użycie etykiety dÅ‚uższej zaskutkuje uciÄ™ciem jej i wypisaniem ostrzeżenia.\n" "\n" #: .././db/sb.c:519 #, c-format msgid "%s: truncating label length from %d to %d\n" msgstr "%s: skrócono dÅ‚ugość etykiety z %d do %d\n" #: .././db/sb.c:561 #, c-format msgid "failed to set label in AG %d\n" msgstr "nie udaÅ‚o siÄ™ ustawić etykiety w AG %d\n" #: .././db/sb.c:564 #, c-format msgid "new label = \"%s\"\n" msgstr "nowa etykieta = \"%s\"\n" #: .././db/sb.c:571 #, c-format msgid "failed to read label in AG %d\n" msgstr "nie udaÅ‚o siÄ™ odczytać etykiety w AG %d\n" #: .././db/sb.c:577 #, c-format msgid "warning: AG %d label differs\n" msgstr "uwaga: etykieta w AG %d różni siÄ™\n" #: .././db/sb.c:579 #, c-format msgid "label = \"%s\"\n" msgstr "etykieta = \"%s\"\n" #: .././db/sb.c:589 msgid "" "\n" " set/print feature bits in sb version\n" "\n" " Example:\n" "\n" " 'version' - print current feature bits\n" " 'version extflg' - enable unwritten extents\n" " 'version attr1' - enable v1 inline extended attributes\n" " 'version attr2' - enable v2 inline extended attributes\n" " 'version log2' - enable v2 log format\n" "\n" "The version function prints currently enabled features for a filesystem\n" "according to the version field of its primary superblock.\n" "It can also be used to enable selected features, such as support for\n" "unwritten extents. The updated version is written into all AGs.\n" "\n" msgstr "" "\n" " ustawienie/wypisanie bitów cech w wersji superbloku\n" "\n" " PrzykÅ‚ad:\n" "\n" " 'version' - wypisanie bieżących bitów cech\n" " 'version extflg' - włączenie nie zapisanych ekstentów\n" " 'version attr1' - włączenie rozszerzonych atrybutów inline v1\n" " 'version attr2' - włączenie rozszerzonych atrybutów inline v2\n" " 'version log2' - włączenie formatu logu v2\n" "\n" "Funkcja 'version' wypisuje aktualnie włączone cechy dla systemu plików\n" "zgodnie z polem wersji w głównym superbloku.\n" "Może być używana także do włączania wybranych cech, takich jak obsÅ‚uga\n" "nie zapisanych ekstentów. Uaktualniona wersja jest zapisywana we wszystkich\n" "AG.\n" "\n" #: .././db/sb.c:617 msgid "Superblock has mismatched features2 fields, skipping modification\n" msgstr "Superblok ma niepasujÄ…ce pola features2, pominiÄ™to modyfikacjÄ™\n" #: .././db/sb.c:740 msgid "unwritten extents flag is already enabled\n" msgstr "flaga nie zapisanych ekstentów jest już włączona\n" #: .././db/sb.c:747 msgid "unwritten extents always enabled for v5 superblocks.\n" msgstr "nie zapisane ekstenty sÄ… zawsze włączone dla superbloków v5.\n" #: .././db/sb.c:764 msgid "version 2 log format is already in use\n" msgstr "format logu w wersji 2 jest już w użyciu\n" #: .././db/sb.c:771 msgid "Version 2 logs always enabled for v5 superblocks.\n" msgstr "Logi w wersji 2 sÄ… zawsze włączone dla superbloków v5.\n" #: .././db/sb.c:776 #, c-format msgid "%s: Cannot change %s on v5 superblocks.\n" msgstr "%s: Nie można zmienić %s przy superblokach v5.\n" #: .././db/sb.c:800 #, c-format msgid "%s: invalid version change command \"%s\"\n" msgstr "%s: błędne polecenie zmiany wersji \"%s\"\n" #: .././db/sb.c:809 #, c-format msgid "failed to set versionnum in AG %d\n" msgstr "nie udaÅ‚o siÄ™ ustawić versionnum w AG %d\n" #: .././db/sb.c:827 #, c-format msgid "versionnum [0x%x+0x%x] = %s\n" msgstr "versionnum [0x%x+0x%x] = %s\n" #: .././db/type.c:49 msgid "[newtype]" msgstr "[nowy-typ]" #: .././db/type.c:50 msgid "set/show current data type" msgstr "ustawienie/wyÅ›wietlenie bieżącego typu danych" #: .././db/type.c:210 #, c-format msgid "current type is \"%s\"\n" msgstr "bieżący typ to \"%s\"\n" #: .././db/type.c:212 msgid "" "\n" " supported types are:\n" " " msgstr "" "\n" " obsÅ‚ugiwane typy to:\n" " " #: .././db/type.c:229 #, c-format msgid "no such type %s\n" msgstr "nie ma typu %s\n" #: .././db/type.c:232 msgid "no current object\n" msgstr "brak bieżącego obiektu\n" #: .././db/write.c:41 #, fuzzy msgid "[-c] [field or value]..." msgstr "[pole lub wartość]..." #: .././db/write.c:42 msgid "write value to disk" msgstr "zapis wartoÅ›ci na dysk" #: .././db/write.c:58 #, fuzzy msgid "" "\n" " The 'write' command takes on different personalities depending on the\n" " type of object being worked with.\n" "\n" " Write has 3 modes:\n" " 'struct mode' - is active anytime you're looking at a filesystem object\n" " which contains individual fields (ex: an inode).\n" " 'data mode' - is active anytime you set a disk address directly or set\n" " the type to 'data'.\n" " 'string mode' - only used for writing symlink blocks.\n" "\n" " Examples:\n" " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n" " 'write fname \"hello\\000\"' - write superblock fname.\n" " (note: in struct mode strings are not null terminated)\n" " 'write fname #6669736800' - write superblock fname with " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - write superblock uuid.\n" " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n" " 'write lshift 3' - shift the block 3 bytes to the left\n" " 'write sequence 1 5' - write a cycle of number [1-5] through\n" " the entire block.\n" " String mode: 'write \"This_is_a_filename\" - write null terminated " "string.\n" "\n" " In data mode type 'write' by itself for a list of specific commands.\n" "\n" " Specifying the -c option will allow writes of invalid (corrupt) data with\n" " an invalid CRC. Specifying the -d option will allow writes of invalid " "data,\n" " but still recalculate the CRC so we are forced to check and detect the\n" " invalid data appropriately.\n" "\n" msgstr "" "\n" " Polecenie 'write' ma różne osobowoÅ›ci w zależnoÅ›ci od rodzaju obiektu,\n" " na jakim pracuje.\n" "\n" " Zapis ma trzy tryby:\n" " 'struct' (strukturalny) - aktywny w przypadku oglÄ…dania obiektu systemu\n" " plików zawierajÄ…cego poszczególne pola (np. i-wÄ™zeÅ‚).\n" " 'data' (danych) - aktywny w przypadku bezpoÅ›redniego ustawienia adresu\n" " na dysku lub ustawienia typu na 'data'.\n" " 'string' (znakowy) - używany tylko przy zapisie bloków dowiÄ…zaÅ„\n" " symbolicznych.\n" "\n" " PrzykÅ‚ady:\n" " Tryb strukturalny: 'write core.uid 23' - ustawienie pola uid i-wÄ™zÅ‚a na " "23\n" " 'write fname \"hello\\000\"' - zapis nazwy pliku sb\n" " (uwaga: w trybie strukturalnym Å‚aÅ„cuchy nie sÄ… " "zakaÅ„czane)\n" " 'write fname #6669736800' - zapis nazwy pliku sb w " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - zapis UUID-a superbloku.\n" " Tryb danych: 'write fill 0xff' - wypeÅ‚nienie bloku bajtam 0xff\n" " 'write lshift 3' - przesuniÄ™cie bloku o 3 bajty w lewo\n" " 'write sequence 1 5' zapis cyklicznie liczb [1-5] " "przez\n" " caÅ‚y blok.\n" " Tryb znakowy: 'write \"To_jest_nazwa_pliku\" - zapis Å‚aÅ„cucha\n" " zakoÅ„czonego znakiem NUL.\n" "\n" " W trybie danych samo 'write' wypisze listÄ™ bardziej specyficznych poleceÅ„.\n" "\n" #: .././db/write.c:104 #, c-format msgid "%s started in read only mode, writing disabled\n" msgstr "%s uruchomiono w trybie tylko do odczytu, zapis wyłączony\n" #: .././db/write.c:116 #, c-format msgid "no handler function for type %s, write unsupported.\n" msgstr "brak funkcji obsÅ‚ugujÄ…cej dla typu %s, zapis nie obsÅ‚ugiwany.\n" #: .././db/write.c:130 #, fuzzy msgid "bad option for write command\n" msgstr "błędna opcja dla polecenia frag\n" #: .././db/write.c:136 #, fuzzy msgid "Cannot specify both -c and -d options\n" msgstr "Nie można podać jednoczeÅ›nie -%c %s i %c %s\n" #: .././db/write.c:141 msgid "Cannot recalculate CRCs on this type of object\n" msgstr "" #: .././db/write.c:166 msgid "Allowing write of corrupted data and bad CRC\n" msgstr "" #: .././db/write.c:169 msgid "Allowing write of corrupted data with good CRC\n" msgstr "" #: .././db/write.c:225 .././db/write.c:254 .././db/write.c:284 #: .././db/write.c:317 .././db/write.c:353 .././db/write.c:402 #: .././db/write.c:431 #, c-format msgid "length (%d) too large for data block size (%d)" msgstr "dÅ‚ugość (%d) zbyt duża dla rozmiaru bloku danych (%d)" #: .././db/write.c:673 msgid "usage: write fieldname value\n" msgstr "skÅ‚adnia: write nazwa-pola wartość\n" #: .././db/write.c:679 #, c-format msgid "unable to parse '%s'.\n" msgstr "nie można przeanalizować '%s'.\n" #: .././db/write.c:728 #, c-format msgid "unable to convert value '%s'.\n" msgstr "nie można przekonwertować wartoÅ›ci '%s'.\n" #: .././db/write.c:752 msgid "usage (in string mode): write \"string...\"\n" msgstr "skÅ‚adnia (w trybie znakowym): write \"Å‚aÅ„cuch...\"\n" #: .././db/write.c:794 msgid "write: invalid subcommand\n" msgstr "write: błędne podpolecenie\n" #: .././db/write.c:799 #, c-format msgid "write %s: invalid number of arguments\n" msgstr "write %s: błędna liczba argumentów\n" #: .././db/write.c:823 msgid "usage: write (in data mode)\n" msgstr "skÅ‚adnia: write (w trybie danych)\n" #: .././estimate/xfs_estimate.c:78 #, c-format msgid "" "Usage: %s [opts] directory [directory ...]\n" "\t-b blocksize (fundamental filesystem blocksize)\n" "\t-i logsize (internal log size)\n" "\t-e logsize (external log size)\n" "\t-v prints more verbose messages\n" "\t-V prints version and exits\n" "\t-h prints this usage message\n" "\n" "Note:\tblocksize may have 'k' appended to indicate x1024\n" "\tlogsize may also have 'm' appended to indicate (1024 x 1024)\n" msgstr "" "SkÅ‚adnia: %s [opcje] katalog [katalog ...]\n" "\t-b rozmiar_bloku (rozmiar bloku zasadniczego systemu plików)\n" "\t-i rozmiar_logu (rozmiar logu wewnÄ™trznego)\n" "\t-e rozmiar_logu (rozmiar logu zewnÄ™trznego)\n" "\t-v wypisywanie bardziej szczegółowych komunikatów\n" "\t-V wypisanie informacji o wersji i zakoÅ„czenie\n" "\t-h wypisanie tej informacji o sposobie użycia\n" "\n" #: .././estimate/xfs_estimate.c:109 #, c-format msgid "blocksize %llu too small\n" msgstr "rozmiar bloku %llu jest zbyt maÅ‚y\n" #: .././estimate/xfs_estimate.c:114 #, c-format msgid "blocksize %llu too large\n" msgstr "rozmiar bloku %llu jest zbyt duży\n" #: .././estimate/xfs_estimate.c:121 #, c-format msgid "already have external log noted, can't have both\n" msgstr "już jest przypisany zewnÄ™trzny log, nie mogÄ… istnieć oba\n" #: .././estimate/xfs_estimate.c:130 #, c-format msgid "already have internal log noted, can't have both\n" msgstr "już jest przypisany wewnÄ™trzny log, nie mogÄ… istnieć oba\n" #: .././estimate/xfs_estimate.c:160 #, c-format msgid "" "directory bsize blocks megabytes " "logsize\n" msgstr "" "katalog rozmb bloków megabajtów rozm." "logu\n" #: .././estimate/xfs_estimate.c:174 #, c-format msgid "dirsize=%llu\n" msgstr "dirsize=%llu\n" #: .././estimate/xfs_estimate.c:175 #, c-format msgid "fullblocks=%llu\n" msgstr "fullblocks=%llu\n" #: .././estimate/xfs_estimate.c:176 #, c-format msgid "isize=%llu\n" msgstr "isize=%llu\n" #: .././estimate/xfs_estimate.c:178 #, c-format msgid "%llu regular files\n" msgstr "%llu plików zwykÅ‚ych\n" #: .././estimate/xfs_estimate.c:179 #, c-format msgid "%llu symbolic links\n" msgstr "%llu dowiÄ…zaÅ„ symbolicznych\n" #: .././estimate/xfs_estimate.c:180 #, c-format msgid "%llu directories\n" msgstr "%llu katalogów\n" #: .././estimate/xfs_estimate.c:181 #, c-format msgid "%llu special files\n" msgstr "%llu plików specjalnych\n" #: .././estimate/xfs_estimate.c:194 #, c-format msgid "%s will take about %.1f megabytes\n" msgstr "%s zajmie okoÅ‚o %.1f megabajtów\n" #: .././estimate/xfs_estimate.c:201 #, c-format msgid "%-39s %5llu %8llu %10.1fMB %10llu\n" msgstr "%-39s %5llu %8llu %10.1fMB %10llu\n" #: .././estimate/xfs_estimate.c:207 #, c-format msgid "\twith the external log using %llu blocks " msgstr "\tz zewnÄ™trznym logiem zajmujÄ…cym %llu bloków " #: .././estimate/xfs_estimate.c:209 #, c-format msgid "or about %.1f megabytes\n" msgstr "lub okoÅ‚o %.1f megabajtów\n" #: .././fsr/xfs_fsr.c:268 #, c-format msgid "%s: Stats not yet supported for XFS\n" msgstr "%s: statystyki nie sÄ… jeszcze obsÅ‚ugiwane dla XFS-a\n" #: .././fsr/xfs_fsr.c:332 #, c-format msgid "%s: could not stat: %s: %s\n" msgstr "%s: nie można wykonać stat: %s: %s\n" #: .././fsr/xfs_fsr.c:351 #, c-format msgid "%s: char special not supported: %s\n" msgstr "%s: urzÄ…dzenia znakowe nie sÄ… obsÅ‚ugiwane: %s\n" #: .././fsr/xfs_fsr.c:357 #, c-format msgid "%s: cannot defragment: %s: Not XFS\n" msgstr "%s: nie można zdefragmentować: %s: to nie jest XFS\n" #: .././fsr/xfs_fsr.c:367 #, c-format msgid "%s: not fsys dev, dir, or reg file, ignoring\n" msgstr "" "%s: nie jest urzÄ…dzeniem z systemem plików, katalogiem ani zwykÅ‚ym plikiem, " "zignorowano\n" #: .././fsr/xfs_fsr.c:382 #, c-format msgid "" "Usage: %s [-d] [-v] [-g] [-t time] [-p passes] [-f leftf] [-m mtab]\n" " %s [-d] [-v] [-g] xfsdev | dir | file ...\n" " %s -V\n" "\n" "Options:\n" " -g Print to syslog (default if stdout not a tty).\n" " -t time How long to run in seconds.\n" " -p passes Number of passes before terminating global re-org.\n" " -f leftoff Use this instead of %s.\n" " -m mtab Use something other than /etc/mtab.\n" " -d Debug, print even more.\n" " -v Verbose, more -v's more verbose.\n" " -V Print version number and exit.\n" msgstr "" "SkÅ‚adnia: %s [-d] [-v] [-g] [-t czas] [-p przebiegi] [-f leftf] [-m mtab]\n" " %s [-d] [-v] [-g] xfsdev | katalog | plik ...\n" " %s -V\n" "\n" "Opcje:\n" " -g Pisanie do sysloga (domyÅ›lne jeÅ›li stdout to nie " "tty).\n" " -t czas Czas dziaÅ‚ania w sekundach.\n" " -p przebiegi Liczba przebiegów przed zakoÅ„czeniem reorganizacji.\n" " -f leftoff Użycie tego pliku zamiast %s.\n" " -m mtab Użycie pliku innego niż /etc/mtab.\n" " -d Diagnostyka, dużo wiÄ™cej informacji.\n" " -v Tym wiÄ™cej szczegółów, im wiÄ™cej opcji -v.\n" " -V Wypisanie informacji o wersji i zakoÅ„czenie.\n" #: .././fsr/xfs_fsr.c:412 .././fsr/xfs_fsr.c:450 #, c-format msgid "out of memory: %s\n" msgstr "brak pamiÄ™ci: %s\n" #: .././fsr/xfs_fsr.c:441 #, c-format msgid "Skipping %s: not mounted rw\n" msgstr "PominiÄ™to %s: nie zamontowany rw\n" #: .././fsr/xfs_fsr.c:455 #, c-format msgid "out of memory on realloc: %s\n" msgstr "brak pamiÄ™ci przy realloc: %s\n" #: .././fsr/xfs_fsr.c:466 .././fsr/xfs_fsr.c:470 #, c-format msgid "strdup(%s) failed\n" msgstr "strdup(%s) nie powiodÅ‚o siÄ™\n" #: .././fsr/xfs_fsr.c:481 #, c-format msgid "no rw xfs file systems in mtab: %s\n" msgstr "brak w pliku mtab systemów plików xfs w trybie rw: %s\n" #: .././fsr/xfs_fsr.c:485 #, c-format msgid "Found %d mounted, writable, XFS filesystems\n" msgstr "" "Liczba znalezionych zamontowanych, zapisywalnych systemów plików XFS: %d\n" #: .././fsr/xfs_fsr.c:515 #, c-format msgid "%s: open failed\n" msgstr "%s: open nie powiodÅ‚o siÄ™\n" #: .././fsr/xfs_fsr.c:530 #, c-format msgid "Can't use %s: mode=0%o own=%d nlink=%d\n" msgstr "Nie można użyć %s: mode=0%o own=%d nlink=%d\n" #: .././fsr/xfs_fsr.c:550 #, c-format msgid "could not read %s, starting with %s\n" msgstr "nie można odczytać %s, rozpoczÄ™cie z %s\n" #: .././fsr/xfs_fsr.c:589 #, c-format msgid "START: pass=%d ino=%llu %s %s\n" msgstr "START: przebieg=%d i-wÄ™zeÅ‚=%llu %s %s\n" #: .././fsr/xfs_fsr.c:606 #, c-format msgid "Completed all %d passes\n" msgstr "ZakoÅ„czono wszystkie przebiegi w liczbie %d\n" #: .././fsr/xfs_fsr.c:616 msgid "couldn't fork sub process:" msgstr "nie udaÅ‚o siÄ™ uruchomić podprocesu:" #: .././fsr/xfs_fsr.c:651 #, c-format msgid "%s startpass %d, endpass %d, time %d seconds\n" msgstr "%s pocz. przebieg %d, koÅ„c. przebieg %d, czas %d sekund\n" #: .././fsr/xfs_fsr.c:658 #, c-format msgid "open(%s) failed: %s\n" msgstr "open(%s) nie powiodÅ‚o siÄ™: %s\n" #: .././fsr/xfs_fsr.c:664 #, c-format msgid "write(%s) failed: %s\n" msgstr "write(%s) nie powiodÅ‚o siÄ™: %s\n" #: .././fsr/xfs_fsr.c:688 #, c-format msgid "%s start inode=%llu\n" msgstr "%s pocz. i-wÄ™zeÅ‚=%llu\n" #: .././fsr/xfs_fsr.c:693 #, c-format msgid "unable to get handle: %s: %s\n" msgstr "nie udaÅ‚o siÄ™ uzyskać uchwytu: %s: %s\n" #: .././fsr/xfs_fsr.c:699 #, c-format msgid "unable to open: %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć: %s: %s\n" #: .././fsr/xfs_fsr.c:706 #, c-format msgid "Skipping %s: could not get XFS geometry\n" msgstr "PominiÄ™to %s: nie można odczytać geometrii XFS\n" #: .././fsr/xfs_fsr.c:741 #, c-format msgid "could not open: inode %llu\n" msgstr "nie udaÅ‚o siÄ™ otworzyć: i-wÄ™zeÅ‚ %llu\n" #: .././fsr/xfs_fsr.c:771 #, c-format msgid "%s: xfs_bulkstat: %s\n" msgstr "%s: xfs_bulkstat: %s\n" #: .././fsr/xfs_fsr.c:798 #, c-format msgid "%s: Directory defragmentation not supported\n" msgstr "%s: Defragmentacja katalogów nie jest obsÅ‚ugiwana\n" #: .././fsr/xfs_fsr.c:817 #, c-format msgid "unable to construct sys handle for %s: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć uchwytu systemowego dla %s: %s\n" #: .././fsr/xfs_fsr.c:828 #, c-format msgid "unable to open sys handle for %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć uchwytu systemowego dla %s: %s\n" #: .././fsr/xfs_fsr.c:834 #, c-format msgid "unable to get bstat on %s: %s\n" msgstr "nie udaÅ‚o siÄ™ uzyskać bstat na %s: %s\n" #: .././fsr/xfs_fsr.c:841 #, c-format msgid "unable to open handle %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć uchwytu %s: %s\n" #: .././fsr/xfs_fsr.c:848 #, c-format msgid "Unable to get geom on fs for: %s\n" msgstr "Nie udaÅ‚o siÄ™ odczytać geometrii systemu plików dla: %s\n" #: .././fsr/xfs_fsr.c:899 #, c-format msgid "sync failed: %s: %s\n" msgstr "sync nie powiodÅ‚o siÄ™: %s: %s\n" #: .././fsr/xfs_fsr.c:905 #, c-format msgid "%s: zero size, ignoring\n" msgstr "%s: zerowy rozmiar, zignorowano\n" #: .././fsr/xfs_fsr.c:924 #, c-format msgid "locking check failed: %s\n" msgstr "sprawdzenie blokowania nie powiodÅ‚o siÄ™: %s\n" #: .././fsr/xfs_fsr.c:931 #, c-format msgid "mandatory lock: %s: ignoring\n" msgstr "obowiÄ…zkowa blokada: %s: zignorowano\n" #: .././fsr/xfs_fsr.c:944 #, c-format msgid "unable to get fs stat on %s: %s\n" msgstr "nie udaÅ‚o siÄ™ uzyskać stat fs na %s: %s\n" #: .././fsr/xfs_fsr.c:951 #, c-format msgid "insufficient freespace for: %s: size=%lld: ignoring\n" msgstr "niewystarczajÄ…ca ilość miejsca dla: %s: rozmiar=%lld: zignorowano\n" #: .././fsr/xfs_fsr.c:958 #, c-format msgid "failed to get inode attrs: %s\n" msgstr "nie udaÅ‚o siÄ™ uzyskać atrybutów i-wÄ™zÅ‚a: %s\n" #: .././fsr/xfs_fsr.c:963 #, c-format msgid "%s: immutable/append, ignoring\n" msgstr "%s: niezmienny/tylko do dołączania, zignorowano\n" #: .././fsr/xfs_fsr.c:968 #, c-format msgid "%s: marked as don't defrag, ignoring\n" msgstr "%s: oznaczony jako nie do defragmentacji, zignorowano\n" #: .././fsr/xfs_fsr.c:974 #, c-format msgid "cannot get realtime geometry for: %s\n" msgstr "nie można uzyskać geometrii realtime dla: %s\n" #: .././fsr/xfs_fsr.c:979 #, c-format msgid "low on realtime free space: %s: ignoring file\n" msgstr "maÅ‚o wolnego miejsca realtime: %s: plik zignorowany\n" #: .././fsr/xfs_fsr.c:986 #, c-format msgid "cannot open: %s: Permission denied\n" msgstr "nie można otworzyć: %s: brak uprawnieÅ„\n" #: .././fsr/xfs_fsr.c:1045 .././fsr/xfs_fsr.c:1095 .././fsr/xfs_fsr.c:1175 msgid "could not set ATTR\n" msgstr "nie udaÅ‚o siÄ™ ustawić ATTR\n" #: .././fsr/xfs_fsr.c:1054 #, c-format msgid "unable to stat temp file: %s\n" msgstr "nie udaÅ‚o siÄ™ wykonać stat na pliku tymczasowym: %s\n" #: .././fsr/xfs_fsr.c:1072 #, c-format msgid "unable to get bstat on temp file: %s\n" msgstr "nie udaÅ‚o siÄ™ uzyskać bstat pliku tymczasowego: %s\n" #: .././fsr/xfs_fsr.c:1077 #, c-format msgid "orig forkoff %d, temp forkoff %d\n" msgstr "orig forkoff %d, temp forkoff %d\n" #: .././fsr/xfs_fsr.c:1130 msgid "big ATTR set failed\n" msgstr "duży zbiór ATTR nie powiódÅ‚ siÄ™\n" #: .././fsr/xfs_fsr.c:1151 #, c-format msgid "forkoff diff %d too large!\n" msgstr "różnica forkoff %d zbyt duża!\n" #: .././fsr/xfs_fsr.c:1168 #, c-format msgid "data fork growth unimplemented\n" msgstr "powiÄ™kszanie odgałęzienia danych nie jest zaimplementowane\n" #: .././fsr/xfs_fsr.c:1183 msgid "set temp attr\n" msgstr "ustawianie atrybutów pliku tymczasowego\n" #: .././fsr/xfs_fsr.c:1186 msgid "failed to match fork offset\n" msgstr "nie udaÅ‚o siÄ™ dopasować offsetu odgałęzienia\n" #: .././fsr/xfs_fsr.c:1233 #, c-format msgid "%s already fully defragmented.\n" msgstr "%s jest już caÅ‚kowicie zdefragmentowany.\n" #: .././fsr/xfs_fsr.c:1239 #, c-format msgid "%s extents=%d can_save=%d tmp=%s\n" msgstr "%s extents=%d can_save=%d tmp=%s\n" #: .././fsr/xfs_fsr.c:1245 #, c-format msgid "could not open tmp file: %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć pliku tymczasowego: %s: %s\n" #: .././fsr/xfs_fsr.c:1253 #, c-format msgid "failed to set ATTR fork on tmp: %s:\n" msgstr "nie udaÅ‚o siÄ™ ustawić odgałęzienia ATTR na tmp: %s\n" #: .././fsr/xfs_fsr.c:1260 #, c-format msgid "could not set inode attrs on tmp: %s\n" msgstr "nie udaÅ‚o siÄ™ ustawić atrybutów i-wÄ™zÅ‚a na tmp: %s\n" #: .././fsr/xfs_fsr.c:1267 #, c-format msgid "could not get DirectIO info on tmp: %s\n" msgstr "nie udaÅ‚o siÄ™ uzyskać informacji o bezpoÅ›rednim we/wy na tmp: %s\n" #: .././fsr/xfs_fsr.c:1282 #, c-format msgid "DEBUG: fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n" msgstr "DEBUG: fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n" #: .././fsr/xfs_fsr.c:1289 #, c-format msgid "could not allocate buf: %s\n" msgstr "nie udaÅ‚o siÄ™ przydzielić bufora: %s\n" #: .././fsr/xfs_fsr.c:1299 #, c-format msgid "could not open fragfile: %s : %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć pliku frag: %s: %s\n" #: .././fsr/xfs_fsr.c:1314 #, c-format msgid "could not trunc tmp %s\n" msgstr "nie udaÅ‚o siÄ™ uciąć tmp %s\n" #: .././fsr/xfs_fsr.c:1318 .././fsr/xfs_fsr.c:1338 .././fsr/xfs_fsr.c:1366 #, c-format msgid "could not lseek in tmpfile: %s : %s\n" msgstr "nie udaÅ‚o siÄ™ przemieÅ›cić (lseek) w pliku tymczasowym: %s: %s\n" #: .././fsr/xfs_fsr.c:1333 #, c-format msgid "could not pre-allocate tmp space: %s\n" msgstr "nie udaÅ‚o siÄ™ wstÄ™pnie przydzielić miejsca tmp: %s\n" #: .././fsr/xfs_fsr.c:1346 msgid "Couldn't rewind on temporary file\n" msgstr "Nie udaÅ‚o siÄ™ przewinąć pliku tymczasowego\n" #: .././fsr/xfs_fsr.c:1353 #, c-format msgid "Temporary file has %d extents (%d in original)\n" msgstr "Plik tymczasowy ma ekstentów: %d (%d w oryginale)\n" #: .././fsr/xfs_fsr.c:1356 #, c-format msgid "No improvement will be made (skipping): %s\n" msgstr "Nie nastÄ…pi poprawa (pominiÄ™to): %s\n" #: .././fsr/xfs_fsr.c:1371 #, c-format msgid "could not lseek in file: %s : %s\n" msgstr "nie udaÅ‚o siÄ™ przemieÅ›cić (lseek) w pliku: %s: %s\n" #: .././fsr/xfs_fsr.c:1407 #, c-format msgid "bad read of %d bytes from %s: %s\n" msgstr "błędny odczyt %d bajtów z %s: %s\n" #: .././fsr/xfs_fsr.c:1411 .././fsr/xfs_fsr.c:1443 #, c-format msgid "bad write of %d bytes to %s: %s\n" msgstr "błędny zapis %d bajtów do %s: %s\n" #: .././fsr/xfs_fsr.c:1428 #, c-format msgid "bad write2 of %d bytes to %s: %s\n" msgstr "błędny zapis 2 %d bajtów do %s: %s\n" #: .././fsr/xfs_fsr.c:1433 #, c-format msgid "bad copy to %s\n" msgstr "błędna kopia do %s\n" #: .././fsr/xfs_fsr.c:1451 #, c-format msgid "could not truncate tmpfile: %s : %s\n" msgstr "nie udaÅ‚o siÄ™ obciąć pliku tymczasowego: %s: %s\n" #: .././fsr/xfs_fsr.c:1456 #, c-format msgid "could not fsync tmpfile: %s : %s\n" msgstr "nie udaÅ‚o siÄ™ wykonać fsync pliku tymczasowego: %s: %s\n" #: .././fsr/xfs_fsr.c:1471 #, c-format msgid "failed to fchown tmpfile %s: %s\n" msgstr "nie udaÅ‚o siÄ™ wykonać fchown na pliku tymczasowym %s: %s\n" #: .././fsr/xfs_fsr.c:1481 #, c-format msgid "%s: file type not supported\n" msgstr "%s: tym pliku nie obsÅ‚ugiwany\n" #: .././fsr/xfs_fsr.c:1485 #, c-format msgid "%s: file modified defrag aborted\n" msgstr "%s: plik zmodyfikowany, defragmentacja przerwana\n" #: .././fsr/xfs_fsr.c:1490 #, c-format msgid "%s: file busy\n" msgstr "%s: plik zajÄ™ty\n" #: .././fsr/xfs_fsr.c:1492 #, c-format msgid "XFS_IOC_SWAPEXT failed: %s: %s\n" msgstr "XFS_IOC_SWAPEXT nie powiodÅ‚o siÄ™: %s: %s\n" #: .././fsr/xfs_fsr.c:1500 #, c-format msgid "extents before:%d after:%d %s %s\n" msgstr "ekstentów przed: %d po: %d %s %s\n" #: .././fsr/xfs_fsr.c:1534 #, c-format msgid "tmp file name too long: %s\n" msgstr "nazwa pliku tymczasowego zbyt dÅ‚uga: %s\n" #: .././fsr/xfs_fsr.c:1584 #, c-format msgid "realloc failed: %s\n" msgstr "realloc nie powiodÅ‚o siÄ™: %s\n" #: .././fsr/xfs_fsr.c:1597 #, c-format msgid "malloc failed: %s\n" msgstr "malloc nie powiodÅ‚o siÄ™: %s\n" #: .././fsr/xfs_fsr.c:1627 #, c-format msgid "failed reading extents: inode %llu" msgstr "nie udaÅ‚o siÄ™ odczytać ekstentów: i-wÄ™zeÅ‚ %llu" #: .././fsr/xfs_fsr.c:1677 msgid "failed reading extents" msgstr "nie udaÅ‚o siÄ™ odczytać ekstentów" #: .././fsr/xfs_fsr.c:1765 .././fsr/xfs_fsr.c:1779 #, c-format msgid "tmpdir already exists: %s\n" msgstr "katalog tymczasowy już istnieje: %s\n" #: .././fsr/xfs_fsr.c:1768 #, c-format msgid "could not create tmpdir: %s: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć katalogu tymczasowego: %s: %s\n" #: .././fsr/xfs_fsr.c:1781 #, c-format msgid "cannot create tmpdir: %s: %s\n" msgstr "nie można utworzyć katalogu tymczasowego: %s: %s\n" #: .././fsr/xfs_fsr.c:1819 .././fsr/xfs_fsr.c:1827 #, c-format msgid "could not remove tmpdir: %s: %s\n" msgstr "nie udaÅ‚o siÄ™ usunąć katalogu tymczasowego: %s: %s\n" #: .././growfs/xfs_growfs.c:26 #, c-format msgid "" "Usage: %s [options] mountpoint\n" "\n" "Options:\n" "\t-d grow data/metadata section\n" "\t-l grow log section\n" "\t-r grow realtime section\n" "\t-n don't change anything, just show geometry\n" "\t-i convert log from external to internal format\n" "\t-t alternate location for mount table (/etc/mtab)\n" "\t-x convert log from internal to external format\n" "\t-D size grow data/metadata section to size blks\n" "\t-L size grow/shrink log section to size blks\n" "\t-R size grow realtime section to size blks\n" "\t-e size set realtime extent size to size blks\n" "\t-m imaxpct set inode max percent to imaxpct\n" "\t-V print version information\n" msgstr "" "SkÅ‚adnia: %s [opcje] punkt_montowania\n" "\n" "Opcje:\n" "\t-d powiÄ™kszenie sekcji danych/metadanych\n" "\t-l powiÄ™kszenie sekcji logu\n" "\t-r powiÄ™kszenie sekcji realtime\n" "\t-n bez zmian, tylko pokazanie geometrii\n" "\t-i przeksztaÅ‚cenie logu z formatu zewnÄ™trznego na wewnÄ™trzny\n" "\t-t inne poÅ‚ożenie tabeli montowaÅ„ (/etc/mtab)\n" "\t-x przeksztaÅ‚cenie logu z formatu wewnÄ™trznego na zewnÄ™trzny\n" "\t-D rozmiar powiÄ™kszenie sekcji danych/metadanych do rozmiaru w blokach\n" "\t-L rozmiar powiÄ™kszenie/zmniejszenie sekcji logu do rozmiaru w blokach\n" "\t-R rozmiar powiÄ™kszenie sekcji realtime do rozmiaru w blokach\n" "\t-e rozmiar stawienie rozmiaru ekstentu realtime na rozmiar w blokach\n" "\t-m imaxpct ustawienie maksymalnego procentu i-wÄ™złów na imaxpct\n" "\t-V wypisanie informacji o wersji\n" #: .././growfs/xfs_growfs.c:66 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u rmapbt=%u\n" " =%-22s reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" msgstr "" "metadane=%-22s isize=%-6u agcount=%u, agsize=%u bloków\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u\n" "dane =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u bloków\n" "nazwy =wersja %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, wersja=%u\n" " =%-22s sectsz=%-5u sunit=%u bloków, lazy-count=%u\n" "realtime=%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" #: .././growfs/xfs_growfs.c:85 .././growfs/xfs_growfs.c:466 #: .././growfs/xfs_growfs.c:467 msgid "internal" msgstr "wewnÄ™trzny" #: .././growfs/xfs_growfs.c:85 .././growfs/xfs_growfs.c:88 #: .././growfs/xfs_growfs.c:466 .././growfs/xfs_growfs.c:467 msgid "external" msgstr "zewnÄ™trzny" #: .././growfs/xfs_growfs.c:207 #, c-format msgid "%s: %s is not a mounted XFS filesystem\n" msgstr "%s: %s nie jest podmontowanym systemem plików XFS\n" #: .././growfs/xfs_growfs.c:224 #, c-format msgid "%s: specified file [\"%s\"] is not on an XFS filesystem\n" msgstr "%s: podany plik [\"%s\"] nie jest na systemie plików XFS\n" #: .././growfs/xfs_growfs.c:241 #, c-format msgid "%s: cannot determine geometry of filesystem mounted at %s: %s\n" msgstr "" "%s: nie można okreÅ›lić geometrii systemu plików podmontowanego pod %s: %s\n" #: .././growfs/xfs_growfs.c:285 #, c-format msgid "%s: failed to access data device for %s\n" msgstr "%s: nie udaÅ‚o siÄ™ uzyskać dostÄ™pu do urzÄ…dzenia z danymi dla %s\n" #: .././growfs/xfs_growfs.c:290 #, c-format msgid "%s: failed to access external log for %s\n" msgstr "%s: nie udaÅ‚o siÄ™ uzyskać dostÄ™pu do zewnÄ™trznego logu dla %s\n" #: .././growfs/xfs_growfs.c:296 #, c-format msgid "%s: failed to access realtime device for %s\n" msgstr "%s: nie udaÅ‚o siÄ™ uzyskać dostÄ™pu do urzÄ…dzenia realtime dla %s\n" #: .././growfs/xfs_growfs.c:336 #, c-format msgid "data size %lld too large, maximum is %lld\n" msgstr "rozmiar danych %lld zbyt duży, maksymalny to %lld\n" #: .././growfs/xfs_growfs.c:343 #, c-format msgid "data size %lld too small, old size is %lld\n" msgstr "rozmiar danych %lld zbyt maÅ‚y, stary rozmiar to %lld\n" #: .././growfs/xfs_growfs.c:351 #, c-format msgid "data size unchanged, skipping\n" msgstr "rozmiar danych nie zmieniony, pominiÄ™to\n" #: .././growfs/xfs_growfs.c:354 #, c-format msgid "inode max pct unchanged, skipping\n" msgstr "maksymalny procent i-wÄ™złów nie zmieniony, pominiÄ™to\n" #: .././growfs/xfs_growfs.c:361 .././growfs/xfs_growfs.c:400 #: .././growfs/xfs_growfs.c:435 #, c-format msgid "%s: growfs operation in progress already\n" msgstr "%s: operacja growfs już trwa\n" #: .././growfs/xfs_growfs.c:365 #, c-format msgid "%s: XFS_IOC_FSGROWFSDATA xfsctl failed: %s\n" msgstr "%s: xfsctl XFS_IOC_FSGROWFSDATA nie powiodÅ‚o siÄ™: %s\n" #: .././growfs/xfs_growfs.c:381 #, c-format msgid "realtime size %lld too large, maximum is %lld\n" msgstr "rozmiar realtime %lld zbyt duży, maksymalny to %lld\n" #: .././growfs/xfs_growfs.c:387 #, c-format msgid "realtime size %lld too small, old size is %lld\n" msgstr "rozmiar realtime %lld zbyt maÅ‚y, stary rozmiar to %lld\n" #: .././growfs/xfs_growfs.c:393 #, c-format msgid "realtime size unchanged, skipping\n" msgstr "rozmiar realtime nie zmieniony, pominiÄ™to\n" #: .././growfs/xfs_growfs.c:404 #, c-format msgid "%s: realtime growth not implemented\n" msgstr "%s: powiÄ™kszanie realtime nie jest zaimplementowane\n" #: .././growfs/xfs_growfs.c:408 #, c-format msgid "%s: XFS_IOC_FSGROWFSRT xfsctl failed: %s\n" msgstr "%s: xfsctl XFS_IOC_FSGROWFSRT nie powiodÅ‚o siÄ™: %s\n" #: .././growfs/xfs_growfs.c:429 #, c-format msgid "log size unchanged, skipping\n" msgstr "rozmiar logu nie zmieniony, pominiÄ™to\n" #: .././growfs/xfs_growfs.c:439 #, c-format msgid "%s: log growth not supported yet\n" msgstr "%s: powiÄ™kszanie logu nie jest jeszcze obsÅ‚ugiwane\n" #: .././growfs/xfs_growfs.c:443 #, c-format msgid "%s: XFS_IOC_FSGROWFSLOG xfsctl failed: %s\n" msgstr "%s: xfsctl XFS_IOC_FSGROWFSLOG nie powiodÅ‚o siÄ™: %s\n" #: .././growfs/xfs_growfs.c:451 #, c-format msgid "%s: XFS_IOC_FSGEOMETRY xfsctl failed: %s\n" msgstr "%s: xfsctl XFS_IOC_FSGEOMETRY nie powiodÅ‚o siÄ™: %s\n" #: .././growfs/xfs_growfs.c:456 #, c-format msgid "data blocks changed from %lld to %lld\n" msgstr "bloki danych zmienione z %lld na %lld\n" #: .././growfs/xfs_growfs.c:459 #, c-format msgid "inode max percent changed from %d to %d\n" msgstr "maksymalny procent i-wÄ™złów zmieniony z %d na %d\n" #: .././growfs/xfs_growfs.c:462 #, c-format msgid "log blocks changed from %d to %d\n" msgstr "bloki logu zmienione z %d na %d\n" #: .././growfs/xfs_growfs.c:465 #, c-format msgid "log changed from %s to %s\n" msgstr "log zmieniony - byÅ‚ %s, jest %s\n" #: .././growfs/xfs_growfs.c:469 #, c-format msgid "realtime blocks changed from %lld to %lld\n" msgstr "bloki realtime zmienione z %lld na %lld\n" #: .././growfs/xfs_growfs.c:472 #, c-format msgid "realtime extent size changed from %d to %d\n" msgstr "rozmiar ekstentu realtime zmieniony z %d na %d\n" #: .././io/attr.c:60 #, fuzzy, c-format msgid "" "\n" " displays the set of extended inode flags associated with the current file\n" "\n" " Each individual flag is displayed as a single character, in this order:\n" " r -- file data is stored in the realtime section\n" " p -- file has preallocated extents (cannot be changed using chattr)\n" " i -- immutable, file cannot be modified\n" " a -- append-only, file can only be appended to\n" " s -- all updates are synchronous\n" " A -- the access time is not updated for this inode\n" " d -- do not include this file in a dump of the filesystem\n" " t -- child created in this directory has realtime bit set by default\n" " P -- child created in this directory has parents project ID by default\n" " n -- symbolic links cannot be created in this directory\n" " e -- for non-realtime files, observe the inode extent size value\n" " E -- children created in this directory inherit the extent size value\n" " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" " x -- Use direct access (DAX) for data in this file\n" " C -- for files with shared blocks, observe the inode CoW extent size value\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, but only list attributes on directories\n" " -a -- show all flags which can be set alongside those which are set\n" " -v -- verbose mode; show long names of flags, not single characters\n" "\n" msgstr "" "\n" " wyÅ›wietlanie zbioru rozszerzonych flag i-wÄ™złów zwiÄ…zanych z bieżącym " "plikiem\n" "\n" " Każda flaga jest wyÅ›wietlana jako pojedynczy znak, w tej kolejnoÅ›ci:\n" " r - dane pliku sÄ… zapisane w sekcji realtime\n" " p - plik ma już przydzielone ekstenty (nie do zmiany przez chattr)\n" " i - niezmienny, pliku nie można modyfikować\n" " a - tylko do dopisywania, do pliku można tylko dopisywać\n" " s - wszystkie uaktualnienia sÄ… synchroniczne\n" " A - czas dostÄ™pu nie jest uaktualniany dla tego i-wÄ™zÅ‚a\n" " d - nie dołączanie pliku do zrzutu systemu plików\n" " t - wpisy tworzone w tym katalogu majÄ… domyÅ›lnie ustawiony bit realtime\n" " P - wpisy tworzone w tym katalogu majÄ… domyÅ›lnie ID projektu rodzica\n" " n - w tym katalogu nie można tworzyć dowiÄ…zaÅ„ symbolicznych\n" " e - dla plików nie-realtime - przestrzeganie wartoÅ›ci rozmiaru ekstentu i-" "wÄ™zÅ‚a\n" " E - wpisy tworzone w tym katalogu dziedziczÄ… wartość rozmiaru ekstentu\n" " f - nie uwzglÄ™dnianie tego pliku przy defragmentacji systemu plików\n" " S - włączenie przydzielania strumieni plikowych dla tego katalogu\n" "\n" " Opcje:\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale wypisywanie atrybutów tylko " "katalogów\n" " -a - pokazywanie wszystkich flag, które można ustawić, obok ustawionych\n" " -v - tryb szczegółowy; pokazywanie dÅ‚ugich nazw flag zamiast pojedynczych " "znaków\n" "\n" #: .././io/attr.c:93 #, fuzzy, c-format msgid "" "\n" " modifies the set of extended inode flags associated with the current file\n" "\n" " Examples:\n" " 'chattr +a' - sets the append-only flag\n" " 'chattr -a' - clears the append-only flag\n" "\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, only modifying attributes on directories\n" " +/-r -- set/clear the realtime flag\n" " +/-i -- set/clear the immutable flag\n" " +/-a -- set/clear the append-only flag\n" " +/-s -- set/clear the sync flag\n" " +/-A -- set/clear the no-atime flag\n" " +/-d -- set/clear the no-dump flag\n" " +/-t -- set/clear the realtime inheritance flag\n" " +/-P -- set/clear the project ID inheritance flag\n" " +/-n -- set/clear the no-symbolic-links flag\n" " +/-e -- set/clear the extent-size flag\n" " +/-E -- set/clear the extent-size inheritance flag\n" " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " +/-x -- set/clear the direct access (DAX) flag\n" " +/-C -- set/clear the CoW extent-size flag\n" " Note1: user must have certain capabilities to modify immutable/append-" "only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" " Note3: the realtime flag can only be set if the filesystem has a realtime\n" " section, and the (regular) file must be empty when the flag is set.\n" "\n" msgstr "" "\n" " zmiana zbioru rozszerzonych flag i-wÄ™złów zwiÄ…zanych z bieżącym plikiem\n" "\n" " PrzykÅ‚ady:\n" " 'chattr +a' - ustawia flagÄ™ tylko do dopisywania\n" " 'chattr -a' - zdejmuje flagÄ™ tylko do dopisywania\n" "\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale zmiana atrybutów tylko katalogów\n" " +/-r - ustawienie/zdjÄ™cie flagi realtime\n" " +/-i - ustawienie/zdjÄ™cie flagi immutable (niezmiennoÅ›ci)\n" " +/-a - ustawienie/zdjÄ™cie flagi append-only (tylko do dopisywania)\n" " +/-s - ustawienie/zdjÄ™cie flagi sync (synchronicznego zapisu)\n" " +/-A - ustawienie/zdjÄ™cie flagi no-atime\n" " +/-d - ustawienie/zdjÄ™cie flagi no-dump\n" " +/-t - ustawienie/zdjÄ™cie flagi dziedziczenia realtime\n" " +/-P - ustawienie/zdjÄ™cie flagi dziedziczenia ID projektu\n" " +/-n - ustawienie/zdjÄ™cie flagi braku dowiÄ…zaÅ„ symbolicznych\n" " +/-e - ustawienie/zdjÄ™cie flagi rozmiaru ekstentu\n" " +/-E - ustawienie/zdjÄ™cie flagi dziedziczenia rozmiaru ekstentu\n" " +/-f - ustawienie/zdjÄ™cie flagi no-defrag\n" " +/-S - ustawienie/zdjÄ™cie flagi przydzielania strumieni plikowych\n" " Uwaga1: użytkownik musi mieć pewne uprawnienia do zmiany flag\n" " immutable/append-only\n" " Uwaga2: plików immutable/append-only nie można usuwać; usuwanie tych " "plików\n" " wymaga zdjÄ™cia flag immutable/append-only przed usuniÄ™ciem.\n" " Uwaga3: flagÄ™ realtime można ustawić tylko jeÅ›li system plików ma sekcjÄ™\n" " realtime i (zwykÅ‚y) plik musi być pusty przy ustawianiu flagi.\n" "\n" #: .././io/attr.c:176 .././io/attr.c:252 .././io/cowextsize.c:109 #: .././io/cowextsize.c:132 .././io/open.c:426 .././io/open.c:498 #: .././io/open.c:622 .././io/open.c:644 .././libxfs/init.c:127 #: .././mkfs/proto.c:302 .././quota/project.c:118 .././quota/project.c:163 #: .././quota/project.c:210 #, c-format msgid "%s: cannot open %s: %s\n" msgstr "%s: nie można otworzyć %s: %s\n" #: .././io/attr.c:179 .././io/attr.c:226 .././io/attr.c:255 .././io/attr.c:326 #: .././quota/project.c:122 .././quota/project.c:168 .././quota/project.c:215 #, c-format msgid "%s: cannot get flags on %s: %s\n" msgstr "%s: nie można pobrać flag %s: %s\n" #: .././io/attr.c:261 .././io/attr.c:332 #, c-format msgid "%s: cannot set flags on %s: %s\n" msgstr "%s: nie można ustawić flag %s: %s\n" #: .././io/attr.c:296 .././io/attr.c:310 #, c-format msgid "%s: unknown flag\n" msgstr "%s: nieznana flaga\n" #: .././io/attr.c:316 #, c-format msgid "%s: bad chattr command, not +/-X\n" msgstr "%s: zÅ‚e polecenie chattr - nie +/-X\n" #: .././io/attr.c:343 msgid "[-R|-D] [+/-" msgstr "[-R|-D] [+/-" #: .././io/attr.c:348 msgid "change extended inode flags on the currently open file" msgstr "zmiana rozszerzonych flag i-wÄ™złów aktualnie otwartego pliku" #: .././io/attr.c:353 msgid "[-R|-D|-a|-v]" msgstr "[-R|-D|-a|-v]" #: .././io/attr.c:358 msgid "list extended inode flags set on the currently open file" msgstr "wypisanie rozszerzonych flag i-wÄ™złów aktualnie otwartego pliku" #: .././io/bmap.c:30 #, fuzzy, c-format msgid "" "\n" " prints the block mapping for an XFS file's data or attribute forks\n" " Example:\n" " 'bmap -vp' - tabular format verbose map, including unwritten extents\n" "\n" " bmap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -c -- prints the copy-on-write fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" " -e -- print delayed allocation extents.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are " "unwritten.)\n" " -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" " Note: the bmap for non-regular files can be obtained provided the file\n" " was opened appropriately (in particular, must be opened read-only).\n" "\n" msgstr "" "\n" " wypisanie mapowania bloków dla danych lub atrybutów pliku na XFS-ie\n" " PrzykÅ‚ad:\n" " 'bmap -vp' - szczegółowa mapa w formacie tabeli wraz z nie zapisanymi\n" " ekstentami\n" "\n" " bmap wypisuje mapÄ™ bloków dysku używanych przez bieżący plik.\n" " Mapa opisuje każdy ekstent użyty przez plik, a także regiony w pliku\n" " nie majÄ…ce przypisanych bloków (dziury).\n" " DomyÅ›lnie każda linia listingu przyjmuje nastÄ™pujÄ…cÄ… postać:\n" " ekstent: [offsetpocz..offsetkoÅ„c]: blokpocz..blokkoÅ„c\n" " Dziury sÄ… oznaczane przez zastÄ…pienie blokpocz..blokkoÅ„c przez 'dziura'.\n" " Wszystkie offsety w plikach i bloki dysku sÄ… w jednostkach 512-bajtowych.\n" " -a - wypisanie mapy gałęzi atrybutów zamiast gałęzi danych.\n" " -d - pominiÄ™cie zdarzenia odczytu DMAPI, pokazanie części offline jako " "dziur.\n" " -l - wyÅ›wietlenie także dÅ‚ugoÅ›ci każdego fragmentu w 512-bajtowych " "blokach.\n" " -n - odpytanie n ekstentów.\n" " -p - wypisanie także nie zapisanych ekstentów (z -v pokazuje, które sÄ… nie\n" " zapisane).\n" " -v - szczegółowe informacje z podaniem informacji ag; legenda drugim -v\n" " Uwaga: bmap dla plików nie bÄ™dÄ…cych plikami zwykÅ‚ymi można uzyskać pod\n" " warunkiem, że plik zostaÅ‚ otwarty odpowiednio (w szczególnoÅ›ci musi być\n" " otwarty tylko do odczytu).\n" "\n" #: .././io/bmap.c:133 #, c-format msgid "%s: can't get geometry [\"%s\"]: %s\n" msgstr "%s: nie można uzyskać geometrii [\"%s\"]: %s\n" #: .././io/bmap.c:141 #, c-format msgid "%s: cannot read attrs on \"%s\": %s\n" msgstr "%s: nie można odczytać atrybutów \"%s\": %s\n" #: .././io/bmap.c:159 .././io/fiemap.c:258 #, c-format msgid "%s: malloc of %d bytes failed.\n" msgstr "%s: przydzielenie %d bajtów nie powiodÅ‚o siÄ™.\n" #: .././io/bmap.c:207 #, c-format msgid "%s: xfsctl(XFS_IOC_GETBMAPX) iflags=0x%x [\"%s\"]: %s\n" msgstr "%s: xfsctl(XFS_IOC_GETBMAPX) iflags=0x%x [\"%s\"]: %s\n" #: .././io/bmap.c:238 #, c-format msgid "%s: cannot realloc %d bytes\n" msgstr "%s: nie można wykonać realloc na %d bajtów\n" #: .././io/bmap.c:247 #, c-format msgid "%s: no extents\n" msgstr "%s: brak ekstentów\n" #: .././io/bmap.c:261 .././io/bmap.c:396 .././io/fiemap.c:104 #: .././io/fiemap.c:339 .././io/fiemap.c:343 #, c-format msgid "hole" msgstr "dziura" #: .././io/bmap.c:263 .././io/bmap.c:404 #, c-format msgid "delalloc" msgstr "" #: .././io/bmap.c:272 #, c-format msgid " %lld blocks\n" msgstr " %lld bloków\n" #: .././io/bmap.c:352 .././io/fiemap.c:93 msgid "EXT" msgstr "EXT" #: .././io/bmap.c:353 .././io/fiemap.c:94 msgid "FILE-OFFSET" msgstr "OFFSET-W-PLIKU" #: .././io/bmap.c:354 msgid "RT-BLOCK-RANGE" msgstr "ZAKRES-BLOKÓW-RT" #: .././io/bmap.c:354 .././io/fiemap.c:95 msgid "BLOCK-RANGE" msgstr "ZAKRES-BLOKÓW" #: .././io/bmap.c:355 msgid "AG" msgstr "AG" #: .././io/bmap.c:356 msgid "AG-OFFSET" msgstr "OFFSET-AG" #: .././io/bmap.c:357 .././io/fiemap.c:96 msgid "TOTAL" msgstr "RAZEM" #: .././io/bmap.c:358 msgid " FLAGS" msgstr " FLAGI" #: .././io/bmap.c:438 #, c-format msgid " FLAG Values:\n" msgstr " WartoÅ›ci FLAG:\n" #: .././io/bmap.c:439 #, fuzzy, c-format msgid " %*.*o Shared extent\n" msgstr " %*.*o Nie zapisany, już przydzielony ekstent\n" #: .././io/bmap.c:441 #, c-format msgid " %*.*o Unwritten preallocated extent\n" msgstr " %*.*o Nie zapisany, już przydzielony ekstent\n" #: .././io/bmap.c:443 #, c-format msgid " %*.*o Doesn't begin on stripe unit\n" msgstr " %*.*o Nie zaczyna siÄ™ od jednostki pasa\n" #: .././io/bmap.c:445 #, c-format msgid " %*.*o Doesn't end on stripe unit\n" msgstr " %*.*o Nie koÅ„czy siÄ™ na jednostce pasa\n" #: .././io/bmap.c:447 #, c-format msgid " %*.*o Doesn't begin on stripe width\n" msgstr " %*.*o Nie zaczyna siÄ™ na szerokoÅ›ci pasa\n" #: .././io/bmap.c:449 #, c-format msgid " %*.*o Doesn't end on stripe width\n" msgstr " %*.*o Nie koÅ„czy siÄ™ na szerokoÅ›ci pasa\n" #: .././io/bmap.c:465 msgid "[-adlpv] [-n nx]" msgstr "[-adlpv] [-n nx]" #: .././io/bmap.c:466 msgid "print block mapping for an XFS file" msgstr "wypisanie mapowania bloków dla pliku na XFS-ie" #: .././io/copy_file_range.c:32 #, c-format msgid "" "\n" " Copies a range of bytes from a file into the open file, overwriting any " "data\n" " already there.\n" "\n" " Example:\n" " 'copy_range -s 100 -d 200 -l 300 some_file' - copies 300 bytes from " "some_file\n" " at offset 100 into the open\n" "\t\t\t\t\t file at offset 200\n" " 'copy_range some_file' - copies all bytes from some_file into the open " "file\n" " at position 0\n" msgstr "" #: .././io/copy_file_range.c:97 #, fuzzy, c-format msgid "invalid source offset -- %s\n" msgstr "nieprawidÅ‚owy ID projektu - %s\n" #: .././io/copy_file_range.c:104 #, fuzzy, c-format msgid "invalid destination offset -- %s\n" msgstr "nieprawidÅ‚owy ID projektu - %s\n" #: .././io/copy_file_range.c:111 #, fuzzy, c-format msgid "invalid length -- %s\n" msgstr "nieprawidÅ‚owy ID projektu - %s\n" #: .././io/copy_file_range.c:143 msgid "[-s src_off] [-d dst_off] [-l len] src_file" msgstr "" #: .././io/copy_file_range.c:144 msgid "Copy a range of data between two files" msgstr "" #: .././io/cowextsize.c:40 #, fuzzy, c-format msgid "" "\n" " report or modify preferred CoW extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying cowextsize on directories\n" "\n" msgstr "" "\n" " odczyt lub zmiana preferowanego rozmiaru ekstentu (w bajtach) dla bieżącej\n" " Å›cieżki\n" "\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale zmiana extsize tylko katalogów\n" "\n" #: .././io/cowextsize.c:81 .././io/open.c:595 #, c-format msgid "invalid target file type - file %s\n" msgstr "nieprawidÅ‚owy rodzaj bliku docelowego - plik %s\n" #: .././io/cowextsize.c:169 #, fuzzy, c-format msgid "non-numeric cowextsize argument -- %s\n" msgstr "nieliczbowy argument extsize - %s\n" #: .././io/cowextsize.c:193 #, fuzzy msgid "[-D | -R] [cowextsize]" msgstr "[-D | -R] [rozmiar_fragmentu]" #: .././io/cowextsize.c:198 #, fuzzy msgid "get/set preferred CoW extent size (in bytes) for the open file" msgstr "" "pobranie/ustawienie preferowanego rozmiaru ekstentu (w bajtach) dla " "otwartego pliku" #: .././io/fadvise.c:30 #, c-format msgid "" "\n" " advise the page cache about expected I/O patterns on the current file\n" "\n" " Modifies kernel page cache behaviour when operating on the current file.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_FADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_FADV_DONTNEED) [*]\n" " -n -- data will be accessed once (POSIX_FADV_NOREUSE) [*]\n" " -r -- expect random page references (POSIX_FADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_FADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_FADV_WILLNEED) [*]\n" " Notes: these interfaces are not supported in Linux kernels before 2.6.\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED and NOREUSE are equivalent, and force the maximum readahead.\n" "\n" msgstr "" "\n" " doradzenie buforowi stron w sprawie oczekiwanych schematów we/wy na " "bieżącym\n" " pliku\n" "\n" " fadvise modyfikuje zachowanie bufora stron przy operacjach na bieżącym " "pliku.\n" " Niektóre polecenia fadvise ([*] poniżej) wymagajÄ… podania zakresu.\n" " Bez argumentów zakÅ‚ada siÄ™ doradzenie POSIX_FADV_NORMAL.\n" " -d - podane strony nie sÄ… wymagane (POSIX_FADV_DONTNEED) [*]\n" " -n - dostÄ™p do danych bÄ™dzie jednokrotny (POSIX_FADV_NOREUSE) [*]\n" " -r - należy oczekiwać losowych odwoÅ‚aÅ„ do stron (POSIX_FADV_RANDOM)\n" " -s - należy oczekiwać sekwencyjnych odwoÅ‚aÅ„ do stron " "(POSIX_FADV_SEQUENTIAL)\n" " -w - podane strony bÄ™dÄ… potrzebne (POSIX_FADV_WILLNEED) [*]\n" " Uwagi: te interfejsy nie byÅ‚y obsÅ‚ugiwane przez jÄ…dra Linuksa przed 2.6.\n" " NORMAL ustawia domyÅ›lnÄ… wartość czytania z wyprzedzeniem dla pliku.\n" " RANDOM ustawia czytanie z wyprzedzeniem dla pliku na zero.\n" " SEQUENTIAL ustawia podwójnÄ… domyÅ›lnÄ… wartość czytania z wyprzedzeniem.\n" " WILLNEED i NOREUSE sÄ… równoznaczne i wymuszajÄ… maksymalne czytanie\n" " z wyprzedzeniem.\n" "\n" #: .././io/fadvise.c:91 .././io/madvise.c:86 .././io/mincore.c:47 #: .././io/mmap.c:213 .././io/mmap.c:320 .././io/mmap.c:406 .././io/mmap.c:565 #: .././io/mmap.c:647 .././io/prealloc.c:73 .././io/pwrite.c:346 #: .././io/sendfile.c:124 .././io/sync_file_range.c:74 #, c-format msgid "non-numeric offset argument -- %s\n" msgstr "nieliczbowy argument bÄ™dÄ…cy offsetem - %s\n" #: .././io/fadvise.c:98 .././io/madvise.c:93 .././io/mincore.c:53 #: .././io/mmap.c:219 .././io/mmap.c:327 .././io/mmap.c:413 .././io/mmap.c:572 #: .././io/pread.c:454 .././io/pread.c:462 .././io/prealloc.c:78 #: .././io/pwrite.c:352 .././io/sendfile.c:131 .././io/sync_file_range.c:81 #, c-format msgid "non-numeric length argument -- %s\n" msgstr "nieliczbowy argument bÄ™dÄ…cy dÅ‚ugoÅ›ciÄ… - %s\n" #: .././io/fadvise.c:121 msgid "[-dnrsw] [off len]" msgstr "[-dnrsw] [offset dÅ‚ugość]" #: .././io/fadvise.c:122 msgid "advisory commands for sections of a file" msgstr "polecenia doradcze dla sekcji pliku" #: .././io/fiemap.c:31 #, c-format msgid "" "\n" " prints the block mapping for a file's data or attribute forks\n" " Example:\n" " 'fiemap -v' - tabular format verbose map\n" "\n" " fiemap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -v -- Verbose information\n" "\n" msgstr "" "\n" " wypisanie mapowania bloków dla danych lub atrybutów pliku\n" " PrzykÅ‚ad:\n" " 'fiemap -v' - szczegółowa mapa w formacie tabeli\n" "\n" " fiemap wypisuje mapÄ™ bloków dysku używanych przez bieżący plik.\n" " Mapa opisuje każdy ekstent użyty przez plik, a także regiony w pliku\n" " nie majÄ…ce przypisanych bloków (dziury).\n" " DomyÅ›lnie każda linia listingu przyjmuje nastÄ™pujÄ…cÄ… postać:\n" " ekstent: [offsetpocz..offsetkoÅ„c]: blokpocz..blokkoÅ„c\n" " Dziury sÄ… oznaczane przez zastÄ…pienie blokpocz..blokkoÅ„c przez 'dziura'.\n" " Wszystkie offsety w plikach i bloki dysku sÄ… w jednostkach 512-bajtowych.\n" " -a - wypisanie mapy gałęzi atrybutów zamiast gałęzi danych.\n" " -l - wyÅ›wietlenie także dÅ‚ugoÅ›ci każdego fragmentu w 512-bajtowych " "blokach.\n" " -n - odpytanie n ekstentów.\n" " -v - szczegółowe informacje\n" "\n" #: .././io/fiemap.c:97 msgid "FLAGS" msgstr "FLAGI" #: .././io/fiemap.c:146 .././io/fiemap.c:160 .././io/fiemap.c:345 #, c-format msgid " %llu blocks\n" msgstr " %llu bloków\n" #: .././io/fiemap.c:365 msgid "[-alv] [-n nx]" msgstr "[-alv] [-n nx]" #: .././io/fiemap.c:366 msgid "print block mapping for a file" msgstr "wypisanie mapowania bloków dla pliku" #: .././io/file.c:38 #, c-format msgid "%c%03d%c %-14s (%s,%s,%s,%s%s%s%s%s)\n" msgstr "%c%03d%c %-14s (%s,%s,%s,%s%s%s%s%s)\n" #: .././io/file.c:40 msgid "foreign" msgstr "obcy" #: .././io/file.c:40 msgid "xfs" msgstr "xfs" #: .././io/file.c:41 .././io/open.c:98 msgid "sync" msgstr "synchr" #: .././io/file.c:41 .././io/open.c:98 msgid "non-sync" msgstr "niesynchr" #: .././io/file.c:42 .././io/open.c:99 msgid "direct" msgstr "bezpoÅ›redni" #: .././io/file.c:42 .././io/open.c:99 msgid "non-direct" msgstr "niebezpoÅ›redni" #: .././io/file.c:43 .././io/open.c:100 msgid "read-only" msgstr "tylko do odczytu" #: .././io/file.c:43 .././io/open.c:100 msgid "read-write" msgstr "odczyt i zapis" #: .././io/file.c:44 .././io/open.c:101 msgid ",real-time" msgstr ",real-time" #: .././io/file.c:45 .././io/open.c:102 msgid ",append-only" msgstr ",tylko dopisywanie" #: .././io/file.c:46 .././io/open.c:103 msgid ",non-block" msgstr ",nieblokujÄ…cy" #: .././io/file.c:47 .././io/open.c:104 msgid ",tmpfile" msgstr ",tmpfile" #: .././io/file.c:81 .././io/sendfile.c:101 .././quota/path.c:126 #, c-format msgid "value %d is out of range (0-%d)\n" msgstr "wartość %d jest spoza zakresu (0-%d)\n" #: .././io/file.c:94 .././quota/path.c:140 msgid "[N]" msgstr "[N]" #: .././io/file.c:99 msgid "set the current file" msgstr "ustawienie bieżącego pliku" #: .././io/file.c:108 msgid "list current open files and memory mappings" msgstr "wypisanie aktualnie otwartych plików i odwzorowaÅ„ w pamiÄ™ci" #: .././io/freeze.c:36 #, c-format msgid "%s: cannot freeze filesystem at %s: %s\n" msgstr "%s: nie można zamrozić systemu plików na %s: %s\n" #: .././io/freeze.c:53 #, c-format msgid "%s: cannot unfreeze filesystem mounted at %s: %s\n" msgstr "%s: nie można odmrozić systemu plików podmontowanego pod %s: %s\n" #: .././io/freeze.c:69 msgid "freeze filesystem of current file" msgstr "zamrożenie systemu plików na bieżącym pliku" #: .././io/freeze.c:76 msgid "unfreeze filesystem of current file" msgstr "odmrożenie systemu plików na bieżącym pliku" #: .././io/fsync.c:59 msgid "calls fsync(2) to flush all in-core file state to disk" msgstr "wywoÅ‚anie fsync(2) aby zrzucić caÅ‚y stan pliku z pamiÄ™ci na dysk" #: .././io/fsync.c:66 msgid "calls fdatasync(2) to flush the files in-core data to disk" msgstr "wywoÅ‚anie fdatasync(2) aby zrzucić dane pliku z pamiÄ™ci na dysk" #: .././io/getrusage.c:117 msgid "report process resource usage" msgstr "informacje o wykorzystaniu zasobów przez proces" #: .././io/imap.c:54 #, c-format msgid "ino %10llu count %2d mask %016llx\n" msgstr "i-wÄ™zeÅ‚ %10llu liczba %2d maska %016llx\n" #: .././io/imap.c:74 msgid "[nentries]" msgstr "[liczba_wpisów]" #: .././io/imap.c:76 msgid "inode map for filesystem of current file" msgstr "map i-wÄ™złów dla systemu plików bieżącego pliku" #: .././io/init.c:37 #, fuzzy, c-format msgid "Usage: %s [-adfinrRstVx] [-m mode] [-p prog] [-c cmd]... file\n" msgstr "SkÅ‚adnia: %s [-adfmnrRstVx] [-p program] [-c polecenie]... plik\n" #: .././io/init.c:111 .././io/mmap.c:171 .././io/mmap.c:178 .././io/mmap.c:181 #: .././io/open.c:294 #, c-format msgid "no files are open, try 'help open'\n" msgstr "nie ma otwartych plików, spróbuj 'help open'\n" #: .././io/init.c:115 .././io/mmap.c:170 .././io/mmap.c:177 #, c-format msgid "no mapped regions, try 'help mmap'\n" msgstr "nie ma podmapowanych regionów, spróbuj 'help mmap'\n" #: .././io/init.c:121 #, c-format msgid "foreign file active, %s command is for XFS filesystems only\n" msgstr "" "aktywny jest plik obcy, polecenie %s jest tylko dla systemów plików XFS\n" #: .././io/init.c:169 .././io/open.c:316 #, c-format msgid "non-numeric mode -- %s\n" msgstr "tryb nieliczbowy - %s\n" #: .././io/inject.c:120 #, c-format msgid "" "\n" " inject errors into the filesystem of the currently open file\n" "\n" " Example:\n" " 'inject readagf' - cause errors on allocation group freespace reads\n" "\n" " Causes the kernel to generate and react to errors within XFS, provided\n" " the XFS kernel code has been built with debugging features enabled.\n" " With no arguments, displays the list of error injection tags.\n" "\n" msgstr "" "\n" " wprowadzenie błędów do systemu plików aktualnie otwartego pliku\n" "\n" " PrzykÅ‚ad:\n" " 'inject readagf' - spowodowanie błędów przy odczytach wolnego miejsca grup\n" " alokacji\n" "\n" " inject powoduje, że jÄ…dro generuje i reaguje na błędy wewnÄ…trz XFS-a,\n" " pod warunkiem, że kod XFS-a w jÄ…drze zostaÅ‚ zbudowany z włączonymi opcjami\n" " diagnostycznymi. Bez argumentów wyÅ›wietla listÄ™ znaczników wprowadzania\n" " błędów.\n" "\n" #: .././io/inject.c:146 #, c-format msgid "no such tag -- %s\n" msgstr "nie ma takiego znacznika - %s\n" #: .././io/inject.c:167 msgid "[tag ...]" msgstr "[znacznik ...]" #: .././io/inject.c:168 msgid "inject errors into a filesystem" msgstr "wprowadzanie błędów do systemu plików" #: .././io/link.c:34 #, c-format msgid "" "\n" "link the open file descriptor to the supplied filename\n" "\n" "\n" msgstr "" "\n" "dowiÄ…zanie otwartego deskryptora pliku do podanej nazwy pliku\n" "\n" "\n" #: .././io/link.c:63 msgid "filename" msgstr "nazwa_pliku" #: .././io/link.c:65 msgid "link the open file descriptor to the supplied filename" msgstr "dowiÄ…zanie otwartego deskryptora pliku do podanej nazwy pliku" #: .././io/madvise.c:31 #, c-format msgid "" "\n" " advise the page cache about access patterns expected for a mapping\n" "\n" " Modifies page cache behavior when operating on the current mapping.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_MADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_MADV_DONTNEED) [*]\n" " -r -- expect random page references (POSIX_MADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_MADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_MADV_WILLNEED) [*]\n" " Notes:\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED forces the maximum readahead.\n" "\n" msgstr "" "\n" " doradzenie buforowi stron w sprawie oczekiwanych schematów dostÄ™pu do " "odwzorowaÅ„\n" "\n" " madvise modyfikuje zachowanie bufora stron przy operacjach na bieżącym\n" " odwzorowaniu. Niektóre polecenia madvise ([*] poniżej) wymagajÄ… podania " "zakresu.\n" " Bez argumentów zakÅ‚ada siÄ™ doradzenie POSIX_MADV_NORMAL.\n" " -d - podane strony nie sÄ… wymagane (POSIX_MADV_DONTNEED) [*]\n" " -r - należy oczekiwać losowych odwoÅ‚aÅ„ do stron (POSIX_MADV_RANDOM)\n" " -s - należy oczekiwać sekwencyjnych odwoÅ‚aÅ„ do stron " "(POSIX_MADV_SEQUENTIAL)\n" " -w - podane strony bÄ™dÄ… potrzebne (POSIX_MADV_WILLNEED) [*]\n" " Uwagi:\n" " NORMAL ustawia domyÅ›lnÄ… wartość czytania z wyprzedzeniem dla pliku.\n" " RANDOM ustawia czytanie z wyprzedzeniem dla pliku na zero.\n" " SEQUENTIAL ustawia podwójnÄ… domyÅ›lnÄ… wartość czytania z wyprzedzeniem.\n" " WILLNEED wymusza maksymalne czytanie z wyprzedzeniem.\n" "\n" #: .././io/madvise.c:97 .././io/mincore.c:57 #, c-format msgid "length argument too large -- %lld\n" msgstr "zbyt duży argument bÄ™dÄ…cy dÅ‚ugoÅ›ciÄ… - %lld\n" #: .././io/madvise.c:126 msgid "[-drsw] [off len]" msgstr "[-drsw] [offset dÅ‚ugość]" #: .././io/madvise.c:127 msgid "give advice about use of memory" msgstr "doradzenie w sprawie użycia pamiÄ™ci" #: .././io/mincore.c:91 .././io/mincore.c:101 #, c-format msgid "0x%lx %lu pages (%llu : %lu)\n" msgstr "0x%lx %lu stron (%llu : %lu)\n" #: .././io/mincore.c:121 msgid "[off len]" msgstr "[offset dÅ‚ugość]" #: .././io/mincore.c:122 msgid "find mapping pages that are memory resident" msgstr "odnalezienie stron odwzorowaÅ„ przechowywanych w pamiÄ™ci" #: .././io/mmap.c:78 #, c-format msgid "offset (%lld) is before start of mapping (%lld)\n" msgstr "offset (%lld) przed poczÄ…tkiem odwzorowania (%lld)\n" #: .././io/mmap.c:84 #, c-format msgid "offset (%lld) is beyond end of mapping (%lld)\n" msgstr "offset (%lld) za koÅ„cem odwzorowania (%lld)\n" #: .././io/mmap.c:89 #, c-format msgid "range (%lld:%lld) is beyond mapping (%lld:%ld)\n" msgstr "przedziaÅ‚ (%lld:%lld) poza odwzorowaniem (%lld:%ld)\n" #: .././io/mmap.c:95 #, c-format msgid "offset address (%p) is not page aligned\n" msgstr "adres offsetu (%p) nie jest wyrównany do rozmiaru strony\n" #: .././io/mmap.c:135 #, fuzzy, c-format msgid "" "\n" " maps a range within the current file into memory\n" "\n" " Example:\n" " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" "\n" " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" " With no arguments, mmap shows the current mappings. The current mapping\n" " can be set by using the single argument form (mapping number or address).\n" " If two arguments are specified (a range), a new mapping is created and the\n" " following options are available:\n" " -r -- map with PROT_READ protection\n" " -w -- map with PROT_WRITE protection\n" " -x -- map with PROT_EXEC protection\n" " -s -- first do mmap(size)/munmap(size), try to reserve some free " "space\n" " If no protection mode is specified, all are used by default.\n" "\n" msgstr "" "\n" " odwzorowanie przedziaÅ‚u z bieżącego pliku w pamiÄ™ci\n" "\n" "PrzykÅ‚ad:\n" " 'mmap -rw 0 1m' - odwzorowuje 1MB od poczÄ…tku bieżącego pliku\n" "\n" " mmap odwzorowuje w pamiÄ™ci przedziaÅ‚ z pliku do dalszego wykorzystania " "przez\n" " inne polecenia xfs_io.\n" " Bez argumentów mmap pokazuje aktualne odwzorowania. Bieżące odwzorowanie\n" " można ustawić przy użyciu formy jednoargumentowej (mmap numer lub adres).\n" " JeÅ›li podano dwa argumenty (przedziaÅ‚), tworzone jest nowe odwzorowanie\n" " i dostÄ™pne sÄ… nastÄ™pujÄ…ce opcje:\n" " -r - odwzorowanie z ochronÄ… PROT_READ\n" " -w - odwzorowanie z ochronÄ… PROT_WRITE\n" " -x - odwzorowanie z ochronÄ… PROT_EXEC\n" " JeÅ›li nie podano trybu ochrony, domyÅ›lnie używane sÄ… wszystkie.\n" "\n" #: .././io/mmap.c:273 #, c-format msgid "" "\n" " flushes a range of bytes in the current memory mapping\n" "\n" " Writes all modified copies of pages over the specified range (or entire\n" " mapping if no range specified) to their backing storage locations. Also,\n" " optionally invalidates so that subsequent references to the pages will be\n" " obtained from their backing storage locations (instead of cached copies).\n" " -a -- perform asynchronous writes (MS_ASYNC)\n" " -i -- invalidate mapped pages (MS_INVALIDATE)\n" " -s -- perform synchronous writes (MS_SYNC)\n" "\n" msgstr "" "\n" " zrzucenie przedziaÅ‚u bajtów w bieżącym odwzorowaniu pamiÄ™ci\n" "\n" " msync zapisuje wszystkie zmodyfikowane kopie stron z podanego przedziaÅ‚u\n" " (lub caÅ‚ego odwzorowania, jeÅ›li nie podano przedziaÅ‚u) do miejsca\n" " przechowywania danych. Opcjonalnie unieważnia bufor, żeby dalsze odwoÅ‚ania\n" " do tych stron odbywaÅ‚y siÄ™ z miejsca przechowywania danych (zamiast kopii\n" " w pamiÄ™ci podrÄ™cznej).\n" " -a - wykonanie zapisu asynchronicznego (MS_ASYNC)\n" " -i - unieważnienie odwzorowanych stron (MS_INVALIDATE)\n" " -s - wykonanie zapisu synchronicznego (MS_SYNC)\n" "\n" #: .././io/mmap.c:349 #, c-format msgid "" "\n" " reads a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n" "\n" " Accesses a range of the current memory mapping, optionally dumping it to\n" " the standard output stream (with -v option) for subsequent inspection.\n" " -f -- verbose mode, dump bytes with offsets relative to start of file.\n" " -r -- reverse order; start accessing from the end of range, moving " "backward\n" " -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n" " The accesses are performed sequentially from the start offset by default.\n" " Notes:\n" " References to whole pages following the end of the backing file results\n" " in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n" " on various filesystem conditions, including quota exceeded errors, and\n" " for physical device errors (such as unreadable disk blocks). No attempt\n" " has been made to catch signals at this stage...\n" "\n" msgstr "" "\n" " odczytanie przedziaÅ‚u bajtów w bieżącym odwzorowaniu pamiÄ™ci\n" "\n" " PrzykÅ‚ad:\n" " 'mread -v 512 20' - zrzucenie 20 bajtów odczytanych od 512 bajtu\n" " w odwzorowaniu\n" "\n" " mread odwoÅ‚uje siÄ™ do przedziaÅ‚u bieżącego odwzorowania pamiÄ™ci, " "opcjonalnie\n" " zrzucajÄ…c go na strumieÅ„ standardowego wyjÅ›cia (z opcjÄ… -v) do dalszych " "badaÅ„.\n" " -f - tryb szczegółowy, zrzucenie bajtów z offsetami wzglÄ™dem poczÄ…tku " "pliku.\n" " -r - odwrotna kolejność; dostÄ™p poczÄ…wszy od koÅ„ca przedziaÅ‚u do poczÄ…tku.\n" " -v - tryb szczegółowy, zrzucenie bajtów z offsetami wzglÄ™dem poczÄ…tku\n" " odwzorowania.\n" " DostÄ™py sÄ… wykonywane sekwencyjnie, domyÅ›lnie od offsetu poczÄ…tkowego.\n" " Uwagi:\n" " OdwoÅ‚ania do caÅ‚ych stron za koÅ„cem pliku powodujÄ… w efekcie sygnaÅ‚ " "SIGBUS.\n" " SygnaÅ‚y SIGBUS mogÄ… być wywoÅ‚ane także przy różnych zdarzeniach " "zwiÄ…zanych\n" " z systemem plików, włącznie z błędami przekroczenia limitów (quota) oraz\n" " fizycznymi błędami urzÄ…dzenia (takimi jak nieczytelne bloki dysku). Na " "tym\n" " etapie nie ma prób wyÅ‚apania sygnałów...\n" "\n" #: .././io/mmap.c:513 #, c-format msgid "" "\n" " dirties a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n" "\n" " Stores a byte into memory for a range within a mapping.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -S -- use an alternate seed character\n" " -r -- reverse order; start storing from the end of range, moving backward\n" " The stores are performed sequentially from the start offset by default.\n" "\n" msgstr "" "\n" " zmiana przedziaÅ‚u bajtów w bieżącym odwzorowaniu pamiÄ™ci\n" "\n" " PrzykÅ‚ad:\n" " 'mwrite 512 20' - zapisuje 20 bajtów od 512 bajtu w bieżącym odwzorowaniu.\n" "\n" " mwrite zapisuje bajt do przedziaÅ‚u pamiÄ™ci w ramach odwzorowania.\n" " DomyÅ›lnie zapisywanÄ… wartoÅ›ciÄ… jest 'X', powtarzane do wypeÅ‚nienia " "przedziaÅ‚u.\n" " -S - użycie alternatywnego znaku\n" " -r - odwrotna kolejność; rozpoczÄ™cie zapisywania od koÅ„ca przedziaÅ‚u do\n" " poczÄ…tku\n" " Zapisy sÄ… wykonywane kolejno, domyÅ›lnie od offsetu poczÄ…tkowego.\n" "\n" #: .././io/mmap.c:549 .././io/pread.c:439 .././io/pwrite.c:305 #: .././io/pwrite.c:332 #, c-format msgid "non-numeric seed -- %s\n" msgstr "nieliczbowy zarodek - %s\n" #: .././io/mmap.c:601 #, c-format msgid "" "\n" " resizes the current memory mapping\n" "\n" " Examples:\n" " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" "\n" " Resizes the mappping, growing or shrinking from the current size.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -f -- use MREMAP_FIXED flag to mremap on new_address\n" " -m -- use the MREMAP_MAYMOVE flag\n" "\n" msgstr "" #: .././io/mmap.c:678 #, fuzzy msgid "[N] | [-rwx] [-s size] [off len]" msgstr "[N] | [-rwx] [offset dÅ‚ugość]" #: .././io/mmap.c:680 msgid "mmap a range in the current file, show mappings" msgstr "odwzorowanie przedziaÅ‚u w bieżącym pliku, pokazanie odwzorowaÅ„" #: .././io/mmap.c:689 msgid "[-r] [off len]" msgstr "[-r] [offset dÅ‚ugość]" #: .././io/mmap.c:691 msgid "reads data from a region in the current memory mapping" msgstr "odczyt danych z regionu w bieżącym odwzorowaniu pamiÄ™ci" #: .././io/mmap.c:700 msgid "[-ais] [off len]" msgstr "[-ais] [offset dÅ‚ugość]" #: .././io/mmap.c:701 msgid "flush a region in the current memory mapping" msgstr "zrzucenie regionu w bieżącym odwzorowaniu pamiÄ™ci" #: .././io/mmap.c:710 msgid "unmaps the current memory mapping" msgstr "usuniÄ™cie bieżącego odwzorowania pamiÄ™ci" #: .././io/mmap.c:718 msgid "[-r] [-S seed] [off len]" msgstr "[-r] [-S wartość] [offset dÅ‚ugość]" #: .././io/mmap.c:720 msgid "writes data into a region in the current memory mapping" msgstr "zapis danych do regionu w bieżącym odwzorowaniu pamiÄ™ci" #: .././io/mmap.c:730 msgid "[-m|-f ] newsize" msgstr "" #: .././io/mmap.c:732 #, fuzzy msgid "alters the size of the current memory mapping" msgstr "usuniÄ™cie bieżącego odwzorowania pamiÄ™ci" #: .././io/open.c:69 msgid "socket" msgstr "gniazdo" #: .././io/open.c:71 .././repair/da_util.c:105 msgid "directory" msgstr "katalog" #: .././io/open.c:73 msgid "char device" msgstr "urzÄ…dzenie znakowe" #: .././io/open.c:75 msgid "block device" msgstr "urzÄ…dzenie blokowe" #: .././io/open.c:77 msgid "regular file" msgstr "plik zwykÅ‚y" #: .././io/open.c:79 msgid "symbolic link" msgstr "dowiÄ…zanie symboliczne" #: .././io/open.c:81 msgid "fifo" msgstr "potok" #: .././io/open.c:96 .././io/open.c:709 #, c-format msgid "fd.path = \"%s\"\n" msgstr "fd.path = \"%s\"\n" #: .././io/open.c:97 #, c-format msgid "fd.flags = %s,%s,%s%s%s%s%s\n" msgstr "fd.flags = %s,%s,%s%s%s%s%s\n" #: .././io/open.c:108 #, c-format msgid "stat.ino = %lld\n" msgstr "stat.ino = %lld\n" #: .././io/open.c:109 #, c-format msgid "stat.type = %s\n" msgstr "stat.type = %s\n" #: .././io/open.c:110 #, c-format msgid "stat.size = %lld\n" msgstr "stat.size = %lld\n" #: .././io/open.c:111 #, c-format msgid "stat.blocks = %lld\n" msgstr "stat.blocks = %lld\n" #: .././io/open.c:113 #, c-format msgid "stat.atime = %s" msgstr "stat.atime = %s" #: .././io/open.c:114 #, c-format msgid "stat.mtime = %s" msgstr "stat.mtime = %s" #: .././io/open.c:115 #, c-format msgid "stat.ctime = %s" msgstr "stat.ctime = %s" #: .././io/open.c:124 #, c-format msgid "fsxattr.xflags = 0x%x " msgstr "fsxattr.xflags = 0x%x " #: .././io/open.c:126 #, c-format msgid "fsxattr.projid = %u\n" msgstr "fsxattr.projid = %u\n" #: .././io/open.c:127 #, c-format msgid "fsxattr.extsize = %u\n" msgstr "fsxattr.extsize = %u\n" #: .././io/open.c:128 #, fuzzy, c-format msgid "fsxattr.cowextsize = %u\n" msgstr "fsxattr.extsize = %u\n" #: .././io/open.c:129 #, c-format msgid "fsxattr.nextents = %u\n" msgstr "fsxattr.nextents = %u\n" #: .././io/open.c:130 #, c-format msgid "fsxattr.naextents = %u\n" msgstr "fsxattr.naextents = %u\n" #: .././io/open.c:135 #, c-format msgid "dioattr.mem = 0x%x\n" msgstr "dioattr.mem = 0x%x\n" #: .././io/open.c:136 #, c-format msgid "dioattr.miniosz = %u\n" msgstr "dioattr.miniosz = %u\n" #: .././io/open.c:137 #, c-format msgid "dioattr.maxiosz = %u\n" msgstr "dioattr.maxiosz = %u\n" #: .././io/open.c:256 #, c-format msgid "" "\n" " opens a new file in the requested mode\n" "\n" " Example:\n" " 'open -cd /tmp/data' - creates/opens data file read-write for direct IO\n" "\n" " Opens a file for subsequent use by all of the other xfs_io commands.\n" " With no arguments, open uses the stat command to show the current file.\n" " -a -- open with the O_APPEND flag (append-only mode)\n" " -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n" " -f -- open with O_CREAT (create the file if it doesn't exist)\n" " -m -- permissions to use in case a new file is created (default 0600)\n" " -n -- open with O_NONBLOCK\n" " -r -- open with O_RDONLY, the default is O_RDWR\n" " -s -- open with O_SYNC\n" " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n" " -R -- mark the file as a realtime XFS file immediately after opening it\n" " -T -- open with O_TMPFILE (create a file not visible in the namespace)\n" " Note1: usually read/write direct IO requests must be blocksize aligned;\n" " some kernels, however, allow sectorsize alignment for direct IO.\n" " Note2: the bmap for non-regular files can be obtained provided the file\n" " was opened correctly (in particular, must be opened read-only).\n" "\n" msgstr "" "\n" " otwarcie nowego pliku w żądanym trybie\n" "\n" " PrzykÅ‚ad:\n" " 'open -cd /tmp/data' - utworzenie/otwarcie pliku danych do odczytu i " "zapisu\n" " z bezpoÅ›rednim we/wy\n" "\n" " open otwiera plik do późniejszego wykorzystania przez wszystkie inne " "polecenia\n" " xfs_io.\n" " Bez argumentów używa polecenia stat do pokazania bieżącego pliku.\n" " -a - otwarcie z flagÄ… O_APPEND (w trybie tylko dopisywania)\n" " -d - otwarcie z flagÄ… O_DIRECT (niebuforowane we/wy, ograniczenia " "wyrównania)\n" " -f - otwarcie z flagÄ… O_CREAT (utworzenie pliku jeÅ›li nie istnieje)\n" " -m - uprawnienia do użycia w przypadku tworzenia pliku (domyÅ›lnie 0600)\n" " -n - otwarcie z flagÄ… O_NONBLOCK\n" " -r - otwarcie z flagÄ… O_RDONLY (domyÅ›lne jest O_RDWR)\n" " -s - otwarcie z flagÄ… O_SYNC\n" " -t - otwarcie z flagÄ… O_TRUNC (uciÄ™cie do zerowej dÅ‚ugoÅ›ci jeÅ›li istnieje)\n" " -R - oznaczenie pliku jako realtime na XFS-ie zaraz po otwarciu\n" " -T - otwarcie z flagÄ… O_TMPFILE (utworzenie pliku niewidocznego w " "przestrzni\n" " nazw)\n" " Uwaga1: zwykle żądania bezpoÅ›redniego we/wy muszÄ… być wyrównane do " "rozmiaru\n" " bloku; niektóre jÄ…dra pozwalajÄ… na wyrównanie do rozmiaru sektora\n" " Uwaga2: bmap dla plików innych niż zwykÅ‚e można uzyskać pod warunkiem, że\n" " plik zostanie poprawnie otwarty (w szczególnoÅ›ci tylko do " "odczytu).\n" "\n" #: .././io/open.c:348 #, c-format msgid "-T and -r options are incompatible\n" msgstr "Opcje -T i -r nie sÄ… zgodne ze sobÄ…\n" #: .././io/open.c:403 #, c-format msgid "" "\n" " displays the project identifier associated with the current path\n" "\n" " Options:\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, but only list projects on directories\n" "\n" msgstr "" "\n" " wyÅ›wietlenie identyfikatora projektu zwiÄ…zanego z bieżącÄ… Å›cieżkÄ…\n" "\n" " Opcje:\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale wypisywanie projektów tylko " "katalogów\n" "\n" #: .././io/open.c:469 #, c-format msgid "projid = %u\n" msgstr "projid = %u\n" #: .././io/open.c:477 #, c-format msgid "" "\n" " modifies the project identifier associated with the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying projects on directories\n" "\n" msgstr "" "\n" " modyfikacja identyfikatora projektu zwiÄ…zanego z bieżącÄ… Å›cieżkÄ…\n" "\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale zmiana projektów tylko katalogów\n" "\n" #: .././io/open.c:536 #, c-format msgid "invalid project ID -- %s\n" msgstr "nieprawidÅ‚owy ID projektu - %s\n" #: .././io/open.c:552 #, c-format msgid "" "\n" " report or modify preferred extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying extsize on directories\n" "\n" msgstr "" "\n" " odczyt lub zmiana preferowanego rozmiaru ekstentu (w bajtach) dla bieżącej\n" " Å›cieżki\n" "\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale zmiana extsize tylko katalogów\n" "\n" #: .././io/open.c:681 #, c-format msgid "non-numeric extsize argument -- %s\n" msgstr "nieliczbowy argument extsize - %s\n" #: .././io/open.c:713 #, c-format msgid "statfs.f_bsize = %lld\n" msgstr "statfs.f_bsize = %lld\n" #: .././io/open.c:714 #, c-format msgid "statfs.f_blocks = %lld\n" msgstr "statfs.f_blocks = %lld\n" #: .././io/open.c:716 #, c-format msgid "statfs.f_frsize = %lld\n" msgstr "statfs.f_frsize = %lld\n" #: .././io/open.c:718 #, c-format msgid "statfs.f_bavail = %lld\n" msgstr "statfs.f_bavail = %lld\n" #: .././io/open.c:720 #, c-format msgid "statfs.f_files = %lld\n" msgstr "statfs.f_files = %lld\n" #: .././io/open.c:721 #, c-format msgid "statfs.f_ffree = %lld\n" msgstr "statfs.f_ffree = %lld\n" #: .././io/open.c:728 #, c-format msgid "geom.bsize = %u\n" msgstr "geom.bsize = %u\n" #: .././io/open.c:729 #, c-format msgid "geom.agcount = %u\n" msgstr "geom.agcount = %u\n" #: .././io/open.c:730 #, c-format msgid "geom.agblocks = %u\n" msgstr "geom.agblocks = %u\n" #: .././io/open.c:731 #, c-format msgid "geom.datablocks = %llu\n" msgstr "geom.datablocks = %llu\n" #: .././io/open.c:733 #, c-format msgid "geom.rtblocks = %llu\n" msgstr "geom.rtblocks = %llu\n" #: .././io/open.c:735 #, c-format msgid "geom.rtextents = %llu\n" msgstr "geom.rtextents = %llu\n" #: .././io/open.c:737 #, c-format msgid "geom.rtextsize = %u\n" msgstr "geom.rtextsize = %u\n" #: .././io/open.c:738 #, c-format msgid "geom.sunit = %u\n" msgstr "geom.sunit = %u\n" #: .././io/open.c:739 #, c-format msgid "geom.swidth = %u\n" msgstr "geom.swidth = %u\n" #: .././io/open.c:744 #, c-format msgid "counts.freedata = %llu\n" msgstr "counts.freedata = %llu\n" #: .././io/open.c:746 #, c-format msgid "counts.freertx = %llu\n" msgstr "counts.freertx = %llu\n" #: .././io/open.c:748 #, c-format msgid "counts.freeino = %llu\n" msgstr "counts.freeino = %llu\n" #: .././io/open.c:750 #, c-format msgid "counts.allocino = %llu\n" msgstr "counts.allocino = %llu\n" #: .././io/open.c:760 #, c-format msgid "" "\n" "Query physical information about an inode\n" " Default:\t-- Return 1 if any inode number greater than 32 bits exists in\n" "\t\t the filesystem, or 0 if none exist\n" " num\t\t-- Return inode number [num] if in use, or 0 if not in use\n" " -n num\t-- Return the next used inode after [num]\n" " -v\t\t-- Verbose mode - display returned inode number's size in bits\n" "\n" msgstr "" #: .././io/open.c:843 #, fuzzy, c-format msgid "%s is not a numeric inode value\n" msgstr "%s nie jest liczbÄ…\n" #: .././io/open.c:922 #, fuzzy msgid "[-acdrstxT] [-m mode] [path]" msgstr "[-acdrstxT] [Å›cieżka]" #: .././io/open.c:923 msgid "open the file specified by path" msgstr "otwarcie pliku okreÅ›lonego Å›cieżkÄ…" #: .././io/open.c:931 msgid "[-v]" msgstr "[-v]" #: .././io/open.c:932 msgid "statistics on the currently open file" msgstr "statystyki dla aktualnie otwartego pliku" #: .././io/open.c:940 msgid "close the current open file" msgstr "zamkniÄ™cie bieżącego otwartego pliku" #: .././io/open.c:946 msgid "statistics on the filesystem of the currently open file" msgstr "statystyki dla systemu plików aktualnie otwartego pliku" #: .././io/open.c:950 msgid "[-D | -R] projid" msgstr "[-D | -R] projid" #: .././io/open.c:955 msgid "change project identifier on the currently open file" msgstr "zmiana identyfikatora projektu aktualnie otwartego pliku" #: .././io/open.c:960 msgid "[-D | -R]" msgstr "[-D | -R]" #: .././io/open.c:965 msgid "list project identifier set on the currently open file" msgstr "wypisanie identyfikatora projektu aktualnie otwartego pliku" #: .././io/open.c:970 msgid "[-D | -R] [extsize]" msgstr "[-D | -R] [rozmiar_fragmentu]" #: .././io/open.c:975 msgid "get/set preferred extent size (in bytes) for the open file" msgstr "" "pobranie/ustawienie preferowanego rozmiaru ekstentu (w bajtach) dla " "otwartego pliku" #: .././io/open.c:980 #, fuzzy msgid "[-nv] [num]" msgstr "[-alv] [-n nx]" #: .././io/open.c:985 #, fuzzy msgid "Query inode number usage in the filesystem" msgstr "błąd - za maÅ‚o wolnego miejsca w systemie plików\n" #: .././io/parent.c:48 #, c-format msgid "%s%s" msgstr "%s%s" #: .././io/parent.c:53 #, c-format msgid "inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n" msgstr "" "inode-path dla i-wÄ™zÅ‚a: %llu jest niepoprawna - Å›cieżka \"%s\" nie istnieje\n" #: .././io/parent.c:57 #, c-format msgid "path \"%s\" does not stat for inode: %llu; err = %s\n" msgstr "Å›cieżka \"%s\" nie pozwala na stat dla i-wÄ™zÅ‚a: %llu; błąd = %s\n" #: .././io/parent.c:66 #, c-format msgid "path \"%s\" found\n" msgstr "Å›cieżki \"%s\" nie znaleziono\n" #: .././io/parent.c:72 #, c-format msgid "inode-path for inode: %llu is incorrect - wrong inode#\n" msgstr "" "inode-path dla i-wÄ™zÅ‚a: %llu jest niepoprawna - niewÅ‚aÅ›ciwy numer i-wÄ™zÅ‚a\n" #: .././io/parent.c:76 .././io/parent.c:106 #, c-format msgid "ino mismatch for path \"%s\" %llu vs %llu\n" msgstr "niezgodność i-wÄ™zÅ‚a dla Å›cieżki \"%s\" %llu vs %llu\n" #: .././io/parent.c:84 #, c-format msgid "inode number match: %llu\n" msgstr "zgodność numeru i-wÄ™zÅ‚a: %llu\n" #: .././io/parent.c:94 #, c-format msgid "parent path \"%s\" does not stat: %s\n" msgstr "Å›cieżka nadrzÄ™dna \"%s\" nie pozwala na stat: %s\n" #: .././io/parent.c:102 #, c-format msgid "inode-path for inode: %llu is incorrect - wrong parent inode#\n" msgstr "" "inode-path dla i-wÄ™zÅ‚a: %llu jest niepoprawna - niewÅ‚aÅ›ciwy numer i-wÄ™zÅ‚a " "nadrzÄ™dnego\n" #: .././io/parent.c:115 #, c-format msgid "parent ino match for %llu\n" msgstr "zgodność numeru i-wÄ™zÅ‚a nadrzÄ™dnego dla %llu\n" #: .././io/parent.c:137 #, c-format msgid "parentpaths failed for ino %llu: %s\n" msgstr "parentpaths nie powiodÅ‚o siÄ™ dla i-wÄ™zÅ‚a %llu: %s\n" #: .././io/parent.c:148 #, c-format msgid "inode-path for inode: %llu is missing\n" msgstr "brak inode-path dla i-wÄ™zÅ‚a: %llu\n" #: .././io/parent.c:172 #, c-format msgid "can't stat mount point \"%s\": %s\n" msgstr "nie można wykonać stat na punkcie montowania \"%s\": %s\n" #: .././io/parent.c:193 #, c-format msgid "failed to get bulkstat information for inode %llu\n" msgstr "nie udaÅ‚o siÄ™ uzyskać informacji bulkstat dla i-wÄ™zÅ‚a %llu\n" #: .././io/parent.c:199 #, c-format msgid "failed to get valid bulkstat information for inode %llu\n" msgstr "" "nie udaÅ‚o siÄ™ uzyskać prawidÅ‚owych informacji bulkstat dla i-wÄ™zÅ‚a %llu\n" #: .././io/parent.c:211 #, c-format msgid "checking inode %llu\n" msgstr "sprawdzanie i-wÄ™zÅ‚a %llu\n" #: .././io/parent.c:226 #, c-format msgid "syssgi bulkstat failed: %s\n" msgstr "syssgi bulkstat nie powiodÅ‚o siÄ™: %s\n" #: .././io/parent.c:248 #, c-format msgid "unable to open \"%s\" for jdm: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć \"%s\" dla jdm: %s\n" #: .././io/parent.c:258 #, c-format msgid "unable to allocate buffers: %s\n" msgstr "nie udaÅ‚o siÄ™ przydzielić buforów: %s\n" #: .././io/parent.c:268 #, c-format msgid "num errors: %d\n" msgstr "liczba błędów: %d\n" #: .././io/parent.c:270 #, c-format msgid "succeeded checking %llu inodes\n" msgstr "udaÅ‚o siÄ™ sprawdzić %llu i-wÄ™złów\n" #: .././io/parent.c:283 #, c-format msgid "p_ino = %llu\n" msgstr "p_ino = %llu\n" #: .././io/parent.c:284 #, c-format msgid "p_gen = %u\n" msgstr "p_gen = %u\n" #: .././io/parent.c:285 #, c-format msgid "p_reclen = %u\n" msgstr "p_reclen = %u\n" #: .././io/parent.c:287 #, c-format msgid "p_name = \"%s%s\"\n" msgstr "p_name = \"%s%s\"\n" #: .././io/parent.c:289 #, c-format msgid "p_name = \"%s\"\n" msgstr "p_name = \"%s\"\n" #: .././io/parent.c:311 #, c-format msgid "%s: failed path_to_fshandle \"%s\": %s\n" msgstr "%s: path_to_fshandle nie powiodÅ‚o siÄ™ dla \"%s\": %s\n" #: .././io/parent.c:319 #, c-format msgid "%s: path_to_handle failed for \"%s\"\n" msgstr "%s: path_to_handle nie powiodÅ‚o siÄ™ dla \"%s\"\n" #: .././io/parent.c:326 #, c-format msgid "%s: unable to allocate parent buffer: %s\n" msgstr "%s: nie udaÅ‚o siÄ™ przydzielić bufora nadrzÄ™dnego: %s\n" #: .././io/parent.c:347 #, c-format msgid "%s: %s call failed for \"%s\": %s\n" msgstr "%s: wywoÅ‚anie %s nie powiodÅ‚o siÄ™ dla \"%s\": %s\n" #: .././io/parent.c:356 #, c-format msgid "%s: inode-path is missing\n" msgstr "%s: brak inode-path\n" #: .././io/parent.c:388 #, c-format msgid "file argument, \"%s\", is not in a mounted XFS filesystem\n" msgstr "" "argument plikowy \"%s\" nie jest na podmontowanym systemie plików XFS\n" #: .././io/parent.c:428 #, c-format msgid "" "\n" " list the current file's parents and their filenames\n" "\n" " -c -- check the current file's file system for parent consistency\n" " -p -- list the current file's parents and their full paths\n" " -v -- verbose mode\n" "\n" msgstr "" "\n" " wypisanie rodziców bieżącego pliku i ich nazw\n" "\n" " -c - sprawdzenie systemu plików pod kÄ…tem spójnoÅ›ci rodziców pliku\n" " -p - wypisanie rodziców bieżącego pliku i ich peÅ‚nych Å›cieżek\n" " -v - tryb szczegółowy\n" "\n" #: .././io/parent.c:444 msgid "[-cpv]" msgstr "[-cpv]" #: .././io/parent.c:446 msgid "print or check parent inodes" msgstr "wypisanie lub sprawdzenie i-wÄ™złów nadrzÄ™dnych" #: .././io/pread.c:32 #, c-format msgid "" "\n" " reads a range of bytes in a specified block size from the given offset\n" "\n" " Example:\n" " 'pread -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n" "\n" " Reads a segment of the currently open file, optionally dumping it to the\n" " standard output stream (with -v option) for subsequent inspection.\n" " The reads are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different pattern is requested.\n" " -B -- read backwards through the range from offset (backwards N bytes)\n" " -F -- read forwards through the range of bytes from offset (default)\n" " -v -- be verbose, dump out buffers (used when reading forwards)\n" " -R -- read at random offsets in the range of bytes\n" " -Z N -- zeed the random number generator (used when reading randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" " -V N -- use vectored IO with N iovecs of blocksize each (preadv)\n" "\n" " When in \"random\" mode, the number of read operations will equal the\n" " number required to do a complete forward/backward scan of the range.\n" " Note that the offset within the range is chosen at random each time\n" " (an offset may be read more than once when operating in this mode).\n" "\n" msgstr "" "\n" " odczytanie przedziaÅ‚u bajtów w podanym rozmiarze bloku od podanego offsetu\n" "\n" " PrzykÅ‚ad:\n" " 'pread -v 512 20' - zrzucenie 20 bajtów odczytanych od 512 bajtu w pliku\n" "\n" " pread odczytuje segment aktualnie otwartego pliku, opcjonalnie zrzucajÄ…c\n" " zawartość na strumieÅ„ standardowego wyjÅ›cia (z opcjÄ… -v) dla dalszych " "badaÅ„.\n" " Odczyty sÄ… wykonywane sekwencyjnie blokami poczÄ…wszy od offsetu z " "rozmiarem\n" " bloku ustawianym przy użyciu opcji -b (domyÅ›lny rozmiar bloku to 4096 " "bajtów),\n" " chyba że zażądano innego schematu.\n" " -B - odczyt przedziaÅ‚u od tyÅ‚u poczÄ…wszy od offsetu (N bajtów do tyÅ‚u)\n" " -F - odczyt przedziaÅ‚u od przodu poczÄ…wszy od offsetu (domyÅ›lny)\n" " -v - tryb szczegółowy, zrzucenie bufora (przy odczycie od przodu)\n" " -R - odczyt losowych offsetów z przedziaÅ‚u bajtów\n" " -Z N - (\"zeed\") nakarmienie generatora liczb losowych (przy odczycie " "losowym)\n" " (nieztety opcje -s/-S pasujÄ…ce do \"seed\" byÅ‚y już zajÄ™te w " "pwrite)\n" " -V N - użycie wektorowego we/wy z N iovec, każdym o rozmiarze blocksize\n" " (preadv)\n" "\n" " W przypadku trybu losowego liczba operacji odczytu bÄ™dzie równa liczbie\n" " potrzebnej do peÅ‚nego przeskanowania od przodu lub od tyÅ‚u caÅ‚ego " "przedziaÅ‚u.\n" " Należy zauważyć, że offset w przedziale jest wybierany za każdym razem " "losowo\n" " (dowolny offset może być w tym trybie czytany wiÄ™cej niż raz).\n" "\n" #: .././io/pread.c:400 .././io/pwrite.c:271 #, c-format msgid "non-numeric bsize -- %s\n" msgstr "nieliczbowy rozmiar bloku - %s\n" #: .././io/pread.c:430 .././io/pwrite.c:318 #, c-format msgid "non-numeric vector count == %s\n" msgstr "nieliczbowa liczba wektorów - %s\n" #: .././io/pread.c:507 msgid "[-b bs] [-v] [-i N] [-FBR [-Z N]] off len" msgstr "[-b rozm_bloku] [-v] [-i N] [-FBR [-Z N]] offset dÅ‚ugość" #: .././io/pread.c:508 msgid "reads a number of bytes at a specified offset" msgstr "odczyt podanej liczby bajtów od podanego offsetu" #: .././io/prealloc.c:175 #, c-format msgid "" "\n" " modifies space associated with part of a file via fallocate\n" " Example:\n" " 'falloc 0 1m' - fills all holes within the first megabyte\n" "\n" " falloc uses the fallocate system call to alter space allocations in the\n" " open file. The following operations are supported:\n" " All the file offsets are in units of bytes.\n" " -c -- collapses the given range.\n" " -i -- inserts a hole into the given range of the file.\n" " -k -- do not change file size.\n" " -p -- unmap the given range from the file.\n" " -u -- unshare shared extents in the given range.\n" "\n" msgstr "" #: .././io/prealloc.c:347 .././io/prealloc.c:355 .././io/prealloc.c:363 #: .././io/prealloc.c:371 .././io/prealloc.c:381 .././io/prealloc.c:408 #: .././io/prealloc.c:418 .././io/prealloc.c:428 .././io/prealloc.c:448 msgid "off len" msgstr "offset dÅ‚ugość" #: .././io/prealloc.c:348 msgid "allocates zeroed space for part of a file" msgstr "przydzielenie wyzerowanej przestrzeni dla części pliku" #: .././io/prealloc.c:356 msgid "frees space associated with part of a file" msgstr "zwolnienie miejsca zwiÄ…zanego z częściÄ… pliku" #: .././io/prealloc.c:365 msgid "reserves space associated with part of a file" msgstr "zarezerwowanie miejsca zwiÄ…zanego z częściÄ… pliku" #: .././io/prealloc.c:374 msgid "frees reserved space associated with part of a file" msgstr "zwolnienie zarezerwowanego miejsca zwiÄ…zanego z częściÄ… pliku" #: .././io/prealloc.c:383 msgid "Converts the given range of a file to allocated zeros" msgstr "Zamiana podanego przedziaÅ‚u pliku na przydzielone zera" #: .././io/prealloc.c:397 #, fuzzy msgid "[-c] [-k] [-p] [-u] off len" msgstr "[-c] [-k] [-p] offset dÅ‚ugość" #: .././io/prealloc.c:399 msgid "allocates space associated with part of a file via fallocate" msgstr "przydzielenie miejsca powiÄ…zanego z częściÄ… pliku przez fallocate" #: .././io/prealloc.c:410 msgid "de-allocates space assocated with part of a file via fallocate" msgstr "zwolnienie miejsca powiÄ…zanego z częściÄ… pliku przez fallocate" #: .././io/prealloc.c:420 msgid "de-allocates space and eliminates the hole by shifting extents" msgstr "zwolnienie miejsca i usuniÄ™cie dziury poprzez przesuniÄ™cie ekstentów" #: .././io/prealloc.c:430 #, fuzzy msgid "creates new space for writing within file by shifting extents" msgstr "zwolnienie miejsca i usuniÄ™cie dziury poprzez przesuniÄ™cie ekstentów" #: .././io/prealloc.c:438 msgid "[-k] off len" msgstr "[-k] offset dÅ‚ugość" #: .././io/prealloc.c:440 msgid "zeroes space and eliminates holes by preallocating" msgstr "wyzerowanie miejsca i usuniÄ™cie dziur poprzez prealokacjÄ™" #: .././io/prealloc.c:450 msgid "unshares shared blocks within the range" msgstr "" #: .././io/pwrite.c:31 #, c-format msgid "" "\n" " writes a range of bytes (in block size increments) from the given offset\n" "\n" " Example:\n" " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Writes into a segment of the currently open file, using either a buffer\n" " filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n" " The writes are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different write pattern is requested.\n" " -S -- use an alternate seed number for filling the write buffer\n" " -i -- input file, source of data to write (used when writing forward)\n" " -d -- open the input file for direct IO\n" " -s -- skip a number of bytes at the start of the input file\n" " -w -- call fdatasync(2) at the end (included in timing results)\n" " -W -- call fsync(2) at the end (included in timing results)\n" " -B -- write backwards through the range from offset (backwards N bytes)\n" " -F -- write forwards through the range of bytes from offset (default)\n" " -R -- write at random offsets in the specified range of bytes\n" " -Z N -- zeed the random number generator (used when writing randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" " -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n" "\n" msgstr "" "\n" " zapisanie przedziaÅ‚u bajtów w podanym rozmiarze bloku od podanego offsetu\n" "\n" " PrzykÅ‚ad:\n" " 'pwrite 512 20' - zapisanie 20 bajtów odczytanych od 512 bajtu w pliku\n" "\n" " pwrite zapisuje segment aktualnie otwartego pliku, używajÄ…c bufora " "wypeÅ‚nionego\n" " ustawionym wzorcem (0xcdcdcdcd) lub danymi odczytanymi z pliku " "wejÅ›ciowego.\n" " Zapisy sÄ… wykonywane sekwencyjnie blokami poczÄ…wszy od offsetu z rozmiarem\n" " bloku ustawianym przy użyciu opcji -b (domyÅ›lny rozmiar bloku to 4096 " "bajtów),\n" " chyba że zażądano innego schematu.\n" " -S - użycie innej liczby do wypeÅ‚nienia bufora zapisu\n" " -i - plik wejÅ›ciowy, źródÅ‚o danych do zapisania (przy pisaniu od przodu)\n" " -d - otwarcie pliku wejÅ›ciowego dla bezpoÅ›redniego we/wy\n" " -s - pominiÄ™cie podanej liczby bajtów od poczÄ…tku pliku wejÅ›ciowego\n" " -w - wywoÅ‚anie fdatasync(2) na koÅ„cu (wliczane w wyniki czasowe)\n" " -W - wywoÅ‚anie fsync(2) na koÅ„cu (wliczane w wyniki czasowe)\n" " -B - zapis przedziaÅ‚u od tyÅ‚u poczÄ…wszy od offsetu (N bajtów do tyÅ‚u)\n" " -F - zapis przedziaÅ‚u od przodu poczÄ…wszy od offsetu (domyÅ›lny)\n" " -R - zapis losowych offsetów z przedziaÅ‚u bajtów\n" " -Z N - (\"zeed\") nakarmienie generatora liczb losowych (przy zapisie " "losowym)\n" " (niestety opcje -s/-S pasujÄ…ce do \"seed\" byÅ‚y już zajÄ™te w " "pwrite)\n" " -V N - użycie wektorowego we/wy z N iovec, każdym o rozmiarze blocksize\n" " (pwritev)\n" "\n" #: .././io/pwrite.c:298 #, c-format msgid "non-numeric skip -- %s\n" msgstr "nieliczbowy liczba bajtów do pominiÄ™cia - %s\n" #: .././io/pwrite.c:409 msgid "" "[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] [-FBR [-Z N]] [-V N] off " "len" msgstr "" "[-i plik_wej [-d] [-s do_pominiÄ™cia]] [-b rozm_bloku] [-S zarodek] [-wW] [-" "FBR [-Z N]] [-V N] offset dÅ‚ugość" #: .././io/pwrite.c:411 msgid "writes a number of bytes at a specified offset" msgstr "zapis podanej liczby bajtów od podanego offsetu" #: .././io/readdir.c:193 #, c-format msgid "read %llu bytes from offset %lld\n" msgstr "odczytano %llu bajtów z offsetu %lld\n" #: .././io/readdir.c:194 #, c-format msgid "%s, %d ops, %s (%s/sec and %.4f ops/sec)\n" msgstr "%s, %d operacji; %s (%s/sek i %.4f operacji/sek)\n" #: .././io/readdir.c:207 msgid "[-v][-o offset][-l length]" msgstr "[-v][-o offset][-l dÅ‚ugość]" #: .././io/readdir.c:208 msgid "read directory entries" msgstr "odczyt wpisów katalogu" #: .././io/reflink.c:32 #, c-format msgid "" "\n" " Links a range of bytes (in block size increments) from a file into a range\n" " of bytes in the open file. The contents of both file ranges must match.\n" "\n" " Example:\n" " 'dedupe some_file 0 4096 32768' - links 32768 bytes from some_file at\n" " offset 0 to into the open file at\n" " position 4096\n" "\n" " Reflink a range of blocks from a given input file to the open file. Both\n" " files share the same range of physical disk blocks; a write to the shared\n" " range of either file should result in the write landing in a new block and\n" " that range of the file being remapped (i.e. copy-on-write). Both files\n" " must reside on the same filesystem, and the contents of both ranges must\n" " match.\n" msgstr "" #: .././io/reflink.c:87 msgid "Extents did not match." msgstr "" #: .././io/reflink.c:141 .././io/reflink.c:264 #, fuzzy, c-format msgid "non-numeric src offset argument -- %s\n" msgstr "nieliczbowy argument bÄ™dÄ…cy offsetem - %s\n" #: .././io/reflink.c:147 .././io/reflink.c:270 #, fuzzy, c-format msgid "non-numeric dest offset argument -- %s\n" msgstr "nieliczbowy argument bÄ™dÄ…cy offsetem - %s\n" #: .././io/reflink.c:153 .././io/reflink.c:276 #, fuzzy, c-format msgid "non-positive length argument -- %s\n" msgstr "nieliczbowy argument bÄ™dÄ…cy dÅ‚ugoÅ›ciÄ… - %s\n" #: .././io/reflink.c:178 #, c-format msgid "" "\n" " Links a range of bytes (in block size increments) from a file into a range\n" " of bytes in the open file. The two extent ranges need not contain " "identical\n" " data.\n" "\n" " Example:\n" " 'reflink some_file 0 4096 32768' - links 32768 bytes from some_file at\n" " offset 0 to into the open file at\n" " position 4096\n" " 'reflink some_file' - links all bytes from some_file into the open file\n" " at position 0\n" "\n" " Reflink a range of blocks from a given input file to the open file. Both\n" " files share the same range of physical disk blocks; a write to the shared\n" " range of either file should result in the write landing in a new block and\n" " that range of the file being remapped (i.e. copy-on-write). Both files\n" " must reside on the same filesystem.\n" msgstr "" #: .././io/reflink.c:309 .././io/reflink.c:323 #, fuzzy msgid "infile src_off dst_off len" msgstr "-i plik_wej | -f N [offset dÅ‚ugość]" #: .././io/reflink.c:311 #, fuzzy msgid "reflinks a number of bytes at a specified offset" msgstr "odczyt podanej liczby bajtów od podanego offsetu" #: .././io/reflink.c:325 #, fuzzy msgid "dedupes a number of bytes at a specified offset" msgstr "odczyt podanej liczby bajtów od podanego offsetu" #: .././io/resblks.c:38 #, c-format msgid "non-numeric argument -- %s\n" msgstr "nieliczbowy argument - %s\n" #: .././io/resblks.c:50 #, c-format msgid "reserved blocks = %llu\n" msgstr "zarezerwowane bloki = %llu\n" #: .././io/resblks.c:52 #, c-format msgid "available reserved blocks = %llu\n" msgstr "dostÄ™pne zarezerwowane bloki = %llu\n" #: .././io/resblks.c:65 msgid "[blocks]" msgstr "[bloki]" #: .././io/resblks.c:67 msgid "get and/or set count of reserved filesystem blocks" msgstr "" "pobranie i/lub ustawienie liczby zarezerwowanych bloków w systemie plików" #: .././io/seek.c:32 #, c-format msgid "" "\n" " returns the next hole and/or data offset at or after the requested offset\n" "\n" " Example:\n" " 'seek -d 512'\t\t- offset of data at or following offset 512\n" " 'seek -a -r 0'\t- offsets of all data and hole in entire file\n" "\n" " Returns the offset of the next data and/or hole. There is an implied hole\n" " at the end of file. If the specified offset is past end of file, or there\n" " is no data past the specified offset, EOF is returned.\n" " -a\t-- return the next data and hole starting at the specified offset.\n" " -d\t-- return the next data starting at the specified offset.\n" " -h\t-- return the next hole starting at the specified offset.\n" " -r\t-- return all remaining type(s) starting at the specified offset.\n" " -s\t-- also print the starting offset.\n" "\n" msgstr "" "\n" " zwrócenie offsetu nastÄ™pnej dziury i/lub danych pod lub za żądanym " "offsetem\n" "\n" " PrzykÅ‚ady:\n" " 'seek -d 512' - offset danych pod lub za offsetem 512\n" " 'seek -a -r 0' - offsety wszystkich danych i dziur w caÅ‚ym pliku\n" "\n" " seek zwraca offset nastÄ™pnych danych i/lub dziury. Istnieje domyÅ›lna " "dziura\n" " na koÅ„cu pliku. JeÅ›li podany offset jest za koÅ„cem pliku lub nie ma danych\n" " za podanym offsetem, zwracany jest EOF.\n" " -a\t- nastÄ™pne dane i dziura od podanego offsetu\n" " -d\t- nastÄ™pne dane poczÄ…wszy od podanego offsetu\n" " -h\t- nastÄ™pna dziura poczÄ…wszy od podanego offsetu\n" " -r\t- wszystkie pozostaÅ‚e typy fragmentów od podanego offsetu\n" " -s\t- wypisane także offsetu poczÄ…tkowego\n" "\n" #: .././io/seek.c:218 msgid "-a | -d | -h [-r] off" msgstr "-a | -d | -h [-r] offset" #: .././io/seek.c:219 msgid "locate the next data and/or hole" msgstr "odnalezienie nastÄ™pnych danych i/lub dziury" #: .././io/sendfile.c:31 #, c-format msgid "" "\n" " transfer a range of bytes from the given offset between files\n" "\n" " Example:\n" " 'send -f 2 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Copies data between one file descriptor and another. Because this copying\n" " is done within the kernel, sendfile does not need to transfer data to and\n" " from user space.\n" " -f -- specifies an input file from which to source data to write\n" " -i -- specifies an input file name from which to source data to write.\n" " An offset and length in the source file can be optionally specified.\n" "\n" msgstr "" "\n" " przesÅ‚anie miÄ™dzy plikami przedziaÅ‚u bajtów od podanego offsetu\n" "\n" " PrzykÅ‚ad:\n" " 'send -f 2 512 20' - zapisanie 20 bajtów od 512 bajtu do otwartego pliku\n" "\n" " sendfile kopiuje dane miÄ™dzy jednym deskryptorem pliku a innym. Ponieważ " "to\n" " kopiowanie jest wykonywane przez jÄ…dro, sendfile nie potrzebuje przesyÅ‚ać\n" " danych do i z przestrzeni użytkownika.\n" " -f - podanie plików wejÅ›ciowego z którego dane majÄ… być czytane\n" " -i - podanie nazwy pliku wejÅ›ciowego z którego dane majÄ… być czytane\n" " Opcjonalnie można podać offset i dÅ‚ugość danych w pliku źródÅ‚owym.\n" "\n" #: .././io/sendfile.c:171 msgid "-i infile | -f N [off len]" msgstr "-i plik_wej | -f N [offset dÅ‚ugość]" #: .././io/sendfile.c:173 msgid "Transfer data directly between file descriptors" msgstr "PrzesÅ‚anie danych bezpoÅ›rednio miÄ™dzy deskryptorami plików" #: .././io/shutdown.c:58 msgid "[-f]" msgstr "[-f]" #: .././io/shutdown.c:60 msgid "shuts down the filesystem where the current file resides" msgstr "wyłączenie systemu plików na którym znajduje siÄ™ bieżący plik" #: .././io/sync.c:57 #, fuzzy msgid "calls sync(2) to flush all in-core filesystem state to disk" msgstr "wywoÅ‚anie fsync(2) aby zrzucić caÅ‚y stan pliku z pamiÄ™ci na dysk" #: .././io/sync.c:66 #, fuzzy msgid "calls syncfs(2) to flush all in-core filesystem state to disk" msgstr "wywoÅ‚anie fsync(2) aby zrzucić caÅ‚y stan pliku z pamiÄ™ci na dysk" #: .././io/sync_file_range.c:30 #, c-format msgid "" "\n" " Trigger specific writeback commands on a range of the current file\n" "\n" " With no options, the SYNC_FILE_RANGE_WRITE is implied.\n" " -a -- wait for IO to finish after writing (SYNC_FILE_RANGE_WAIT_AFTER).\n" " -b -- wait for IO to finish before writing (SYNC_FILE_RANGE_WAIT_BEFORE).\n" " -w -- write dirty data in range (SYNC_FILE_RANGE_WRITE).\n" "\n" msgstr "" "\n" " Wyzwolenie okreÅ›lonych poleceÅ„ zapisu w tle na pewnym zakresie bieżącego " "pliku\n" "\n" " Bez opcji przyjmowana jest operacja SYNC_FILE_RANGE_WRITE.\n" " -a - oczekiwanie na zakoÅ„czenie we/wy po zapisie " "(SYNC_FILE_RANGE_WAIT_AFTER).\n" " -b - oczekiwanie na zakoÅ„czenie we/wy przedtem " "(SYNC_FILE_RANGE_WAIT_BEFORE).\n" " -w - zapis zmodyfikowanych danych z zakresu (SYNC_FILE_RANGE_WRITE).\n" "\n" #: .././io/sync_file_range.c:101 msgid "[-abw] off len" msgstr "[-abw] offset dÅ‚ugość" #: .././io/sync_file_range.c:102 msgid "Control writeback on a range of a file" msgstr "Sterowanie zapisem w tle dla zakresu pliku" #: .././io/truncate.c:37 #, c-format msgid "non-numeric truncate argument -- %s\n" msgstr "nieliczbowy argument truncate - %s\n" #: .././io/truncate.c:57 msgid "off" msgstr "offset" #: .././io/truncate.c:59 msgid "truncates the current file at the given offset" msgstr "uciÄ™cie bieżącego pliku na podanym offsecie" #: .././libxcmd/command.c:85 #, c-format msgid "bad argument count %d to %s, expected at least %d arguments\n" msgstr "" "błędna liczba argumentów %d dla %s, oczekiwano co najmniej %d argumentów\n" #: .././libxcmd/command.c:89 #, c-format msgid "bad argument count %d to %s, expected %d arguments\n" msgstr "błędna liczba argumentów %d dla %s, oczekiwano %d argumentów\n" #: .././libxcmd/command.c:93 #, c-format msgid "bad argument count %d to %s, expected between %d and %d arguments\n" msgstr "" "błędna liczba argumentów %d dla %s, oczekiwano od %d do %d argumentów\n" #: .././libxcmd/command.c:155 #, c-format msgid "cannot strdup command '%s': %s\n" msgstr "nie można wykonać strdup na poleceniu '%s': %s\n" #: .././libxcmd/command.c:171 .././libxcmd/command.c:189 #, c-format msgid "command \"%s\" not found\n" msgstr "nie znaleziono polecenia \"%s\"\n" #: .././libxcmd/command.c:212 #, fuzzy, c-format msgid "%s %lld/%lld bytes at offset %lld\n" msgstr "odczytano %lld/%lld bajtów od offsetu %lld\n" #: .././libxcmd/command.c:214 #, c-format msgid "%s, %d ops; %s (%s/sec and %.4f ops/sec)\n" msgstr "%s, %d operacji; %s (%s/sek i %.4f operacji/sek)\n" #: .././libxcmd/paths.c:285 #, c-format msgid "%s: unable to extract mount options for \"%s\"\n" msgstr "%s: nie udaÅ‚o siÄ™ wydobyć opcji montowania dla \"%s\"\n" #: .././libxcmd/paths.c:371 #, c-format msgid "%s: getmntinfo() failed: %s\n" msgstr "%s: getmntinfo() nie powiodÅ‚o siÄ™: %s\n" #: .././libxcmd/paths.c:440 #, c-format msgid "%s: cannot setup path for mount %s: %s\n" msgstr "%s: nie można ustawić Å›cieżki dla montowania %s: %s\n" #: .././libxcmd/paths.c:462 #, c-format msgid "%s: cannot find mount point for path `%s': %s\n" msgstr "%s: nie można znaleźć punktu montowania dla Å›cieżki `%s': %s\n" #: .././libxcmd/paths.c:490 #, c-format msgid "%s: cannot setup path for project %s: %s\n" msgstr "%s: nie można ustawić Å›cieżki dla projektu %s: %s\n" #: .././libxcmd/paths.c:531 #, c-format msgid "%s: cannot initialise path table: %s\n" msgstr "%s: nie można zainicjować tabeli Å›cieżek: %s\n" #: .././libxcmd/paths.c:551 #, c-format msgid "%s: cannot setup path for project dir %s: %s\n" msgstr "%s: nie można ustawić Å›cieżki dla katalogu projektu %s: %s\n" #: .././libxcmd/quit.c:43 msgid "exit the program" msgstr "wyjÅ›cie z programu" #: .././libxcmd/topology.c:165 #, c-format msgid "%s: %s appears to contain an existing filesystem (%s).\n" msgstr "%s: %s zdaje siÄ™ zawierać istniejÄ…cy system plików (%s).\n" #: .././libxcmd/topology.c:169 #, c-format msgid "%s: %s appears to contain a partition table (%s).\n" msgstr "%s: %s zdaje siÄ™ zawierać tablicÄ™ partycji (%s).\n" #: .././libxcmd/topology.c:173 #, c-format msgid "%s: %s appears to contain something weird according to blkid\n" msgstr "%s: %s zdaje siÄ™ zawierać coÅ› dziwnego wg blkid\n" #: .././libxcmd/topology.c:182 #, c-format msgid "%s: probe of %s failed, cannot detect existing filesystem.\n" msgstr "" "%s: test %s nie powiódÅ‚ siÄ™, nie można wykryć istniejÄ…cego systemu plików.\n" #: .././libxcmd/topology.c:204 #, fuzzy, c-format msgid "%s: Warning: trying to probe topology of a file %s!\n" msgstr "uwaga: nie udaÅ‚o siÄ™ odczytać topologii urzÄ…dzenia %s\n" #: .././libxcmd/topology.c:245 #, c-format msgid "warning: device is not properly aligned %s\n" msgstr "uwaga: urzÄ…dzenie nie jest wÅ‚aÅ›ciwie wyrównane: %s\n" #: .././libxcmd/topology.c:250 #, c-format msgid "Use -f to force usage of a misaligned device\n" msgstr "Można użyć -f do wymuszenia użycia źle wyrównanego urzÄ…dzenia\n" #: .././libxcmd/topology.c:264 #, c-format msgid "warning: unable to probe device topology for device %s\n" msgstr "uwaga: nie udaÅ‚o siÄ™ odczytać topologii urzÄ…dzenia %s\n" #: .././libxfs/darwin.c:41 #, c-format msgid "%s: error opening the device special file \"%s\": %s\n" msgstr "%s: błąd podczas otwierania pliku specjalnego urzÄ…dzenia \"%s\": %s\n" #: .././libxfs/darwin.c:48 #, c-format msgid "%s: can't tell if \"%s\" is writable: %s\n" msgstr "%s: nie można stwierdzić czy \"%s\" jest zapisywalny: %s\n" #: .././libxfs/darwin.c:76 .././libxfs/freebsd.c:116 .././libxfs/irix.c:58 #: .././libxfs/linux.c:170 #, c-format msgid "%s: cannot stat the device file \"%s\": %s\n" msgstr "%s: nie można wykonać stat na pliku urzÄ…dzenia \"%s\": %s\n" #: .././libxfs/darwin.c:86 #, c-format msgid "%s: can't determine device size: %s\n" msgstr "%s: nie można okreÅ›lić rozmiaru urzÄ…dzenia: %s\n" #: .././libxfs/darwin.c:139 .././libxfs/freebsd.c:196 .././libxfs/irix.c:106 #: .././libxfs/linux.c:260 #, c-format msgid "%s: can't determine memory size\n" msgstr "%s: nie można okreÅ›lić rozmiaru pamiÄ™ci\n" #: .././libxfs/freebsd.c:49 .././libxfs/linux.c:76 #, c-format msgid "%s: %s possibly contains a mounted filesystem\n" msgstr "%s: %s może zawierać podmontowany system plików\n" #: .././libxfs/freebsd.c:60 .././libxfs/linux.c:104 #, c-format msgid "%s: %s contains a mounted filesystem\n" msgstr "%s: %s zawiera podmontowany system plików\n" #: .././libxfs/freebsd.c:75 #, c-format msgid "%s: %s contains a possibly writable, mounted filesystem\n" msgstr "%s: %s zawiera podmontowany, być może zapisywalny system plików\n" #: .././libxfs/freebsd.c:89 .././libxfs/linux.c:100 #, c-format msgid "%s: %s contains a mounted and writable filesystem\n" msgstr "%s: %s zawiera podmontowany, zapisywalny system plików\n" #: .././libxfs/freebsd.c:129 #, c-format msgid "%s: Not a device or file: \"%s\"\n" msgstr "%s: Nie jest urzÄ…dzeniem ani plikiem: \"%s\"\n" #: .././libxfs/freebsd.c:135 #, c-format msgid "%s: DIOCGMEDIASIZE failed on \"%s\": %s\n" msgstr "%s: DIOCGMEDIASIE nie powiodÅ‚o siÄ™ dla \"%s\": %s\n" #: .././libxfs/freebsd.c:141 #, c-format msgid "%s: DIOCGSECTORSIZE failed on \"%s\": %s\n" msgstr "%s: DIOCGSECTORSIZE nie powiodÅ‚o siÄ™ dla \"%s\": %s\n" #: .././libxfs/init.c:97 .././libxfs/init.c:196 #, c-format msgid "%s: %s: device %lld is not open\n" msgstr "%s: %s: urzÄ…dzenie %lld nie jest otwarte\n" #: .././libxfs/init.c:133 #, c-format msgid "%s: cannot stat %s: %s\n" msgstr "%s: nie można wykonać stat na %s: %s\n" #: .././libxfs/init.c:158 #, c-format msgid "%s: device %lld is already open\n" msgstr "%s: urzÄ…dzenie %lld jest już otwarte\n" #: .././libxfs/init.c:171 #, c-format msgid "%s: %s: too many open devices\n" msgstr "%s: %s: zbyt dużo otwartych urzÄ…dzeÅ„\n" #: .././libxfs/init.c:214 #, c-format msgid "%s: can't find a character device matching %s\n" msgstr "%s: nie można odnaleźć urzÄ…dzenia znakowego odpowiadajÄ…cego %s\n" #: .././libxfs/init.c:220 #, c-format msgid "%s: can't find a block device matching %s\n" msgstr "%s: nie można odnaleźć urzÄ…dzenia blokowego odpowiadajÄ…cego %s\n" #: .././libxfs/init.c:348 #, c-format msgid "%s: can't get size for data subvolume\n" msgstr "%s: nie można pobrać rozmiaru podwolumenu danych\n" #: .././libxfs/init.c:353 #, c-format msgid "%s: can't get size for log subvolume\n" msgstr "%s: nie można pobrać rozmiaru podwolumenu logu\n" #: .././libxfs/init.c:358 #, c-format msgid "%s: can't get size for realtime subvolume\n" msgstr "%s: nie można pobrać rozmiaru podwolumenu realtime\n" #: .././libxfs/init.c:453 #, c-format msgid "%s: filesystem has a realtime subvolume\n" msgstr "%s: system plików ma podwolumen realtime\n" #: .././libxfs/init.c:475 #, c-format msgid "%s: realtime init - %llu != %llu\n" msgstr "%s: inicjalizacja realtime - %llu != %llu\n" #: .././libxfs/init.c:483 #, c-format msgid "%s: realtime size check failed\n" msgstr "%s: sprawdzenie rozmiaru realtime nie powiodÅ‚o siÄ™\n" #: .././libxfs/init.c:605 #, c-format msgid "%s: buftarg init failed\n" msgstr "%s: nie udaÅ‚o siÄ™ zainicjować buftarg\n" #: .././libxfs/init.c:626 #, c-format msgid "%s: bad buftarg reinit, ddev\n" msgstr "%s: błędna reinicjacja buftarg, ddev\n" #: .././libxfs/init.c:633 #, c-format msgid "%s: bad buftarg reinit, ldev mismatch\n" msgstr "%s: błędna reinicjacja buftarg, niezgodność ldev\n" #: .././libxfs/init.c:640 #, c-format msgid "%s: bad buftarg reinit, logdev\n" msgstr "%s: błędna reinicjacja buftarg, logdev\n" #: .././libxfs/init.c:647 #, c-format msgid "%s: bad buftarg reinit, rtdev\n" msgstr "%s: błędna reinicjacja buftarg, rtdev\n" #: .././libxfs/init.c:741 #, c-format msgid "%s: size check failed\n" msgstr "%s: sprawdzenie rozmiaru nie powiodÅ‚o siÄ™\n" #: .././libxfs/init.c:753 #, fuzzy, c-format msgid "%s: V1 inodes unsupported. Please try an older xfsprogs.\n" msgstr "" "%s: katalogi V1 nie sÄ… obsÅ‚ugiwane. ProszÄ™ spróbować starszÄ… wersjÄ… " "xfsprogs.\n" #: .././libxfs/init.c:762 #, c-format msgid "%s: V1 directories unsupported. Please try an older xfsprogs.\n" msgstr "" "%s: katalogi V1 nie sÄ… obsÅ‚ugiwane. ProszÄ™ spróbować starszÄ… wersjÄ… " "xfsprogs.\n" #: .././libxfs/init.c:770 #, fuzzy, c-format msgid "%s: Unsupported features detected. Please try a newer xfsprogs.\n" msgstr "" "%s: katalogi V1 nie sÄ… obsÅ‚ugiwane. ProszÄ™ spróbować starszÄ… wersjÄ… " "xfsprogs.\n" #: .././libxfs/init.c:790 #, c-format msgid "%s: data size check failed\n" msgstr "%s: sprawdzenie rozmiaru danych nie powiodÅ‚o siÄ™\n" #: .././libxfs/init.c:804 #, c-format msgid "%s: log size checks failed\n" msgstr "%s: sprawdzenie rozmiaru logu nie powiodÅ‚o siÄ™\n" #: .././libxfs/init.c:815 #, c-format msgid "%s: realtime device init failed\n" msgstr "%s: inicjalizacja urzÄ…dzenia realtime nie powiodÅ‚a siÄ™\n" #: .././libxfs/init.c:822 #, c-format msgid "%s: perag init failed\n" msgstr "%s: nie udaÅ‚o siÄ™ zainicjować perag\n" #: .././libxfs/kmem.c:15 #, c-format msgid "%s: zone init failed (%s, %d bytes): %s\n" msgstr "%s: inicjalizacja strefy nie powiodÅ‚a siÄ™ (%s, %d bajtów): %s\n" #: .././libxfs/kmem.c:32 #, c-format msgid "%s: zone alloc failed (%s, %d bytes): %s\n" msgstr "%s: przydzielenie strefy nie powiodÅ‚o siÄ™ (%s, %d bajtów): %s\n" #: .././libxfs/kmem.c:56 #, c-format msgid "%s: malloc failed (%d bytes): %s\n" msgstr "%s: malloc nie powiodÅ‚o siÄ™ (%d bajtów): %s\n" #: .././libxfs/kmem.c:77 #, c-format msgid "%s: realloc failed (%d bytes): %s\n" msgstr "%s: realloc nie powiodÅ‚o siÄ™ (%d bajtów): %s\n" #: .././libxfs/linux.c:137 #, c-format msgid "%s: %s - cannot set blocksize %d on block device %s: %s\n" msgstr "" "%s: %s - nie można ustawić rozmiaru bloku %d dla urzÄ…dzenia blokowego %s: " "%s\n" #: .././libxfs/linux.c:205 #, c-format msgid "%s: can't determine device size\n" msgstr "%s: nie można okreÅ›lić rozmiaru urzÄ…dzenia\n" #: .././libxfs/linux.c:213 #, c-format msgid "%s: warning - cannot get sector size from block device %s: %s\n" msgstr "" "%s: uwaga - nie można pobrać rozmiaru sektora urzÄ…dzenia blokowego %s: %s\n" #: .././libxfs/rdwr.c:82 #, c-format msgid "%s: %s can't memalign %d bytes: %s\n" msgstr "%s: %s nie można wykonać memalign dla %d bajtów: %s\n" #: .././libxfs/rdwr.c:92 #, c-format msgid "%s: %s seek to offset %llu failed: %s\n" msgstr "%s: %s zmiana offsetu na %llu nie powiodÅ‚a siÄ™: %s\n" #: .././libxfs/rdwr.c:102 #, c-format msgid "%s: %s write failed: %s\n" msgstr "%s: %s zapis nie powiódÅ‚ siÄ™: %s\n" #: .././libxfs/rdwr.c:106 #, c-format msgid "%s: %s not progressing?\n" msgstr "%s: %s nie postÄ™puje?\n" #: .././libxfs/rdwr.c:581 #, c-format msgid "%s: %s can't memalign %u bytes: %s\n" msgstr "%s: %s nie można wykonać memalign dla %u bajtów: %s\n" #: .././libxfs/rdwr.c:614 #, c-format msgid "%s: %s can't malloc %u bytes: %s\n" msgstr "%s: %s nie można przydzielić %u bajtów: %s\n" #: .././libxfs/rdwr.c:697 #, c-format msgid "%s: %s invalid map %p or nmaps %d\n" msgstr "%s: %s nieprawidÅ‚owa mapa %p lub nmaps %d\n" #: .././libxfs/rdwr.c:704 #, c-format msgid "%s: %s map blkno 0x%llx doesn't match key 0x%llx\n" msgstr "%s: %s map blkno 0x%llx nie pasuje do klucza 0x%llx\n" #: .././libxfs/rdwr.c:749 #, c-format msgid "Warning: recursive buffer locking at block % detected\n" msgstr "Uwaga: wykryto rekurencyjnÄ… blokadÄ™ bufora na bloku %\n" #: .././libxfs/rdwr.c:921 #, c-format msgid "%s: read failed: %s\n" msgstr "%s: odczyt nie powiódÅ‚ siÄ™: %s\n" #: .././libxfs/rdwr.c:927 #, c-format msgid "%s: error - read only %d of %d bytes\n" msgstr "%s: błąd - odczytano tylko %d z %d bajtów\n" #: .././libxfs/rdwr.c:1089 #, c-format msgid "%s: pwrite failed: %s\n" msgstr "%s: pwrite nie powiodÅ‚o siÄ™: %s\n" #: .././libxfs/rdwr.c:1095 #, c-format msgid "%s: error - pwrite only %d of %d bytes\n" msgstr "%s: błąd - wykonano pwrite tylko %d z %d bajtów\n" #: .././libxfs/rdwr.c:1130 #, fuzzy, c-format msgid "%s: write verifer failed on %s bno 0x%llx/0x%x\n" msgstr "%s: weryfikacja zapisu nie powiodÅ‚a siÄ™ na bno 0x%llx/0x%x\n" #: .././libxfs/trans.c:69 #, c-format msgid "%s: lidp calloc failed (%d bytes): %s\n" msgstr "%s: calloc lidp nie powiodÅ‚o siÄ™ (%d bajtów): %s\n" #: .././libxfs/trans.c:183 #, c-format msgid "%s: xact calloc failed (%d bytes): %s\n" msgstr "%s: xact calloc nie powiodÅ‚o siÄ™ (%d bajtów): %s\n" #: .././libxfs/trans.c:670 #, c-format msgid "%s: warning - imap_to_bp failed (%d)\n" msgstr "%s: uwaga - imap_to_bp nie powiodÅ‚o siÄ™ (%d)\n" #: .././libxfs/trans.c:678 #, c-format msgid "%s: warning - iflush_int failed (%d)\n" msgstr "%s: uwaga - iflush_int nie powiodÅ‚o siÄ™ (%d)\n" #: .././libxfs/trans.c:738 .././libxfs/trans.c:792 #, c-format msgid "%s: unrecognised log item type\n" msgstr "%s: nierozpoznany typ elementu logu\n" #: .././libxfs/util.c:617 #, fuzzy, c-format msgid "%s: cannot duplicate transaction: %s\n" msgstr "%s: nie można ustawić ostrzeżeÅ„: %s\n" #: .././libxlog/util.c:67 #, fuzzy, c-format msgid "%s: cannot find log head/tail (xlog_find_tail=%d)\n" msgstr "" "zero_log: nie znaleziono poczÄ…tku/koÅ„ca logu (xlog_find_tail=%d), wyzerowano " "go\n" #: .././libxlog/util.c:75 #, fuzzy, c-format msgid "%s: head block % tail block %\n" msgstr "zero_log: blok poczÄ…tku % blok koÅ„ca %\n" #: .././libxlog/util.c:97 #, c-format msgid "" "* ERROR: mismatched uuid in log\n" "* SB : %s\n" "* log: %s\n" msgstr "" "* BÅÄ„D: niepasujÄ…cy uuid w logu\n" " SB : %s\n" " log: %s\n" #: .././libxlog/util.c:110 #, c-format msgid "" "\n" "LOG REC AT LSN cycle %d block %d (0x%x, 0x%x)\n" msgstr "" "\n" "LOG REC AT LSN cykl %d blok %d (0x%x, 0x%x)\n" #: .././libxlog/util.c:118 #, c-format msgid "* ERROR: bad magic number in log header: 0x%x\n" msgstr "* BÅÄ„D: błędna liczba magiczna w nagłówku logu: 0x%x\n" #: .././libxlog/util.c:127 #, c-format msgid "* ERROR: log format incompatible (log=%d, ours=%d)\n" msgstr "* BÅÄ„D: niekompatybilny format logu (log=%d, nasz=%d)\n" #: .././libxlog/util.c:137 .././libxlog/util.c:149 msgid "Bad log" msgstr "Błędny log" #: .././logprint/log_copy.c:46 .././logprint/log_dump.c:45 #, c-format msgid "%s: read error (%lld): %s\n" msgstr "%s: błąd odczytu (%lld): %s\n" #: .././logprint/log_copy.c:51 .././logprint/log_dump.c:50 #, c-format msgid "%s: physical end of log at %lld\n" msgstr "%s: fizyczny koniec logu na %lld\n" #: .././logprint/log_copy.c:55 #, c-format msgid "%s: short read? (%lld)\n" msgstr "%s: skrócony odczyt? (%lld)\n" #: .././logprint/log_copy.c:62 #, c-format msgid "%s: write error (%lld): %s\n" msgstr "%s: błąd zapisu (%lld): %s\n" #: .././logprint/log_copy.c:67 #, c-format msgid "%s: short write? (%lld)\n" msgstr "%s: skrócony zapis? (%lld)\n" #: .././logprint/log_dump.c:58 #, c-format msgid "%6lld HEADER Cycle %d tail %d:%06d len %6d ops %d\n" msgstr "%6lld NAGÅÓWEK Cykl %d koniec %d:%06d len %6d ops %d\n" #: .././logprint/log_dump.c:69 #, c-format msgid "[%05lld - %05lld] Cycle 0x%08x New Cycle 0x%08x\n" msgstr "[%05lld - %05lld] Cykl 0x%08x Nowy cykl 0x%08x\n" #: .././logprint/log_misc.c:87 #, c-format msgid "Oper (%d): tid: %x len: %d clientid: %s " msgstr "Operacja (%d): tid: %x len: %d clientid: %s " #: .././logprint/log_misc.c:92 #, c-format msgid "flags: " msgstr "flagi: " #: .././logprint/log_misc.c:186 #, c-format msgid " Not enough data to decode further\n" msgstr " Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_misc.c:190 #, fuzzy, c-format msgid " tid: %x num_items: %d\n" msgstr " typ: %s tid: %x num_items: %d\n" #: .././logprint/log_misc.c:235 #, c-format msgid "" "#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d flags: 0x%x\n" msgstr "" "#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d flags: 0x%x\n" #: .././logprint/log_misc.c:241 #, c-format msgid "#regs: %d Not printing rest of data\n" msgstr "#regs: %d Bez wypisywania reszty danych\n" #: .././logprint/log_misc.c:258 #, c-format msgid "SUPER BLOCK Buffer: " msgstr "Bufor SUPER BLOKU: " #: .././logprint/log_misc.c:260 .././logprint/log_misc.c:348 #: .././logprint/log_misc.c:378 #, c-format msgid "Out of space\n" msgstr "Brak miejsca na dysku\n" #: .././logprint/log_misc.c:268 #, c-format msgid "icount: %llu ifree: %llu " msgstr "icount: %llu ifree: %llu " #: .././logprint/log_misc.c:273 #, c-format msgid "fdblks: %llu frext: %llu\n" msgstr "fdblks: %llu frext: %llu\n" #: .././logprint/log_misc.c:284 #, c-format msgid "AGI Buffer: XAGI " msgstr "Bufor AGI: XAGI " #: .././logprint/log_misc.c:295 #, c-format msgid "out of space\n" msgstr "brak miejsca na dysku\n" #: .././logprint/log_misc.c:298 #, c-format msgid "ver: %d " msgstr "wersja: %d " #: .././logprint/log_misc.c:300 #, c-format msgid "seq#: %d len: %d cnt: %d root: %d\n" msgstr "seq#: %d len: %d cnt: %d root: %d\n" #: .././logprint/log_misc.c:305 #, c-format msgid "level: %d free#: 0x%x newino: 0x%x\n" msgstr "level: %d free#: 0x%x newino: 0x%x\n" #: .././logprint/log_misc.c:315 #, c-format msgid "AGI unlinked data skipped " msgstr "PominiÄ™to niedowiÄ…zane dane AGI " #: .././logprint/log_misc.c:316 #, c-format msgid "(CONTINUE set, no space)\n" msgstr "(KONTYNUACJA, brak miejsca)\n" #: .././logprint/log_misc.c:322 .././logprint/log_print_all.c:148 #, c-format msgid "bucket[%d - %d]: " msgstr "kubeÅ‚ek[%d - %d]: " #: .././logprint/log_misc.c:338 #, c-format msgid "AGF Buffer: XAGF " msgstr "Bufor AGF: XAGF " #: .././logprint/log_misc.c:351 #, c-format msgid "ver: %d seq#: %d len: %d \n" msgstr "ver: %d seq#: %d len: %d \n" #: .././logprint/log_misc.c:355 #, c-format msgid "root BNO: %d CNT: %d\n" msgstr "root BNO: %d CNT: %d\n" #: .././logprint/log_misc.c:358 #, c-format msgid "level BNO: %d CNT: %d\n" msgstr "level BNO: %d CNT: %d\n" #: .././logprint/log_misc.c:361 #, c-format msgid "1st: %d last: %d cnt: %d freeblks: %d longest: %d\n" msgstr "1st: %d last: %d cnt: %d freeblks: %d longest: %d\n" #: .././logprint/log_misc.c:375 #, c-format msgid "DQUOT Buffer: DQ " msgstr "Bufor DQUOT: DQ " #: .././logprint/log_misc.c:382 #, c-format msgid "ver: %d flags: 0x%x id: %d \n" msgstr "ver: %d flags: 0x%x id: %d \n" #: .././logprint/log_misc.c:385 #, c-format msgid "blk limits hard: %llu soft: %llu\n" msgstr "blk limits hard: %llu soft: %llu\n" #: .././logprint/log_misc.c:390 #, c-format msgid "blk count: %llu warns: %d timer: %d\n" msgstr "blk count: %llu warns: %d timer: %d\n" #: .././logprint/log_misc.c:394 #, c-format msgid "ino limits hard: %llu soft: %llu\n" msgstr "ino limits hard: %llu soft: %llu\n" #: .././logprint/log_misc.c:399 #, c-format msgid "ino count: %llu warns: %d timer: %d\n" msgstr "ino count: %llu warns: %d timer: %d\n" #: .././logprint/log_misc.c:405 #, c-format msgid "BUF DATA\n" msgstr "DANE BUFORA\n" #: .././logprint/log_misc.c:441 #, c-format msgid "QOFF: #regs: %d flags: 0x%x\n" msgstr "QOFF: #regs: %d flags: 0x%x\n" #: .././logprint/log_misc.c:444 #, c-format msgid "QOFF: Not enough data to decode further\n" msgstr "QOFF: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_misc.c:454 #, c-format msgid "INODE CORE\n" msgstr "RDZEŃ I-WĘZÅA\n" #: .././logprint/log_misc.c:455 #, c-format msgid "magic 0x%hx mode 0%ho version %d format %d\n" msgstr "magic 0x%hx mode 0%ho version %d format %d\n" #: .././logprint/log_misc.c:458 #, c-format msgid "nlink %hd uid %d gid %d\n" msgstr "nlink %hd uid %d gid %d\n" #: .././logprint/log_misc.c:460 #, c-format msgid "atime 0x%x mtime 0x%x ctime 0x%x\n" msgstr "atime 0x%x mtime 0x%x ctime 0x%x\n" #: .././logprint/log_misc.c:462 #, c-format msgid "size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n" msgstr "size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n" #: .././logprint/log_misc.c:465 #, c-format msgid "naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n" msgstr "naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n" #: .././logprint/log_misc.c:468 #, c-format msgid "flags 0x%x gen 0x%x\n" msgstr "flags 0x%x gen 0x%x\n" #: .././logprint/log_misc.c:471 .././logprint/log_print_all.c:276 #, fuzzy, c-format msgid "flags2 0x%llx cowextsize 0x%x\n" msgstr "flags 0x%x gen 0x%x\n" #: .././logprint/log_misc.c:488 #, c-format msgid "SHORTFORM DIRECTORY size %d\n" msgstr "Rozmiar KATALOGU W POSTACI KRÓTKIEJ %d\n" #: .././logprint/log_misc.c:494 #, c-format msgid "SHORTFORM DIRECTORY size %d count %d\n" msgstr "KATALOG W POSTACI KRÓTKIEJ: rozmiar %d liczba %d\n" #: .././logprint/log_misc.c:497 #, c-format msgid ".. ino 0x%llx\n" msgstr ".. ino 0x%llx\n" #: .././logprint/log_misc.c:505 #, c-format msgid "%s ino 0x%llx namelen %d\n" msgstr "%s ino 0x%llx namelen %d\n" #: .././logprint/log_misc.c:544 #, c-format msgid "INODE: " msgstr "I-WĘZEÅ: " #: .././logprint/log_misc.c:545 #, c-format msgid "#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n" msgstr "#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n" #: .././logprint/log_misc.c:548 #, c-format msgid " blkno: %lld len: %d boff: %d\n" msgstr " blkno: %lld len: %d boff: %d\n" #: .././logprint/log_misc.c:553 #, c-format msgid "INODE: #regs: %d Not printing rest of data\n" msgstr "I-WĘZEÅ: #regs: %d Bez wypisywania reszty danych\n" #: .././logprint/log_misc.c:584 #, c-format msgid "DEV inode: no extra region\n" msgstr "I-wÄ™zeÅ‚ DEV: brak dodatkowego regionu\n" #: .././logprint/log_misc.c:587 #, c-format msgid "UUID inode: no extra region\n" msgstr "I-wÄ™zeÅ‚ UUID: brak dodatkowego regionu\n" #: .././logprint/log_misc.c:604 #, c-format msgid "EXTENTS inode data\n" msgstr "EKSTENTY danych i-wÄ™zÅ‚a\n" #: .././logprint/log_misc.c:607 #, c-format msgid "BTREE inode data\n" msgstr "B-DRZEWO danych i-wÄ™zÅ‚a\n" #: .././logprint/log_misc.c:610 #, c-format msgid "LOCAL inode data\n" msgstr "LOKALNE dane i-wÄ™zÅ‚a\n" #: .././logprint/log_misc.c:631 #, c-format msgid "EXTENTS attr data\n" msgstr "EKSTENTY danych atrybutów\n" #: .././logprint/log_misc.c:634 #, c-format msgid "BTREE attr data\n" msgstr "B-DRZEWO danych atrybutów\n" #: .././logprint/log_misc.c:637 #, c-format msgid "LOCAL attr data\n" msgstr "LOKALNE dane atrybutów\n" #: .././logprint/log_misc.c:675 #, c-format msgid "#regs: %d id: 0x%x" msgstr "#regs: %d id: 0x%x" #: .././logprint/log_misc.c:676 #, c-format msgid " blkno: %lld len: %d boff: %d\n" msgstr " blkno: %lld len: %d boff: %d\n" #: .././logprint/log_misc.c:680 #, c-format msgid "DQUOT: #regs: %d Not printing rest of data\n" msgstr "DQUOT: #regs: %d Bez wypisywania reszty danych\n" #: .././logprint/log_misc.c:699 #, c-format msgid "DQUOT: magic 0x%hx flags 0%ho\n" msgstr "DQUOT: magic 0x%hx flags 0%ho\n" #: .././logprint/log_misc.c:725 #, c-format msgid "ICR: split header, not printing\n" msgstr "ICR: nagłówek podzielony, bez wypisywania\n" #: .././logprint/log_misc.c:729 #, c-format msgid "" "ICR: #ag: %d agbno: 0x%x len: %d\n" " cnt: %d isize: %d gen: 0x%x\n" msgstr "" "ICR: #ag: %d agbno: 0x%x len: %d\n" " cnt: %d isize: %d gen: 0x%x\n" #: .././logprint/log_misc.c:755 #, c-format msgid "%s: lseek to %lld failed: %s\n" msgstr "%s: lseek na %lld nie powiodÅ‚o siÄ™: %s\n" #: .././logprint/log_misc.c:801 #, c-format msgid "%s: xlog_print_record: malloc failed\n" msgstr "%s: xlog_print_record: malloc nie powiodÅ‚o siÄ™\n" #: .././logprint/log_misc.c:810 #, c-format msgid "%s: xlog_print_record: read error\n" msgstr "%s: xlog_print_record: błąd odczytu\n" #: .././logprint/log_misc.c:905 .././logprint/log_misc.c:1008 #, c-format msgid "Left over region from split log item\n" msgstr "Region pozostaÅ‚y z podziaÅ‚u elementu logu\n" #: .././logprint/log_misc.c:993 #, c-format msgid "Unmount filesystem\n" msgstr "Niezamontowany system plików\n" #: .././logprint/log_misc.c:1000 #, c-format msgid "%s: unknown log operation type (%x)\n" msgstr "%s: nieznany typ operacji w logu (%x)\n" #: .././logprint/log_misc.c:1041 #, c-format msgid "Header 0x%x wanted 0x%x\n" msgstr "Nagłówek 0x%x, pożądany 0x%x\n" #: .././logprint/log_misc.c:1055 #, c-format msgid "cycle: %d\tversion: %d\t" msgstr "cykl: %d\twersja: %d\t" #: .././logprint/log_misc.c:1061 #, c-format msgid "length of Log Record: %d\tprev offset: %d\t\tnum ops: %d\n" msgstr "dÅ‚ugość rekordu logu: %d\tpoprz.offset: %d\t\tl.oper.: %d\n" #: .././logprint/log_misc.c:1067 .././logprint/log_misc.c:1109 #, c-format msgid "cycle num overwrites: " msgstr "liczba nadpisaÅ„ cyklu: " #: .././logprint/log_misc.c:1076 #, c-format msgid "uuid: %s format: " msgstr "uuid: %s format: " #: .././logprint/log_misc.c:1079 #, c-format msgid "unknown\n" msgstr "nieznany\n" #: .././logprint/log_misc.c:1082 #, c-format msgid "little endian linux\n" msgstr "Linux little endian\n" #: .././logprint/log_misc.c:1085 #, c-format msgid "big endian linux\n" msgstr "Linux big endian\n" #: .././logprint/log_misc.c:1088 #, c-format msgid "big endian irix\n" msgstr "IRIX big endian\n" #: .././logprint/log_misc.c:1094 #, c-format msgid "h_size: %d\n" msgstr "h_size: %d\n" #: .././logprint/log_misc.c:1106 #, c-format msgid "extended-header: cycle: %d\n" msgstr "nagłówek-rozszerzony: cykl: %d\n" #: .././logprint/log_misc.c:1122 #, c-format msgid "* ERROR: found data after zeroed blocks block=%-21lld *\n" msgstr "* BÅÄ„D: znaleziono dane za wyzerowanymi blokami blok=%-21lld *\n" #: .././logprint/log_misc.c:1133 #, c-format msgid "* ERROR: header cycle=%-11d block=%-21lld *\n" msgstr "* BÅÄ„D: nagłówek cykl=%-11d blok=%-21lld *\n" #: .././logprint/log_misc.c:1144 #, c-format msgid "* ERROR: data block=%-21lld *\n" msgstr "* BÅÄ„D: blok danych=%-21lld *\n" #: .././logprint/log_misc.c:1155 #, c-format msgid "" "* ERROR: for header block=%lld\n" "* not enough hdrs for data length, required num = %d, hdr num = %d\n" msgstr "" "* BÅÄ„D: dla bloku nagłówka %lld\n" "* za maÅ‚o nagłówków dla dÅ‚ugoÅ›ci danych, wymaganych = %d, liczba = %d\n" #: .././logprint/log_misc.c:1161 msgid "Not enough headers for data length." msgstr "Za maÅ‚o nagłówków dla dÅ‚ugoÅ›ci danych." #: .././logprint/log_misc.c:1171 #, c-format msgid "%s: xlog_print: malloc failed for ext hdrs\n" msgstr "%s: xlog_print: malloc dla rozszerzonych nagłówków nie powiódÅ‚ siÄ™\n" #: .././logprint/log_misc.c:1219 .././logprint/log_misc.c:1295 #: .././logprint/log_misc.c:1366 .././logprint/log_misc.c:1403 #, c-format msgid "%s: physical end of log\n" msgstr "%s: fizyczny koniec logu\n" #: .././logprint/log_misc.c:1225 .././logprint/log_misc.c:1300 #: .././logprint/log_misc.c:1418 #, c-format msgid "BLKNO: %lld\n" msgstr "BLKNO: %lld\n" #: .././logprint/log_misc.c:1283 #, c-format msgid "%s: problem finding oldest LR\n" msgstr "%s: problem ze znalezieniem najstarszego rekordu logu\n" #: .././logprint/log_misc.c:1309 #, c-format msgid "%s: after %d zeroed blocks\n" msgstr "%s: po %d wyzerowanych blokach\n" #: .././logprint/log_misc.c:1378 msgid "illegal value" msgstr "niedozwolona wartość" #: .././logprint/log_misc.c:1384 #, c-format msgid "%s: skipped %d cleared blocks in range: %lld - %lld\n" msgstr "%s: pominiÄ™to %d wyzerowanych bloków w przedziale: %lld - %lld\n" #: .././logprint/log_misc.c:1389 #, c-format msgid "%s: totally cleared log\n" msgstr "%s: caÅ‚kowicie wyczyszczony log\n" #: .././logprint/log_misc.c:1394 #, c-format msgid "%s: skipped %d zeroed blocks in range: %lld - %lld\n" msgstr "%s: pominiÄ™to %d wyzerowanych bloków w przedziale %lld - %lld\n" #: .././logprint/log_misc.c:1399 #, c-format msgid "%s: totally zeroed log\n" msgstr "%s: caÅ‚kowicie wyzerowany log\n" #: .././logprint/log_misc.c:1415 msgid "xlog_find_head: bad read" msgstr "xlog_find_head: błędny odczyt" #: .././logprint/log_misc.c:1467 #, c-format msgid "%s: logical end of log\n" msgstr "%s: logiczny koniec logu\n" #: .././logprint/log_print_all.c:96 #, c-format msgid "" "BUF: #regs:%d start blkno:0x%llx len:%d bmap size:%d flags:0x%x\n" msgstr "" "BUF: #regs:%d blok pocz.:0x%llx dÅ‚ug.:%d rozm.bmapy:%d flagi:0x%x\n" #: .././logprint/log_print_all.c:106 #, c-format msgid "\tSUPER Block Buffer:\n" msgstr "\tBufor SUPER bloku:\n" #: .././logprint/log_print_all.c:109 #, c-format msgid " icount:%llu ifree:%llu " msgstr " icount:%llu ifree:%llu " #: .././logprint/log_print_all.c:114 #, c-format msgid "fdblks:%llu frext:%llu\n" msgstr "fdblks:%llu frext:%llu\n" #: .././logprint/log_print_all.c:119 #, c-format msgid "\t\tsunit:%u swidth:%u\n" msgstr "\t\tsunit:%u swidth:%u\n" #: .././logprint/log_print_all.c:125 #, c-format msgid "\tAGI Buffer: (XAGI)\n" msgstr "\tBufor AGI: (XAGI)\n" #: .././logprint/log_print_all.c:128 #, c-format msgid "\t\tver:%d " msgstr "\t\twersja:%d " #: .././logprint/log_print_all.c:130 #, c-format msgid "seq#:%d len:%d cnt:%d root:%d\n" msgstr "seq#:%d len:%d cnt:%d root:%d\n" #: .././logprint/log_print_all.c:135 #, c-format msgid "\t\tlevel:%d free#:0x%x newino:0x%x\n" msgstr "\t\tlevel:%d free#:0x%x newino:0x%x\n" #: .././logprint/log_print_all.c:159 #, c-format msgid "\tAGF Buffer: (XAGF)\n" msgstr "\tBufor AGI: (XAGF)\n" #: .././logprint/log_print_all.c:162 #, c-format msgid "\t\tver:%d seq#:%d len:%d \n" msgstr "\t\tver:%d seq#:%d len:%d \n" #: .././logprint/log_print_all.c:166 #, c-format msgid "\t\troot BNO:%d CNT:%d\n" msgstr "\t\troot BNO:%d CNT:%d\n" #: .././logprint/log_print_all.c:169 #, c-format msgid "\t\tlevel BNO:%d CNT:%d\n" msgstr "\t\tlevel BNO:%d CNT:%d\n" #: .././logprint/log_print_all.c:172 #, c-format msgid "\t\t1st:%d last:%d cnt:%d freeblks:%d longest:%d\n" msgstr "\t\t1st:%d last:%d cnt:%d freeblks:%d longest:%d\n" #: .././logprint/log_print_all.c:181 #, c-format msgid "\tDQUOT Buffer:\n" msgstr "\tBufor DQUOT:\n" #: .././logprint/log_print_all.c:184 #, c-format msgid "\t\tUIDs 0x%lx-0x%lx\n" msgstr "\t\tUIDs 0x%lx-0x%lx\n" #: .././logprint/log_print_all.c:189 #, c-format msgid "\tBUF DATA\n" msgstr "\tDANE BUF\n" #: .././logprint/log_print_all.c:211 #, c-format msgid "\tQUOTAOFF: #regs:%d type:%s\n" msgstr "\tQUOTAOFF: #regs:%d type:%s\n" #: .././logprint/log_print_all.c:226 #, c-format msgid "\tDQUOT: #regs:%d blkno:%lld boffset:%u id: %d\n" msgstr "\tDQUOT: #regs:%d blkno:%lld boffset:%u id: %d\n" #: .././logprint/log_print_all.c:230 #, c-format msgid "\t\tmagic 0x%x\tversion 0x%x\tID 0x%x (%d)\t\n" msgstr "\t\tmagic 0x%x\twersja 0x%x\tID 0x%x (%d)\t\n" #: .././logprint/log_print_all.c:235 #, c-format msgid "\t\tblk_hard 0x%x\tblk_soft 0x%x\tino_hard 0x%x\tino_soft 0x%x\n" msgstr "\t\tblk_hard 0x%x\tblk_soft 0x%x\tino_hard 0x%x\tino_soft 0x%x\n" #: .././logprint/log_print_all.c:241 #, c-format msgid "\t\tbcount 0x%x (%d) icount 0x%x (%d)\n" msgstr "\t\tbcount 0x%x (%d) icount 0x%x (%d)\n" #: .././logprint/log_print_all.c:246 #, c-format msgid "\t\tbtimer 0x%x itimer 0x%x \n" msgstr "\t\tbtimer 0x%x itimer 0x%x \n" #: .././logprint/log_print_all.c:255 #, c-format msgid "\tCORE inode:\n" msgstr "\tGÅÓWNY i-wÄ™zeÅ‚:\n" #: .././logprint/log_print_all.c:258 #, fuzzy, c-format msgid "\t\tmagic:%c%c mode:0x%x ver:%d format:%d\n" msgstr "\t\tmagic:%c%c mode:0x%x ver:%d format:%d onlin:%d\n" #: .././logprint/log_print_all.c:261 #, fuzzy, c-format msgid "\t\tuid:%d gid:%d nlink:%d projid:0x%04x%04x\n" msgstr "\t\tuid:%d gid:%d nlink:%d projid:%u\n" #: .././logprint/log_print_all.c:264 #, c-format msgid "\t\tatime:%d mtime:%d ctime:%d\n" msgstr "\t\tatime:%d mtime:%d ctime:%d\n" #: .././logprint/log_print_all.c:266 #, c-format msgid "\t\tflushiter:%d\n" msgstr "\t\tflushiter:%d\n" #: .././logprint/log_print_all.c:267 #, c-format msgid "\t\tsize:0x%llx nblks:0x%llx exsize:%d nextents:%d anextents:%d\n" msgstr "\t\tsize:0x%llx nblks:0x%llx exsize:%d nextents:%d anextents:%d\n" #: .././logprint/log_print_all.c:271 #, c-format msgid "\t\tforkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x gen:%d\n" msgstr "\t\tforkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x gen:%d\n" #: .././logprint/log_print_all.c:295 #, c-format msgid "\tINODE: #regs:%d ino:0x%llx flags:0x%x dsize:%d\n" msgstr "\tINODE: #regs:%d ino:0x%llx flags:0x%x dsize:%d\n" #: .././logprint/log_print_all.c:311 #, c-format msgid "\t\tDATA FORK EXTENTS inode data:\n" msgstr "\t\tDane EKSTENTÓW GAÅĘZI DANYCH i-wÄ™zÅ‚a:\n" #: .././logprint/log_print_all.c:318 #, c-format msgid "\t\tDATA FORK BTREE inode data:\n" msgstr "\t\tDane B-DRZEWA GAÅĘZI DANYCH i-wÄ™zÅ‚a:\n" #: .././logprint/log_print_all.c:325 #, c-format msgid "\t\tDATA FORK LOCAL inode data:\n" msgstr "\t\tDane LOKALNE GAÅĘZI DANYCH i-wÄ™zÅ‚a:\n" #: .././logprint/log_print_all.c:332 #, c-format msgid "\t\tDEV inode: no extra region\n" msgstr "\t\tI-wÄ™zeÅ‚ DEV: brak dodatkowego regionu\n" #: .././logprint/log_print_all.c:336 #, c-format msgid "\t\tUUID inode: no extra region\n" msgstr "\t\tI-wÄ™zeÅ‚ UUID: brak dodatkowego regionu\n" #: .././logprint/log_print_all.c:351 #, c-format msgid "\t\tATTR FORK EXTENTS inode data:\n" msgstr "\t\tDane EKSTENTÓW GAÅĘZI ATRYBUTÓW i-wÄ™zÅ‚a:\n" #: .././logprint/log_print_all.c:359 #, c-format msgid "\t\tATTR FORK BTREE inode data:\n" msgstr "\t\tDane B-DRZEWA GAÅĘZI ATRYBUTÓW i-wÄ™zÅ‚a:\n" #: .././logprint/log_print_all.c:367 #, c-format msgid "\t\tATTR FORK LOCAL inode data:\n" msgstr "\t\tDane LOKALNE GAÅĘZI ATRYBUTÓW i-wÄ™zÅ‚a:\n" #: .././logprint/log_print_all.c:388 #, c-format msgid "" "\tICR: #ag: %d agbno: 0x%x len: %d\n" "\t cnt: %d isize: %d gen: 0x%x\n" msgstr "" "\tICR: #ag: %d agbno: 0x%x len: %d\n" "\t cnt: %d isize: %d gen: 0x%x\n" #: .././logprint/log_print_all.c:440 #, c-format msgid "xlog_recover_print_logitem: illegal type\n" msgstr "xlog_recover_print_logitem: niedozwolony typ\n" #: .././logprint/log_print_all.c:492 #, c-format msgid "%s: illegal type" msgstr "%s: niedozwolony typ" #: .././logprint/log_print_all.c:500 #, c-format msgid ": cnt:%d total:%d " msgstr ": cnt:%d total:%d " #: .././logprint/log_print_all.c:502 #, c-format msgid "a:0x%lx len:%d " msgstr "a:0x%lx len:%d " #: .././logprint/log_print_trans.c:27 #, fuzzy, c-format msgid "TRANS: tid:0x%x #items:%d trans:0x%x q:0x%lx\n" msgstr "TRANS: tid:0x%x typ:%s #elem:%d trans:0x%x q:0x%lx\n" #: .././logprint/log_print_trans.c:53 #, c-format msgid "%s: failed to find head and tail, error: %d\n" msgstr "%s: nie udaÅ‚o siÄ™ odnaleźć poczÄ…tku ani koÅ„ca, błąd: %d\n" #: .././logprint/log_print_trans.c:58 #, c-format msgid " log tail: %lld head: %lld state: %s\n" msgstr " koniec logu: %lld poczÄ…tek: %lld stan: %s\n" #: .././logprint/log_print_trans.c:64 #, c-format msgid " override tail: %d\n" msgstr " koniec override: %d\n" #: .././logprint/log_print_trans.c:84 #, c-format msgid "" "Superblock has unknown incompatible log features (0x%x) enabled.\n" "Output may be incomplete or inaccurate. It is recommended that you\n" "upgrade your xfsprogs installation to match the filesystem features.\n" msgstr "" "Superblok ma włączone nieznane, niezgodne opcje logu (0x%x).\n" "WyjÅ›cie może być niekompletne lub niedokÅ‚adne. Zalecana jest\n" "aktualizacja zainstalowanej wersji xfsprogs, aby zgadzaÅ‚a siÄ™ z opcjami\n" "systemu plików.\n" #: .././logprint/log_print_trans.c:92 #, c-format msgid "%s: failed in xfs_do_recovery_pass, error: %d\n" msgstr "%s: xfs_do_recovery_pass nie powiodÅ‚o siÄ™, błąd: %d\n" #: .././logprint/log_redo.c:71 #, c-format msgid "%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n" msgstr "" "%s: błędny rozmiar formatu efi: %u; oczekiwano %u lub %u; nextents = %u\n" #: .././logprint/log_redo.c:94 .././logprint/log_redo.c:110 #, c-format msgid "%s: xlog_print_trans_efi: malloc failed\n" msgstr "%s: xlog_print_trans_efi: malloc nie powiodÅ‚o siÄ™\n" #: .././logprint/log_redo.c:104 #, c-format msgid "EFI: Not enough data to decode further\n" msgstr "EFI: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_redo.c:118 #, fuzzy, c-format msgid "EFI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:122 #, c-format msgid "EFI free extent data skipped (CONTINUE set, no space)\n" msgstr "PominiÄ™to dane wolnego ekstentu EFI (KONTYNUACJA, brak miejsca)\n" #: .././logprint/log_redo.c:161 #, c-format msgid "%s: xlog_recover_print_efi: malloc failed\n" msgstr "%s: xlog_recover_print_efi: malloc nie powiodÅ‚o siÄ™\n" #: .././logprint/log_redo.c:170 #, fuzzy, c-format msgid "\tEFI: #regs:%d\tnum_extents:%d id:0x%llx\n" msgstr "\tEFI: #regs:%d num_extents:%d id:0x%llx\n" #: .././logprint/log_redo.c:202 #, fuzzy, c-format msgid "EFD: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:210 #, c-format msgid "EFD: Not enough data to decode further\n" msgstr "EFD: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_redo.c:228 #, fuzzy, c-format msgid "\tEFD: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "\tEFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:249 #, fuzzy, c-format msgid "%s: bad size of RUI format: %u; expected %u; nextents = %u\n" msgstr "" "%s: błędny rozmiar formatu efi: %u; oczekiwano %u lub %u; nextents = %u\n" #: .././logprint/log_redo.c:276 .././logprint/log_redo.c:295 #: .././logprint/log_redo.c:424 .././logprint/log_redo.c:443 #: .././logprint/log_redo.c:567 .././logprint/log_redo.c:586 #, fuzzy, c-format msgid "%s: %s: malloc failed\n" msgstr "malloc nie powiodÅ‚o siÄ™: %s\n" #: .././logprint/log_redo.c:288 #, fuzzy, c-format msgid "RUI: Not enough data to decode further\n" msgstr "EFI: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_redo.c:304 #, fuzzy, c-format msgid "RUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:308 #, fuzzy, c-format msgid "RUI extent data skipped (CONTINUE set, no space)\n" msgstr "PominiÄ™to dane wolnego ekstentu EFI (KONTYNUACJA, brak miejsca)\n" #: .././logprint/log_redo.c:359 #, fuzzy, c-format msgid "RUD: #regs: %d\t id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:367 #, fuzzy, c-format msgid "RUD: Not enough data to decode further\n" msgstr "EFD: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_redo.c:401 #, fuzzy, c-format msgid "%s: bad size of CUI format: %u; expected %u; nextents = %u\n" msgstr "" "%s: błędny rozmiar formatu efi: %u; oczekiwano %u lub %u; nextents = %u\n" #: .././logprint/log_redo.c:436 #, fuzzy, c-format msgid "CUI: Not enough data to decode further\n" msgstr "EFI: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_redo.c:452 #, fuzzy, c-format msgid "CUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:456 #, fuzzy, c-format msgid "CUI extent data skipped (CONTINUE set, no space)\n" msgstr "PominiÄ™to dane wolnego ekstentu EFI (KONTYNUACJA, brak miejsca)\n" #: .././logprint/log_redo.c:502 #, fuzzy, c-format msgid "CUD: #regs: %d\t id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:510 #, fuzzy, c-format msgid "CUD: Not enough data to decode further\n" msgstr "EFD: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_redo.c:544 #, fuzzy, c-format msgid "%s: bad size of BUI format: %u; expected %u; nextents = %u\n" msgstr "" "%s: błędny rozmiar formatu efi: %u; oczekiwano %u lub %u; nextents = %u\n" #: .././logprint/log_redo.c:579 #, fuzzy, c-format msgid "BUI: Not enough data to decode further\n" msgstr "EFI: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/log_redo.c:595 #, fuzzy, c-format msgid "BUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:599 #, fuzzy, c-format msgid "BUI extent data skipped (CONTINUE set, no space)\n" msgstr "PominiÄ™to dane wolnego ekstentu EFI (KONTYNUACJA, brak miejsca)\n" #: .././logprint/log_redo.c:646 #, fuzzy, c-format msgid "BUD: #regs: %d\t id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_redo.c:654 #, fuzzy, c-format msgid "BUD: Not enough data to decode further\n" msgstr "EFD: Za maÅ‚o danych do dalszego dekodowania\n" #: .././logprint/logprint.c:45 #, c-format msgid "" "Usage: %s [options...] \n" "\n" "Options:\n" " -c\t try to continue if error found in log\n" " -C copy the log from the filesystem to filename\n" " -d\t dump the log in log-record format\n" " -e\t exit when an error is found in the log\n" " -f\t specified device is actually a file\n" " -l filename of external log\n" " -n\t don't try and interpret log data\n" " -o\t print buffer data in hex\n" " -s block # to start printing\n" " -v print \"overwrite\" data\n" " -t\t print out transactional view\n" "\t-b in transactional view, extract buffer info\n" "\t-i in transactional view, extract inode info\n" "\t-q in transactional view, extract quota info\n" " -D print only data; no decoding\n" " -V print version information\n" msgstr "" "SkÅ‚adnia: %s [opcje...] \n" "\n" "Opcje:\n" " -c próba kontynuacji w przypadku błędu w logu\n" " -C skopiowanie logu z systemu plików do pliku o podanej " "nazwie\n" " -d zrzut logu w formacie jego rekordów\n" " -e zakoÅ„czenie po napotkaniu błędu w logu\n" " -f podane urzÄ…dzenie jest plikiem\n" " -l nazwa pliku z logiem zewnÄ™trznym\n" " -n bez prób interpretacji danych logu\n" " -o wypisanie danych bufora szesnastkowo\n" " -s numer pierwszego bloku do wypisania\n" " -v wypisanie danych \"overwrite\"\n" " -t wypisywanie w widoku transakcyjnym\n" " -b w wid.transakcyjnym: wypisywanie informacji o buforze\n" " -i w wid.transakcyjnym: wypisywanie informacji o i-wÄ™zÅ‚ach\n" " -q w wid.transakcyjnym: wypisywanie informacji o limitach\n" " -D wypisywanie tylko danych, bez dekodowania\n" " -V wypisanie informacji o wersji\n" #: .././logprint/logprint.c:79 #, c-format msgid " Can't open device %s: %s\n" msgstr " Nie można otworzyć urzÄ…dzenia %s: %s\n" #: .././logprint/logprint.c:85 #, c-format msgid " read of XFS superblock failed\n" msgstr " odczyt superbloku XFS-a nie powiódÅ‚ siÄ™\n" #: .././logprint/logprint.c:105 #, c-format msgid "" " external log device not specified\n" "\n" msgstr "" " Nie podano urzÄ…dzenia zewnÄ™trznego loga\n" "\n" #: .././logprint/logprint.c:121 #, c-format msgid "Can't open file %s: %s\n" msgstr "Nie można otworzyć pliku %s: %s\n" #: .././logprint/logprint.c:222 #, c-format msgid "xfs_logprint:\n" msgstr "xfs_logprint:\n" #: .././logprint/logprint.c:231 #, c-format msgid " data device: 0x%llx\n" msgstr " urzÄ…dzenie danych: 0x%llx\n" #: .././logprint/logprint.c:234 #, c-format msgid " log file: \"%s\" " msgstr " plik logu: \"%s\" " #: .././logprint/logprint.c:236 #, c-format msgid " log device: 0x%llx " msgstr " urzÄ…dzenie logu: 0x%llx " #: .././logprint/logprint.c:239 #, c-format msgid "" "daddr: %lld length: %lld\n" "\n" msgstr "" "daddr: %lld dÅ‚ugość: %lld\n" "\n" #: .././mkfs/proto.c:79 #, c-format msgid "%s: failed to open %s: %s\n" msgstr "%s: nie udaÅ‚o siÄ™ otworzyć %s: %s\n" #: .././mkfs/proto.c:86 .././mkfs/proto.c:309 #, c-format msgid "%s: read failed on %s: %s\n" msgstr "%s: odczyt nie powiódÅ‚ siÄ™ dla %s: %s\n" #: .././mkfs/proto.c:91 #, c-format msgid "%s: proto file %s premature EOF\n" msgstr "%s: plik prototypu %s skoÅ„czyÅ‚ siÄ™ przedwczeÅ›nie\n" #: .././mkfs/proto.c:125 msgid "cannot reserve space" msgstr "nie można zarezerwować miejsca" #: .././mkfs/proto.c:180 #, c-format msgid "%s: premature EOF in prototype file\n" msgstr "%s: przedwczesny EOF w pliku prototypu\n" #: .././mkfs/proto.c:200 msgid "error reserving space for a file" msgstr "błąd podczas rezerwowania miejsca na plik" #: .././mkfs/proto.c:267 msgid "error allocating space for a file" msgstr "błąd podczas przydzielania miejsca na plik" #: .././mkfs/proto.c:271 #, c-format msgid "%s: cannot allocate space for file\n" msgstr "%s: nie można przydzielić miejsca na plik\n" #: .././mkfs/proto.c:336 msgid "directory createname error" msgstr "błąd tworzenia nazwy katalogu" #: .././mkfs/proto.c:350 msgid "directory create error" msgstr "błąd tworzenia katalogu" #: .././mkfs/proto.c:415 .././mkfs/proto.c:427 .././mkfs/proto.c:438 #: .././mkfs/proto.c:445 #, c-format msgid "%s: bad format string %s\n" msgstr "%s: błędny Å‚aÅ„cuch formatujÄ…cy %s\n" #: .././mkfs/proto.c:466 .././mkfs/proto.c:513 .././mkfs/proto.c:528 #: .././mkfs/proto.c:540 .././mkfs/proto.c:552 .././mkfs/proto.c:563 msgid "Inode allocation failed" msgstr "Przydzielanie i-wÄ™zÅ‚a nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:481 #, fuzzy, c-format msgid "%s: Bad value %s for proto file %s\n" msgstr "błędna wartość diagnostyki %s\n" #: .././mkfs/proto.c:490 msgid "Inode pre-allocation failed" msgstr "Wczesne przydzielanie i-wÄ™zÅ‚a nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:500 msgid "Pre-allocated file creation failed" msgstr "Tworzenie wczeÅ›nie przydzielonego pliku nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:582 msgid "Directory creation failed" msgstr "Tworzenie katalogu nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:603 msgid "Unknown format" msgstr "Nieznany format" #: .././mkfs/proto.c:608 msgid "Error encountered creating file from prototype file" msgstr "WystÄ…piÅ‚ błąd podczas tworzenia pliku z pliku prototypu" #: .././mkfs/proto.c:660 msgid "Realtime bitmap inode allocation failed" msgstr "Przydzielanie i-wÄ™zÅ‚a bitmapy realtime nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:677 msgid "Realtime summary inode allocation failed" msgstr "Tworzenie i-wÄ™zÅ‚a opisu realtime nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:704 msgid "Allocation of the realtime bitmap failed" msgstr "Przydzielenie bitmapy realtime nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:717 msgid "Completion of the realtime bitmap failed" msgstr "UzupeÅ‚nienie bitmapy realtime nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:740 msgid "Allocation of the realtime summary failed" msgstr "Przydzielenie opisu realtime nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:752 msgid "Completion of the realtime summary failed" msgstr "UzupeÅ‚nienie opisu realtime nie powiodÅ‚o siÄ™" #: .././mkfs/proto.c:770 msgid "Error initializing the realtime space" msgstr "Błąd podczas inicjalizacji przestrzeni realtime" #: .././mkfs/proto.c:775 msgid "Error completing the realtime space" msgstr "Błąd podczas uzupeÅ‚niania przestrzeni realtime" #: .././mkfs/xfs_mkfs.c:752 #, c-format msgid "both data sunit and data swidth options must be specified\n" msgstr "trzeba podać obie opcje sunit i swidth dla danych\n" #: .././mkfs/xfs_mkfs.c:760 #, c-format msgid "both data su and data sw options must be specified\n" msgstr "trzeba podać obie opcje su i sw dla danych\n" #: .././mkfs/xfs_mkfs.c:767 #, c-format msgid "data su must be a multiple of the sector size (%d)\n" msgstr "su danych musi być wielokrotnoÅ›ciÄ… rozmiaru sektora (%d)\n" #: .././mkfs/xfs_mkfs.c:778 #, c-format msgid "" "data stripe width (%d) must be a multiple of the data stripe unit (%d)\n" msgstr "" "szerokość pasa danych (%d) musi być wielokrotnoÅ›ciÄ… jednostki pasa danych " "(%d)\n" #: .././mkfs/xfs_mkfs.c:791 .././mkfs/xfs_mkfs.c:797 #, c-format msgid "log stripe unit (%d) must be a multiple of the block size (%d)\n" msgstr "" "jednostka pasa logu (%d) musi być wielokrotnoÅ›ciÄ… rozmiaru bloku (%d)\n" #: .././mkfs/xfs_mkfs.c:817 #, fuzzy, c-format msgid "if -%s file then -%s name and -%s size are required\n" msgstr "jeÅ›li podano -d file, to -d name i -d size sÄ… wymagane\n" #: .././mkfs/xfs_mkfs.c:823 #, fuzzy, c-format msgid "No device name specified\n" msgstr "" " Nie podano urzÄ…dzenia zewnÄ™trznego loga\n" "\n" #: .././mkfs/xfs_mkfs.c:835 #, fuzzy, c-format msgid "Error accessing specified device %s: %s\n" msgstr " Nie można otworzyć urzÄ…dzenia %s: %s\n" #: .././mkfs/xfs_mkfs.c:843 #, c-format msgid "%s: Use the -f option to force overwrite.\n" msgstr "%s: Można użyć opcji -f do wymuszenia nadpisania.\n" #: .././mkfs/xfs_mkfs.c:864 #, c-format msgid "specified \"-%s file\" on a block device %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:872 #, fuzzy, c-format msgid "specified device %s not a file or block device\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku inobt %d/%d\n" #: .././mkfs/xfs_mkfs.c:903 #, c-format msgid "log size %lld is not a multiple of the log stripe unit %d\n" msgstr "rozmiar logu %lld nie jest wielokrotnoÅ›ciÄ… jednostki pasa logu %d\n" #: .././mkfs/xfs_mkfs.c:931 #, c-format msgid "Due to stripe alignment, the internal log size (%lld) is too large.\n" msgstr "" "Ze wzglÄ™du na wyrównanie do rozmiaru pasa rozmiar wewnÄ™trznego logu (%lld) " "jest zbyt duży.\n" #: .././mkfs/xfs_mkfs.c:933 #, c-format msgid "Must fit within an allocation group.\n" msgstr "Musi zmieÅ›cić siÄ™ wewnÄ…trz grupy alokacji.\n" #: .././mkfs/xfs_mkfs.c:944 #, c-format msgid "log size %lld blocks too small, minimum size is %d blocks\n" msgstr "" "rozmiar logu %lld bloków jest zbyt maÅ‚y, minimalny rozmiar to %d bloków\n" #: .././mkfs/xfs_mkfs.c:950 #, c-format msgid "log size %lld blocks too large, maximum size is %lld blocks\n" msgstr "" "rozmiar logu %lld bloków jest zbyt duży, maksymalny rozmiar to %lld bloków\n" #: .././mkfs/xfs_mkfs.c:956 #, c-format msgid "log size %lld bytes too large, maximum size is %lld bytes\n" msgstr "" "rozmiar logu %lld bajtów jest zbyt duży, maksymalny rozmiar to %lld bajtów\n" #: .././mkfs/xfs_mkfs.c:993 #, c-format msgid "agsize (%lld blocks) too small, need at least %lld blocks\n" msgstr "agsize (%lld bloków) zbyt maÅ‚e, potrzeba co najmniej %lld bloków\n" #: .././mkfs/xfs_mkfs.c:1001 #, c-format msgid "agsize (%lld blocks) too big, maximum is %lld blocks\n" msgstr "agsize (%lld bloków) zbyt duże, maksimum to %lld bloków\n" #: .././mkfs/xfs_mkfs.c:1009 #, c-format msgid "agsize (%lld blocks) too big, data area is %lld blocks\n" msgstr "agsize (%lld bloków) zbyt duże, obszar danych to %lld bloków\n" #: .././mkfs/xfs_mkfs.c:1016 #, c-format msgid "too many allocation groups for size = %lld\n" msgstr "zbyt dużo grup alokacji dla rozmiaru = %lld\n" #: .././mkfs/xfs_mkfs.c:1018 #, c-format msgid "need at most %lld allocation groups\n" msgstr "potrzeba najwyżej %lld grup alokacji\n" #: .././mkfs/xfs_mkfs.c:1026 #, c-format msgid "too few allocation groups for size = %lld\n" msgstr "zbyt maÅ‚o grup alokacji dla rozmiaru = %lld\n" #: .././mkfs/xfs_mkfs.c:1028 #, c-format msgid "need at least %lld allocation groups\n" msgstr "potrzeba co najmniej %lld grup alokacji\n" #: .././mkfs/xfs_mkfs.c:1041 #, c-format msgid "last AG size %lld blocks too small, minimum size is %lld blocks\n" msgstr "" "rozmiar ostatniej AG %lld bloków zbyt maÅ‚y, minimalny rozmiar to %lld " "bloków\n" #: .././mkfs/xfs_mkfs.c:1052 #, c-format msgid "%lld allocation groups is too many, maximum is %lld\n" msgstr "%lld grup alokacji to zbyt dużo, maksimum to %lld\n" #: .././mkfs/xfs_mkfs.c:1082 #, c-format msgid "error reading existing superblock -- failed to memalign buffer\n" msgstr "" "błąd podczas odczytu istniejÄ…cego superbloku - nie udaÅ‚o siÄ™ wykonać " "memalign dla bufora\n" #: .././mkfs/xfs_mkfs.c:1097 #, fuzzy, c-format msgid "error reading existing superblock: %s\n" msgstr "błąd podczas odczytu głównego superbloku\n" #: .././mkfs/xfs_mkfs.c:1267 #, fuzzy, c-format msgid "Illegal value %s for -%c %s option. %s\n" msgstr "Niedozwolona wartość %s dla opcji -%s\n" #: .././mkfs/xfs_mkfs.c:1342 #, c-format msgid "" "Option -%c %s has undefined minval/maxval.Can't verify value range. This is " "a bug.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1368 #, fuzzy msgid "value is too small" msgstr "\tCzy cel \"%s\" jest zbyt maÅ‚y?\n" #: .././mkfs/xfs_mkfs.c:1370 #, fuzzy msgid "value is too large" msgstr "rozmiar bloku %llu jest zbyt duży\n" #: .././mkfs/xfs_mkfs.c:1372 msgid "value must be a power of 2" msgstr "" #: .././mkfs/xfs_mkfs.c:1932 #, c-format msgid "extra arguments\n" msgstr "nadmiarowe argumenty\n" #: .././mkfs/xfs_mkfs.c:1949 #, c-format msgid "illegal block size %d\n" msgstr "niedozwolony rozmiar bloku %d\n" #: .././mkfs/xfs_mkfs.c:1954 #, fuzzy, c-format msgid "Minimum block size for CRC enabled filesystems is %d bytes.\n" msgstr "Minimalny rozmiar i-wÄ™zÅ‚a dla CRC to %d bajtów\n" #: .././mkfs/xfs_mkfs.c:1959 #, fuzzy, c-format msgid "cannot disable ftype with crcs enabled\n" msgstr "nie można podać jednoczeÅ›nie crc i ftype\n" #: .././mkfs/xfs_mkfs.c:2013 #, c-format msgid "specified blocksize %d is less than device physical sector size %d\n" msgstr "" "podany rozmiar bloku %d jest mniejszy niż rozmiar fizycznego sektora " "urzÄ…dzenia (%d)\n" #: .././mkfs/xfs_mkfs.c:2016 #, c-format msgid "switching to logical sector size %d\n" msgstr "przełączono na rozmiar sektora logicznego %d\n" #: .././mkfs/xfs_mkfs.c:2034 #, c-format msgid "illegal sector size %d\n" msgstr "niedozwolony rozmiar sektora %d\n" #: .././mkfs/xfs_mkfs.c:2037 #, c-format msgid "block size %d cannot be smaller than logical sector size %d\n" msgstr "" "rozmiar bloku %d nie może być mniejszy niż rozmiar sektora logicznego %d\n" #: .././mkfs/xfs_mkfs.c:2042 #, c-format msgid "illegal sector size %d; hw sector is %d\n" msgstr "niedozwolony rozmiar sektora %d; sektor sprzÄ™towy ma %d\n" #: .././mkfs/xfs_mkfs.c:2048 #, c-format msgid "illegal log sector size %d\n" msgstr "niedozwolony rozmiar sektora logu %d\n" #: .././mkfs/xfs_mkfs.c:2064 .././mkfs/xfs_mkfs.c:2194 #, c-format msgid "Minimum inode size for CRCs is %d bytes\n" msgstr "Minimalny rozmiar i-wÄ™zÅ‚a dla CRC to %d bajtów\n" #: .././mkfs/xfs_mkfs.c:2072 #, c-format msgid "Inodes always aligned for CRC enabled filesytems\n" msgstr "I-wÄ™zÅ‚y sÄ… zawsze wyrównane dla systemów plików z CRC\n" #: .././mkfs/xfs_mkfs.c:2079 #, c-format msgid "Lazy superblock counted always enabled for CRC enabled filesytems\n" msgstr "" "Leniwe liczenie syperbloków jest zawsze włączone dla systemów plików z CRC\n" #: .././mkfs/xfs_mkfs.c:2086 #, c-format msgid "V2 logs always enabled for CRC enabled filesytems\n" msgstr "Logi V2 sÄ… zawsze włączone dla systemów plików z CRC\n" #: .././mkfs/xfs_mkfs.c:2093 #, c-format msgid "V2 attribute format always enabled on CRC enabled filesytems\n" msgstr "Format atrybutów V2 jest zawsze włączony dla systemów plików z CRC\n" #: .././mkfs/xfs_mkfs.c:2101 #, c-format msgid "32 bit Project IDs always enabled on CRC enabled filesytems\n" msgstr "32-bitowe ID projektów sÄ… zawsze włączone dla systemów plików z CRC\n" #: .././mkfs/xfs_mkfs.c:2116 #, fuzzy, c-format msgid "finobt not supported without CRC support\n" msgstr "uwaga: finobt nie jest obsÅ‚ugiwane bez obsÅ‚ugi CRC, wyłączono.\n" #: .././mkfs/xfs_mkfs.c:2123 #, fuzzy, c-format msgid "sparse inodes not supported without CRC support\n" msgstr "uwaga: finobt nie jest obsÅ‚ugiwane bez obsÅ‚ugi CRC, wyłączono.\n" #: .././mkfs/xfs_mkfs.c:2130 #, fuzzy, c-format msgid "rmapbt not supported without CRC support\n" msgstr "uwaga: finobt nie jest obsÅ‚ugiwane bez obsÅ‚ugi CRC, wyłączono.\n" #: .././mkfs/xfs_mkfs.c:2137 #, fuzzy, c-format msgid "reflink not supported without CRC support\n" msgstr "uwaga: finobt nie jest obsÅ‚ugiwane bez obsÅ‚ugi CRC, wyłączono.\n" #: .././mkfs/xfs_mkfs.c:2146 #, c-format msgid "rmapbt not supported with realtime devices\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2154 #, c-format msgid "illegal directory block size %d\n" msgstr "niedozwolony rozmiar bloku katalogu %d\n" #: .././mkfs/xfs_mkfs.c:2173 #, c-format msgid "illegal data length %lld, not a multiple of %d\n" msgstr "niedozwolona dÅ‚ugość danych %lld, nie jest wielokrotnoÅ›ciÄ… %d\n" #: .././mkfs/xfs_mkfs.c:2179 #, c-format msgid "warning: data length %lld not a multiple of %d, truncated to %lld\n" msgstr "" "uwaga: dÅ‚ugość danych %lld nie jest wielokrotnoÅ›ciÄ… %d, uciÄ™to do %lld\n" #: .././mkfs/xfs_mkfs.c:2205 #, c-format msgid "illegal log length %lld, not a multiple of %d\n" msgstr "niedozwolona dÅ‚ugość logu %lld, nie jest wielokrotnoÅ›ciÄ… %d\n" #: .././mkfs/xfs_mkfs.c:2212 #, c-format msgid "warning: log length %lld not a multiple of %d, truncated to %lld\n" msgstr "uwaga: dÅ‚ugość logu %lld nie jest wielokrotnoÅ›ciÄ… %d, uciÄ™to do %lld\n" #: .././mkfs/xfs_mkfs.c:2222 #, c-format msgid "illegal rt length %lld, not a multiple of %d\n" msgstr "niedozwolona dÅ‚ugość rt %lld, nie jest wielokrotnoÅ›ciÄ… %d\n" #: .././mkfs/xfs_mkfs.c:2229 #, c-format msgid "warning: rt length %lld not a multiple of %d, truncated to %lld\n" msgstr "uwaga: dÅ‚ugość rt %lld nie jest wielokrotnoÅ›ciÄ… %d, uciÄ™to do %lld\n" #: .././mkfs/xfs_mkfs.c:2242 #, c-format msgid "illegal rt extent size %lld, not a multiple of %d\n" msgstr "niedozwolony rozmiar ekstentu rt %lld, nie jest wielokrotnoÅ›ciÄ… %d\n" #: .././mkfs/xfs_mkfs.c:2285 #, c-format msgid "illegal inode size %d\n" msgstr "niedozwolony rozmiar i-wÄ™zÅ‚a %d\n" #: .././mkfs/xfs_mkfs.c:2290 #, c-format msgid "allowable inode size with %d byte blocks is %d\n" msgstr "dozwolony rozmiar i-wÄ™zÅ‚a przy blokach %d-bajtowych to %d\n" #: .././mkfs/xfs_mkfs.c:2294 #, c-format msgid "allowable inode size with %d byte blocks is between %d and %d\n" msgstr "dozwolone rozmiary i-wÄ™zÅ‚a przy blokach %d-bajtowych sÄ… od %d do %d\n" #: .././mkfs/xfs_mkfs.c:2302 #, c-format msgid "log stripe unit specified, using v2 logs\n" msgstr "podano jednostkÄ™ pasa logu, użyto logów v2\n" #: .././mkfs/xfs_mkfs.c:2317 #, c-format msgid "no device name given in argument list\n" msgstr "nie podano nazwy urzÄ…dzenia w liÅ›cie argumentów\n" #: .././mkfs/xfs_mkfs.c:2353 msgid "internal log" msgstr "log wewnÄ™trzny" #: .././mkfs/xfs_mkfs.c:2355 msgid "volume log" msgstr "log na wolumenie" #: .././mkfs/xfs_mkfs.c:2357 #, c-format msgid "no log subvolume or internal log\n" msgstr "brak podwolumenu logu ani logu wewnÄ™trznego\n" #: .././mkfs/xfs_mkfs.c:2364 msgid "volume rt" msgstr "wolumen rt" #: .././mkfs/xfs_mkfs.c:2369 #, c-format msgid "" "size %s specified for data subvolume is too large, maximum is %lld blocks\n" msgstr "" "rozmiar %s podany dla podwolumenu danych jest zbyt duży, maksimum to %lld " "bloków\n" #: .././mkfs/xfs_mkfs.c:2376 #, c-format msgid "can't get size of data subvolume\n" msgstr "nie można pobrać rozmiaru podwolumenu danych\n" #: .././mkfs/xfs_mkfs.c:2381 #, c-format msgid "size %lld of data subvolume is too small, minimum %d blocks\n" msgstr "" "rozmiar %lld dla podwolumenu danych jest zbyt maÅ‚y, minimum to %d bloków\n" #: .././mkfs/xfs_mkfs.c:2388 #, c-format msgid "can't have both external and internal logs\n" msgstr "nie można mieć jednoczeÅ›nie zewnÄ™trznego i wewnÄ™trznego logu\n" #: .././mkfs/xfs_mkfs.c:2392 #, c-format msgid "data and log sector sizes must be equal for internal logs\n" msgstr "" "rozmiary sektora danych i logu muszÄ… być równe dla logów wewnÄ™trznych\n" #: .././mkfs/xfs_mkfs.c:2398 #, c-format msgid "" "Warning: the data subvolume sector size %u is less than the sector size \n" "reported by the device (%u).\n" msgstr "" "Uwaga: rozmiar sektora podwolumenu danych %u jest mniejszy od rozmiaru\n" "sektora zgÅ‚aszanego przez urzÄ…dzenie (%u).\n" #: .././mkfs/xfs_mkfs.c:2404 #, c-format msgid "" "Warning: the log subvolume sector size %u is less than the sector size\n" "reported by the device (%u).\n" msgstr "" "Uwaga: rozmiar sektora podwolumenu logu %u jest mniejszy od rozmiaru\n" "sektora zgÅ‚aszanego przez urzÄ…dzenie (%u).\n" #: .././mkfs/xfs_mkfs.c:2410 #, c-format msgid "" "Warning: the realtime subvolume sector size %u is less than the sector size\n" "reported by the device (%u).\n" msgstr "" "Uwaga: rozmiar sektora podwolumenu realtime %u jest mniejszy od rozmiaru\n" "sektora zgÅ‚aszanego przez urzÄ…dzenie (%u).\n" #: .././mkfs/xfs_mkfs.c:2417 #, c-format msgid "" "size %s specified for rt subvolume is too large, maximum is %lld blocks\n" msgstr "" "rozmiar %s podany dla podwolumenu rt jest zbyt duży, maksimum to %lld " "bloków\n" #: .././mkfs/xfs_mkfs.c:2425 #, c-format msgid "size specified for non-existent rt subvolume\n" msgstr "podano rozmiar dla nie istniejÄ…cego podwolumenu rt\n" #: .././mkfs/xfs_mkfs.c:2440 #, c-format msgid "" "%s: Specified data stripe unit %d is not the same as the volume stripe unit " "%d\n" msgstr "" "%s: Podana jednostka pasa danych %d nie jest taka sama jak jednostka pasa " "wolumenu %d\n" #: .././mkfs/xfs_mkfs.c:2447 #, c-format msgid "" "%s: Specified data stripe width %d is not the same as the volume stripe " "width %d\n" msgstr "" "%s: Podana szerokość pasa danych %d nie jest taka sama jak szerokość pasa " "wolumenu %d\n" #: .././mkfs/xfs_mkfs.c:2465 #, c-format msgid "agsize (%lld) not a multiple of fs blk size (%d)\n" msgstr "" "agsize (%lld) nie jest wielokrotnoÅ›ciÄ… rozmiaru bloku systemu plików (%d)\n" #: .././mkfs/xfs_mkfs.c:2515 #, c-format msgid "agsize rounded to %lld, swidth = %d\n" msgstr "agsize zaokrÄ…glone do %lld, swidth = %d\n" #: .././mkfs/xfs_mkfs.c:2547 #, c-format msgid "" "Warning: AG size is a multiple of stripe width. This can cause performance\n" "problems by aligning all AGs on the same disk. To avoid this, run mkfs " "with\n" "an AG size that is one stripe unit smaller, for example %llu.\n" msgstr "" "Uwaga: rozmiar AG jest wielokrotnoÅ›ciÄ… szerokoÅ›ci pasa. Może to spowodować\n" "problemy z wydajnoÅ›ciÄ… poprzez wyrównanie wszystkich AG na tym samym dysku.\n" "Aby temu zapobiec, należy uruchomić mkfs z rozmiarem AG o jednÄ… jednostkÄ™\n" "pasa mniejszym, na przykÅ‚ad %llu.\n" #: .././mkfs/xfs_mkfs.c:2572 #, c-format msgid "" "%s: Stripe unit(%d) or stripe width(%d) is not a multiple of the block size" "(%d)\n" msgstr "" "%s: Jednostka pasa (%d) lub szerokość pasa (%d) nie jest wielokrotnoÅ›ciÄ… " "rozmiaru bloku (%d)\n" #: .././mkfs/xfs_mkfs.c:2613 #, c-format msgid "log stripe unit (%d bytes) is too large (maximum is 256KiB)\n" msgstr "jednostka pasa logu (%d bajtów) jest zbyt duża (maksimum to 256KiB)\n" #: .././mkfs/xfs_mkfs.c:2616 #, c-format msgid "log stripe unit adjusted to 32KiB\n" msgstr "jednostka pasa logu zmodyfikowana na 32KiB\n" #: .././mkfs/xfs_mkfs.c:2632 #, c-format msgid "" "size %s specified for log subvolume is too large, maximum is %lld blocks\n" msgstr "" "rozmiar %s podany dla podwolumenu logu jest zbyt duży, maksimum to %lld " "bloków\n" #: .././mkfs/xfs_mkfs.c:2639 #, c-format msgid "size specified for non-existent log subvolume\n" msgstr "podano rozmiar dla nie istniejÄ…cego podwolumenu logu\n" #: .././mkfs/xfs_mkfs.c:2642 #, c-format msgid "size %lld too large for internal log\n" msgstr "rozmiar %lld jest zbyt duży dla logu wewnÄ™trznego\n" #: .././mkfs/xfs_mkfs.c:2720 #, c-format msgid "internal log size %lld too large, must fit in allocation group\n" msgstr "" "rozmiar wewnÄ™trznego logu %lld zbyt duży, musi siÄ™ zmieÅ›cić w grupie " "alokacji\n" #: .././mkfs/xfs_mkfs.c:2728 #, c-format msgid "log ag number %d too large, must be less than %lld\n" msgstr "liczba ag logu %d zbyt duża, musi być mniejsza niż %lld\n" #: .././mkfs/xfs_mkfs.c:2758 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" msgstr "" "metadane=%-22s isize=%-6d agcount=%lld, agsize=%lld bloków\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u\n" "dane =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u bloków\n" "nazwy =wersja %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, wersja=%d\n" " =%-22s sectsz=%-5u sunit=%d bloków, lazy-count=%d\n" "realtime=%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" #: .././mkfs/xfs_mkfs.c:2876 #, c-format msgid "%s: Growing the data section failed\n" msgstr "%s: PowiÄ™kszenie sekcji danych nie powiodÅ‚o siÄ™\n" #: .././mkfs/xfs_mkfs.c:2906 #, c-format msgid "%s: filesystem failed to initialize\n" msgstr "%s: nie udaÅ‚o siÄ™ zainicjować systemu plików\n" #: .././mkfs/xfs_mkfs.c:3319 #, c-format msgid "%s: root inode created in AG %u, not AG 0\n" msgstr "%s: główny i-wÄ™zeÅ‚ utworzony w AG %u, nie AG 0\n" #: .././mkfs/xfs_mkfs.c:3385 #, c-format msgid "Cannot specify both -%c %s and -%c %s\n" msgstr "Nie można podać jednoczeÅ›nie -%c %s i %c %s\n" #: .././mkfs/xfs_mkfs.c:3396 #, c-format msgid "Illegal value %s for -%s option\n" msgstr "Niedozwolona wartość %s dla opcji -%s\n" #: .././mkfs/xfs_mkfs.c:3413 #, c-format msgid "-%c %s option requires a value\n" msgstr "Opcja -%c %s wymaga wartoÅ›ci\n" #: .././mkfs/xfs_mkfs.c:3426 .././repair/xfs_repair.c:168 #, c-format msgid "option respecified\n" msgstr "ponownie podana opcja\n" #: .././mkfs/xfs_mkfs.c:3435 .././repair/xfs_repair.c:175 #, c-format msgid "unknown option -%c %s\n" msgstr "nieznana opcja -%c %s\n" #: .././mkfs/xfs_mkfs.c:3461 #, c-format msgid "Blocksize must be provided prior to using 'b' suffix.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3470 #, c-format msgid "Sectorsize must be specified prior to using 's' suffix.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3505 #, fuzzy, c-format msgid "" "Usage: %s\n" "/* blocksize */\t\t[-b log=n|size=num]\n" "/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n" "/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num|noalign),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* force overwrite */\t[-f]\n" "/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n" "\t\t\t projid32bit=0|1,sparse=0|1]\n" "/* no discard */\t[-K]\n" "/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* label */\t\t[-L label (maximum 12 characters)]\n" "/* naming */\t\t[-n log=n|size=num,version=2|ci,ftype=0|1]\n" "/* no-op info only */\t[-N]\n" "/* prototype file */\t[-p fname]\n" "/* quiet */\t\t[-q]\n" "/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* sectorsize */\t[-s log=n|size=num]\n" "/* version */\t\t[-V]\n" "\t\t\tdevicename\n" " is required unless -d name=xxx is given.\n" " is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " is xxx (512 byte blocks).\n" msgstr "" "SkÅ‚adnia: %s\n" "/* rozmiar bloku */ [-b log=n|size=liczba]\n" "/* metadane */ [-m crc=0|1,finobt=0|1]\n" "/* podwolumen danych */ [-d agcount=n,agsize=n,file,name=xxx,size=liczba,\n" " (sunit=wartość,swidth=wartość|su=ile,sw=ile|" "noalign),\n" " sectlog=n|sectsize=ile]\n" "/* wym. nadpisania */ [-f]\n" "/* rozmiar i-wÄ™zÅ‚a */ [-i log=n|perblock=n|size=ile,maxpct=n,attr=0|1|2,\n" " projid32bit=0|1]\n" "/* bez porzucenia */ [-K]\n" "/* podwolumen logu */ [-l agnum=n,internal,size=ile,logdev=xxx,version=n\n" " sunit=wartość|su=ile,sectlog=n|sectsize=ile,\n" " lazy-count=0|1]\n" "/* etykieta */ [-L etykieta (maksymalnie 12 znaków)]\n" "/* nazwy */ [-n log=n|size=ile,wersja=2|ci,ftype=0|1]\n" "/* tylko info no-op */ [-N]\n" "/* plik prototypu */ [-p nazwa_pliku]\n" "/* cisza */ [-q]\n" "/* podwolumen rt */ [-r extsize=ile,size=ile,rtdev=xxx]\n" "/* rozmiar sektora */ [-s log=n|size=ile]\n" "/* wersja */ [-V]\n" " nazwa_urzÄ…dzenia\n" " jest wymagana, chyba że podano -d name=xxx.\n" " to xxx (bajtów), xxxs (sektorów), xxxb (bloków systemu plików),\n" " xxxk (xxx KiB), xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB),\n" " xxxp (xxx PiB).\n" " to xxx (512-bajtowych bloków).\n" #: .././quota/edit.c:36 #, c-format msgid "" "\n" " modify quota limits for the specified user\n" "\n" " Example:\n" " 'limit bsoft=100m bhard=110m tanya\n" "\n" " Changes the soft and/or hard block limits, inode limits and/or realtime\n" " block limits that are currently being used for the specified user, group,\n" " or project. The filesystem identified by the current path is modified.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota limits\n" " -p -- modify project quota limits\n" " -u -- modify user quota limits\n" " The block limit values can be specified with a units suffix - accepted\n" " units are: k (kilobytes), m (megabytes), g (gigabytes), and t (terabytes).\n" " The user/group/project can be specified either by name or by number.\n" "\n" msgstr "" "\n" " zmiana limitów quot dla podanego użytkownika\n" "\n" "PrzykÅ‚ad:\n" " 'limit bsoft=100m bhard=110m tanya'\n" "\n" " limit zmienia miÄ™kki i/lub twardy limit bloków, limity i-wÄ™złów i/lub " "limity\n" " bloków realtime aktualnie używane dla podanego użytkownika, grupy lub " "projektu.\n" " System plików okreÅ›lony bieżącÄ… Å›cieżkÄ… jest modyfikowany.\n" " -d - ustawienie wartoÅ›ci domyÅ›lnych, użytych pierwszy raz przy tworzeniu " "pliku\n" " -g - zmiana limitów quot grupy\n" " -p - zmiana limitów quot projektu\n" " -u - zmiana limitów quot użytkownika\n" " WartoÅ›ci limitów bloków mogÄ… być podane z koÅ„cówkÄ… jednostki - przyjmowane\n" " jednostki to: k (kilobajty), m (megabajty), g (gigabajty) i t (terabajty).\n" " Użytkownik/grupa/projekt może być podany za pomocÄ… nazwy lub numeru.\n" "\n" #: .././quota/edit.c:59 #, c-format msgid "" "\n" " modify quota enforcement timeout for the current filesystem\n" "\n" " Example:\n" " 'timer -i 3days'\n" " (soft inode limit timer is changed to 3 days)\n" "\n" " Changes the timeout value associated with the block limits, inode limits\n" " and/or realtime block limits for all users, groups, or projects on the\n" " current filesystem.\n" " As soon as a user consumes the amount of space or number of inodes set as\n" " the soft limit, a timer is started. If the timer expires and the user is\n" " still over the soft limit, the soft limit is enforced as the hard limit.\n" " The default timeout is 7 days.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota timer\n" " -p -- modify project quota timer\n" " -u -- modify user quota timer\n" " -b -- modify the blocks-used timer\n" " -i -- modify the inodes-used timer\n" " -r -- modify the blocks-used timer for the (optional) realtime subvolume\n" " The timeout value is specified as a number of seconds, by default.\n" " However, a suffix may be used to alternatively specify minutes (m),\n" " hours (h), days (d), or weeks (w) - either the full word or the first\n" " letter of the word can be used.\n" "\n" msgstr "" "\n" " zmiana czasu wymuszenia limitów dla bieżącego systemu plików\n" "\n" " PrzykÅ‚ad:\n" " 'timer -i 3days'\n" " (zmiana czasu wymuszenia miÄ™kkiego limitu i-wÄ™złów na 3 dni)\n" "\n" " timer zmienia wartość ograniczenia czasu zwiÄ…zanego z limitami bloków,\n" " limitami i-wÄ™złów i/lub limitami bloków realtime dla wszystkich " "użytkowników,\n" " grup lub projektów na bieżącym systemie plików.\n" " Po tym jak użytkownik wykorzysta ilość miejsca lub liczbÄ™ i-wÄ™złów " "ustawionÄ…\n" " jako miÄ™kki limit, zaczyna dziaÅ‚ać zegar. Kiedy czas minie, a użytkownik " "nadal\n" " przekracza miÄ™kki limit, miÄ™kki limit staje siÄ™ twardym.\n" " DomyÅ›lne ograniczenie czasowe to 7 dni.\n" " -d - ustawienie wartoÅ›ci domyÅ›lnych, użytych pierwszy raz przy tworzeniu " "pliku\n" " -g - zmiana czasu dla limitów quot grup\n" " -p - zmiana czasu dla limitów quot projektów\n" " -u - zmiana czasu dla limitów quot użytkowników\n" " -b - zmiana czasu dla użytych bloków\n" " -i - zmiana czasu dla użytych i-wÄ™złów\n" " -r - zmiana czasu dla użytych bloków na (opcjonalnym) podwolumenie " "realtime\n" " Wartość ograniczenia czasu jest podawana domyÅ›lnie jako liczba sekund.\n" " Jednak można dodać koÅ„cówkÄ™, aby podać czas w minutach (m), godzinach (h),\n" " dniach (d) lub tygodniach (w) - można użyć peÅ‚nego sÅ‚owa lub pierwsze " "litery.\n" "\n" #: .././quota/edit.c:91 #, c-format msgid "" "\n" " modify the number of quota warnings sent to the specified user\n" "\n" " Example:\n" " 'warn 2 jimmy'\n" " (tell the quota system that two warnings have been sent to user jimmy)\n" "\n" " Changes the warning count associated with the block limits, inode limits\n" " and/or realtime block limits for the specified user, group, or project.\n" " When a user has been warned the maximum number of times allowed, the soft\n" " limit is enforced as the hard limit. It is intended as an alternative to\n" " the timeout system, where the system administrator updates a count of the\n" " number of warnings issued to people, and they are penalised if the " "warnings\n" " are ignored.\n" " -d -- set maximum warning count, which triggers soft limit enforcement\n" " -g -- set group quota warning count\n" " -p -- set project quota warning count\n" " -u -- set user quota warning count\n" " -b -- set the blocks-used warning count\n" " -i -- set the inodes-used warning count\n" " -r -- set the blocks-used warn count for the (optional) realtime subvolume\n" " The user/group/project can be specified either by name or by number.\n" "\n" msgstr "" "\n" " zmiana liczby ostrzeżeÅ„ quot wysyÅ‚anych do podanego użytkownika\n" "\n" " PrzykÅ‚ad:\n" " 'warn 2 jimmy'\n" " (przekazanie systemowi quota, że wysÅ‚ano 2 ostrzeżenia do użytkownika " "jimmy)\n" "\n" " warn zmienia liczbÄ™ ostrzeżeÅ„ zwiÄ…zanych z limitami bloków, limitami i-" "wÄ™złów\n" " i/lub limitami bloków realtime dla podanego użytkownika, grupy lub " "projektu.\n" " Kiedy użytkownik zostaÅ‚ ostrzeżony maksymalnÄ… dozwolonÄ… liczbÄ™ razy, " "miÄ™kki\n" " limit staje siÄ™ twardym. Jest to pomyÅ›lane jako alternatywa dla systemu\n" " ograniczeÅ„ czasowych, gdzie administrator uaktualnia licznik ostrzeżeÅ„\n" " wysÅ‚anych do ludzi i karze użytkowników ignorujÄ…cych ostrzeżenia.\n" " -d - ustawienie maksymalnej liczby ostrzeżeÅ„, po której wymuszane sÄ… " "limity\n" " -g - ustawienie liczby ostrzeżeÅ„ dla grupy\n" " -p - ustawienie liczby ostrzeżeÅ„ dla projektu\n" " -u - ustawienie liczby ostrzeżeÅ„ dla grupy\n" " -b - ustawienie liczby ostrzeżeÅ„ dla użytych bloków\n" " -i - ustawienie liczby ostrzeżeÅ„ dla użytych i-wÄ™złów\n" " -r - ustawienie liczby ostrzeżeÅ„ dla użytych bloków na podwolumenie " "realtime\n" " Użytkownik/grupa/projekt może być podany za pomocÄ… nazwy lub numeru.\n" "\n" #: .././quota/edit.c:145 #, c-format msgid "%s: cannot set limits: %s\n" msgstr "%s: nie można ustawić limitów: %s\n" #: .././quota/edit.c:166 .././quota/edit.c:584 #, c-format msgid "%s: invalid user name: %s\n" msgstr "%s: nieprawidÅ‚owa nazwa użytkownika: %s\n" #: .././quota/edit.c:189 .././quota/edit.c:601 #, c-format msgid "%s: invalid group name: %s\n" msgstr "%s: nieprawidÅ‚owa nazwa grupy: %s\n" #: .././quota/edit.c:212 .././quota/edit.c:618 #, c-format msgid "%s: invalid project name: %s\n" msgstr "%s: nieprawidÅ‚owa nazwa projektu: %s\n" #: .././quota/edit.c:237 #, c-format msgid "%s: Error: could not parse size %s.\n" msgstr "%s: Błąd: nie udaÅ‚o siÄ™ przeanalizować rozmiaru %s.\n" #: .././quota/edit.c:243 #, c-format msgid "%s: Warning: `%s' in quota blocks is 0 (unlimited).\n" msgstr "%s: Uwaga: `%s' w blokach limitów wynosi 0 (bez ograniczeÅ„).\n" #: .././quota/edit.c:332 #, c-format msgid "%s: unrecognised argument %s\n" msgstr "%s: nierozpoznany argument %s\n" #: .././quota/edit.c:339 #, c-format msgid "%s: cannot find any valid arguments\n" msgstr "%s: nie można znaleźć żadnych poprawnych argumentów\n" #: .././quota/edit.c:457 #, c-format msgid "%s: fopen on %s failed: %s\n" msgstr "%s: fopen na %s nie powiodÅ‚o siÄ™: %s\n" #: .././quota/edit.c:489 #, c-format msgid "%s: cannot set timer: %s\n" msgstr "%s: nie można ustawić czasu: %s\n" #: .././quota/edit.c:568 #, c-format msgid "%s: cannot set warnings: %s\n" msgstr "%s: nie można ustawić ostrzeżeÅ„: %s\n" #: .././quota/edit.c:709 #, fuzzy msgid "[-g|-p|-u] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" msgstr "[-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|nazwa" #: .././quota/edit.c:710 msgid "modify quota limits" msgstr "zmiana limitów quot" #: .././quota/edit.c:718 .././quota/report.c:33 .././quota/report.c:768 #, fuzzy msgid "[-g|-p|-u] [-f file]" msgstr "[-gpu] [-f plik]" #: .././quota/edit.c:719 msgid "restore quota limits from a backup file" msgstr "odtworzenie limitów quot z pliku kopii zapasowej" #: .././quota/edit.c:726 #, fuzzy msgid "[-bir] [-g|-p|-u] value" msgstr "[-bir] [-gpu] wartość -d|id|nazwa" #: .././quota/edit.c:727 #, fuzzy msgid "set quota enforcement timeouts" msgstr "pobranie/ustawienie czasu wymuszenia quot" #: .././quota/edit.c:735 #, fuzzy msgid "[-bir] [-g|-p|-u] value -d|id|name" msgstr "[-bir] [-gpu] wartość -d|id|nazwa" #: .././quota/edit.c:736 msgid "get/set enforcement warning counter" msgstr "pobranie/ustawienie licznika ostrzeżeÅ„" #: .././quota/free.c:30 #, c-format msgid "" "\n" " reports the number of free disk blocks and inodes\n" "\n" " This command reports the number of total, used, and available disk blocks.\n" " It can optionally report the same set of numbers for inodes and realtime\n" " disk blocks, and will report on all known XFS filesystem mount points and\n" " project quota paths by default (see 'print' command for a list).\n" " -b -- report the block count values\n" " -i -- report the inode count values\n" " -r -- report the realtime block count values\n" " -h -- report in a human-readable format\n" " -N -- suppress the header from the output\n" "\n" msgstr "" "\n" " informacje o liczbie wolnych bloków i i-wÄ™złów dysku\n" "\n" " To polecenie informuje o liczbie wszystkich, używanych i dostÄ™pnych bloków\n" " dysku. Opcjonalnie informuje o tym samym zestawie liczb dla i-wÄ™złów i " "bloków\n" " realtime oraz domyÅ›lnie zgÅ‚asza wszystkie znane punkty montowania systemu\n" " plików XFS i Å›cieżki quot projektów (patrz lista w poleceniu 'print').\n" " -b - informacje o liczbach bloków\n" " -i - informacje o liczbach i-wÄ™złów\n" " -r - informacje o liczbach bloków realtime\n" " -h - informacje w postaci czytelnej dla czÅ‚owieka\n" " -N - pominiÄ™cie nagłówka z wyjÅ›cia\n" "\n" #: .././quota/free.c:171 #, c-format msgid "%s: project quota flag not set on %s\n" msgstr "%s: flaga quot projektu nie ustawiona dla %s\n" #: .././quota/free.c:180 #, c-format msgid "%s: project ID %u (%s) doesn't match ID %u (%s)\n" msgstr "%s: ID projektu %u (%s) nie zgadza siÄ™ z ID %u (%s)\n" #: .././quota/free.c:247 #, c-format msgid "Filesystem " msgstr "System plików " #: .././quota/free.c:247 #, c-format msgid "Filesystem " msgstr "System plików " #: .././quota/free.c:250 #, c-format msgid " Size Used Avail Use%%" msgstr " Rozmiar Użyto Dost. %%uż." #: .././quota/free.c:251 #, c-format msgid " 1K-blocks Used Available Use%%" msgstr " Bloki 1K Użyto DostÄ™pnych %%uż." #: .././quota/free.c:254 #, c-format msgid " Inodes Used Free Use%%" msgstr " I-wÄ™zÅ‚y Użyto Wolne %%uż." #: .././quota/free.c:255 #, c-format msgid " Inodes IUsed IFree IUse%%" msgstr " I-wÄ™zÅ‚y UżytoI WolneI %%użI" #: .././quota/free.c:256 #, c-format msgid " Pathname\n" msgstr " Åšcieżka\n" #: .././quota/free.c:388 #, fuzzy msgid "[-bir] [-hN] [-f file]" msgstr "[-bir] [hn] [-f plik]" #: .././quota/free.c:389 msgid "show free and used counts for blocks and inodes" msgstr "pokazanie liczby wolnych i zajÄ™tych bloków i i-wÄ™złów" #: .././quota/init.c:49 #, fuzzy, c-format msgid "Usage: %s [-V] [-x] [-f] [-p prog] [-c cmd]... [-d project]... [path]\n" msgstr "" "SkÅ‚adnia: %s [-V] [-x] [-p program] [-c polecenie]... [-d projekt]... " "[Å›cieżka]\n" #: .././quota/init.c:130 #, fuzzy, c-format msgid "%s: command is for XFS filesystems only\n" msgstr "" "aktywny jest plik obcy, polecenie %s jest tylko dla systemów plików XFS\n" #: .././quota/init.c:137 #, c-format msgid "%s: foreign filesystem. Invoke xfs_quota with -f to enable.\n" msgstr "" #: .././quota/path.c:39 #, fuzzy, c-format msgid "%s%sFilesystem Pathname\n" msgstr "%sSystem plików Åšcieżka\n" #: .././quota/path.c:40 msgid " " msgstr " " #: .././quota/path.c:41 #, fuzzy msgid " " msgstr " " #: .././quota/path.c:44 #, c-format msgid "%c%03d%c " msgstr "%c%03d%c " #: .././quota/path.c:47 #, c-format msgid "%-19s %s" msgstr "%-19s %s" #: .././quota/path.c:50 #, c-format msgid " (project %u" msgstr " (projekt %u" #: .././quota/path.c:52 #, c-format msgid ", %s" msgstr ", %s" #: .././quota/path.c:117 #, c-format msgid "No paths are available\n" msgstr "Brak Å›cieżek\n" #: .././quota/path.c:145 msgid "set current path, or show the list of paths" msgstr "ustawienie bieżącej Å›cieżki lub pokazanie listy Å›cieżek" #: .././quota/path.c:153 msgid "list known mount points and projects" msgstr "wypisanie znanych punktów montowaÅ„ i projektów" #: .././quota/project.c:45 #, c-format msgid "" "\n" " list projects or setup a project tree for tree quota management\n" "\n" " Example:\n" " 'project -c logfiles'\n" " (match project 'logfiles' to a directory, and setup the directory tree)\n" "\n" " Without arguments, report all projects found in the /etc/projects file.\n" " The project quota mechanism in XFS can be used to implement a form of\n" " directory tree quota, where a specified directory and all of the files\n" " and subdirectories below it (i.e. a tree) can be restricted to using a\n" " subset of the available space in the filesystem.\n" "\n" " A managed tree must be setup initially using the -c option with a project.\n" " The specified project name or identifier is matched to one or more trees\n" " defined in /etc/projects, and these trees are then recursively descended\n" " to mark the affected inodes as being part of that tree - which sets inode\n" " flags and the project identifier on every file.\n" " Once this has been done, new files created in the tree will automatically\n" " be accounted to the tree based on their project identifier. An attempt to\n" " create a hard link to a file in the tree will only succeed if the project\n" " identifier matches the project identifier for the tree. The xfs_io " "utility\n" " can be used to set the project ID for an arbitrary file, but this can only\n" " be done by a privileged user.\n" "\n" " A previously setup tree can be cleared from project quota control through\n" " use of the -C option, which will recursively descend the tree, clearing\n" " the affected inodes from project quota control.\n" "\n" " The -c option can be used to check whether a tree is setup, it reports\n" " nothing if the tree is correct, otherwise it reports the paths of inodes\n" " which do not have the project ID of the rest of the tree, or if the inode\n" " flag is not set.\n" "\n" " The -p option can be used to manually specify project path without\n" " need to create /etc/projects file. This option can be used multiple times\n" " to specify multiple paths. When using this option only one projid/name can\n" " be specified at command line. Note that /etc/projects is also used if " "exists.\n" "\n" " The -d option allows to descend at most levels of " "directories\n" " below the command line arguments. -d 0 means only apply the actions\n" " to the top level of the projects. -d -1 means no recursion limit " "(default).\n" "\n" " The /etc/projid and /etc/projects file formats are simple, and described\n" " on the xfs_quota man page.\n" "\n" msgstr "" "\n" " wypisanie projektów lub ustanowienie drzewa projektu do zarzÄ…dzania " "limitami\n" "\n" " PrzykÅ‚ad:\n" " 'project -c logfiles'\n" " (dopasowanie projektu 'logfiles' do katalogu i ustanowienie drzewa " "katalogów)\n" "\n" " Bez argumentów project wypisuje wszystkie projekty znalezione w pliku\n" " /etc/projects. Mechanizm quota dla projektów w XFS-ie może być używany do\n" " zaimplementowania formy limitów dla drzewa katalogów, gdzie podany katalog\n" " i wszystkie pliki i podkatalogi poniżej niego (czyli drzewo) mogÄ… być\n" " ograniczone do używania podzbioru miejsca dostÄ™pnego w systemie plików.\n" "\n" " ZarzÄ…dzane drzewo musi być ustanowione poczÄ…tkowo przy użyciu opcji project " "-c.\n" " Podana nazwa lub identyfikator projektu jest dopasowywany do jednego lub\n" " wiÄ™kszej liczby drzew zdefiniowanych w /etc/projects, a nastÄ™pnie te drzewa " "sÄ…\n" " rekurencyjnie przechodzone w celu oznaczenia i-wÄ™złów jako bÄ™dÄ…cych " "częściÄ…\n" " tego drzewa - co ustawia flagi i-wÄ™złów i identyfikator projektu dla " "każdego\n" " pliku.\n" " Po zrobieniu tego nowe pliki tworzone w drzewie bÄ™dÄ… automatycznie liczone " "jako\n" " część drzewa o ich identyfikatorze projektu. Próba utworzenia dowiÄ…zania\n" " zwykÅ‚ego do pliku w drzewie powiedzie siÄ™ tylko jeÅ›li identyfikator " "projektu\n" " pasuje do identyfikatora projektu drzewa. Można użyć narzÄ™dzia xfs_io do\n" " ustawienia ID projektu dla dowolnego pliku, ale może tego dokonać tylko\n" " uprzywilejowany użytkownik.\n" "\n" " Poprzednio ustanowione drzewa można usunąć z kontroli limitów projektu " "poprzez\n" " użycie opcji -C, która rekurencyjnie przejdzie drzewo, usuwajÄ…c i-wÄ™zÅ‚y " "spod\n" " kontroli limitów projektu.\n" "\n" " Opcji -c można użyć do sprawdzenia czy drzewo zostaÅ‚o ustanowione - nie\n" " informuje o niczym jeÅ›li drzewo jest poprawne, a w przeciwnym wypadku " "zgÅ‚asza\n" " Å›cieżki i-wÄ™złów nie majÄ…ce ID projektu takiego jak reszta drzewa lub nie\n" " majÄ…ce ustawionej flagi.\n" "\n" " Opcja -p <Å›cieżka> umożliwia podanie Å›cieżki projektu w linii poleceÅ„\n" " bez potrzeby tworzenia pliku /etc/projects. Ta opcja może być używana\n" " wielokrotnie w celu przekazanie wielu Å›cieżek projektu. Tylko jeden\n" " identyfikator projektu może być podawy w linii poleceÅ„ w momencie\n" " używania opcji -p. JeÅ›li plik /etc/projects istnieje to także jest używany\n" " oprócz Å›cieżek w linii poleceÅ„.\n" "\n" " Opcja -d pozwala na ograniczanie zagłębiania siÄ™ w podkatalogach\n" " projektu do granicy . -d 0 oznacza najwyższy poziom. -d 1 oznacza\n" " brak limitu zagłębiania (domyÅ›lny).\n" "\n" " Format plików /etc/projid i /etc/projects jest prosty i opisany na stronie\n" " manuala xfs_quota.\n" "\n" #: .././quota/project.c:108 .././quota/project.c:153 .././quota/project.c:200 #, c-format msgid "%s: cannot stat file %s\n" msgstr "%s: nie można wykonać stat na pliku %s\n" #: .././quota/project.c:112 .././quota/project.c:157 .././quota/project.c:204 #, c-format msgid "%s: skipping special file %s\n" msgstr "%s: pominiÄ™to plik specjalny %s\n" #: .././quota/project.c:126 #, c-format msgid "%s - project identifier is not set (inode=%u, tree=%u)\n" msgstr "%s - identyfikator projektu nie ustawiony (i-wÄ™zeÅ‚=%u, drzewo=%u)\n" #: .././quota/project.c:130 #, c-format msgid "%s - project inheritance flag is not set\n" msgstr "%s - flaga dziedziczenia projektu nie ustawiona\n" #: .././quota/project.c:178 #, c-format msgid "%s: cannot clear project on %s: %s\n" msgstr "%s: nie można usunąć projektu z %s: %s\n" #: .././quota/project.c:225 #, c-format msgid "%s: cannot set project on %s: %s\n" msgstr "%s: nie można ustawić projektu na %s: %s\n" #: .././quota/project.c:240 #, c-format msgid "Checking project %s (path %s)...\n" msgstr "Sprawdzanie projektu %s (Å›cieżka %s)...\n" #: .././quota/project.c:244 #, c-format msgid "Setting up project %s (path %s)...\n" msgstr "Ustanawianie projektu %s (Å›cieżka %s)...\n" #: .././quota/project.c:248 #, c-format msgid "Clearing project %s (path %s)...\n" msgstr "Usuwanie projektu %s (Å›cieżka %s)...\n" #: .././quota/project.c:271 #, c-format msgid "" "Processed %d (%s and cmdline) paths for project %s with recursion depth %s " "(%d).\n" msgstr "" "Przetworzono %d (z %s oraz z linii poleceÅ„) Å›cieżek dla projektu %s\n" "z ograniczeniem %s (%d)\n" #: .././quota/project.c:274 msgid "infinite" msgstr "nieaktywnym" #: .././quota/project.c:274 msgid "limited" msgstr "aktywnym" #: .././quota/project.c:319 #, c-format msgid "projects file \"%s\" doesn't exist\n" msgstr "plik projektów \"%s\" nie istnieje\n" #: .././quota/project.c:326 #, c-format msgid "" "%s: only one projid/name can be specified when using -p , %d found.\n" msgstr "" "%s: tylko jeden id projektu/nazwa może być podana kiedy opcja -p <Å›cieżka> " "jest w użyciu. Znaleziono %d.\n" #: .././quota/project.c:336 #, c-format msgid "%s - no such project in %s or invalid project number\n" msgstr "%s - nie ma takiego projektu w %s lub błędny numer projektu\n" #: .././quota/project.c:353 msgid "[-c|-s|-C|-d |-p ] project ..." msgstr "[-c|-s|-C| -d |-p <Å›cieżka>] projekt ..." #: .././quota/project.c:356 msgid "check, setup or clear project quota trees" msgstr "sprawdzenie, ustanowienie lub usuniÄ™cie drzew projektów" #: .././quota/quot.c:56 #, c-format msgid "" "\n" " display a summary of filesystem ownership\n" "\n" " -a -- summarise for all local XFS filesystem mount points\n" " -c -- display three columns giving file size in kilobytes, number of files\n" " of that size, and cumulative total of kilobytes in that size or\n" " smaller file. The last row is used as an overflow bucket and is the\n" " total of all files greater than 500 kilobytes.\n" " -v -- display three columns containing the number of kilobytes not\n" " accessed in the last 30, 60, and 90 days.\n" " -g -- display group summary\n" " -p -- display project summary\n" " -u -- display user summary\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n" msgstr "" "\n" " wyÅ›wietlenie podsumowania wÅ‚asnoÅ›ci systemu plików\n" "\n" " -a - podsumowanie dla wszystkich punktów montowania systemów plików XFS\n" " -c - wyÅ›wietlenie trzech kolumn z rozmiarem plików w kilobajtach, liczbÄ…\n" " plików tego rozmiaru i sumÄ… kilobajtów w plikach o tym lub mniejszym\n" " rozmiarze. Ostatni wiersz podsumowuje pliki wiÄ™ksze niż 500 " "kilobajtów.\n" " -v - wyÅ›wietlenie trzech kolumn zawierajÄ…cych liczbÄ™ kilobajtów, do " "których\n" " nie byÅ‚o odwoÅ‚aÅ„ przez ostatnie 30, 60 i 90 dni.\n" " -g - wyÅ›wietlenie podsumowania dla grup\n" " -p - wyÅ›wietlenie podsumowania dla projektów\n" " -u - wyÅ›wietlenie podsumowania dla użytkowników\n" " -b - wyÅ›wietlenie liczby wykorzystanych bloków\n" " -i - wyÅ›wietlenie liczby wykorzystanych i-wÄ™złów\n" " -r - wyÅ›wietlenie liczby wykorzystanych blików realtime\n" " -n - pominiÄ™cie tÅ‚umaczenia identyfikatorów na nazwy, wypisywanie ID\n" " -N - pominiÄ™cie poczÄ…tkowego nagłówka\n" " -f - zapisanie wyjÅ›cia do pliku\n" " (opcjonalny) użytkownik/grupa/projekt może być podany za pomocÄ… nazwy lub\n" " numeru (tzn. uid/gid/projid).\n" #: .././quota/quot.c:221 #, c-format msgid "%s (%s) %s:\n" msgstr "%s (%s) %s:\n" #: .././quota/quot.c:297 #, c-format msgid "%s (%s):\n" msgstr "%s (%s):\n" #: .././quota/quot.c:302 .././quota/quot.c:306 #, c-format msgid "%d\t%llu\t%llu\n" msgstr "%d\t%llu\t%llu\n" #: .././quota/quot.c:425 #, fuzzy msgid "[-bir] [-g|-p|-u] [-acv] [-f file]" msgstr "[-bir] [-gpu] [-acv] [-f plik]" #: .././quota/quot.c:426 msgid "summarize filesystem ownership" msgstr "podsumowanie wÅ‚asnoÅ›ci systemu plików" #: .././quota/quota.c:33 #, c-format msgid "" "\n" " display usage and quota information\n" "\n" " -g -- display group quota information\n" " -p -- display project quota information\n" " -u -- display user quota information\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -v -- increase verbosity in reporting (also dumps zero values)\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n" msgstr "" "\n" " wyÅ›wietlenie informacji o wykorzystaniu miejsca i limitach\n" "\n" " -g - wyÅ›wietlenie informacji o limitach grup\n" " -p - wyÅ›wietlenie informacji o limitach projektów\n" " -u - wyÅ›wietlenie informacji o limitach użytkowników\n" " -b - wyÅ›wietlenie liczby wykorzystanych bloków\n" " -i - wyÅ›wietlenie liczby wykorzystanych i-wÄ™złów\n" " -r - wyÅ›wietlenie liczby wykorzystanych bloków realtime\n" " -h - użycie formatu czytelnego dla czÅ‚owieka\n" " -n - pominiÄ™cie tÅ‚umaczenia identyfikatorów na nazwy, wypisywanie ID\n" " -N - pominiÄ™cie poczÄ…tkowego nagłówka\n" " -v - zwiÄ™kszenie szczegółowoÅ›ci (wypisywanie także wartoÅ›ci zerowych)\n" " -f - zapisanie wyjÅ›cia do pliku\n" " (opcjonalny) użytkownik/grupa/projekt może być podany za pomocÄ… nazwy lub\n" " numeru (tzn. uid/gid/projid).\n" #: .././quota/quota.c:86 #, c-format msgid "" "Disk quotas for %s %s (%u)\n" "Filesystem%s" msgstr "" "Limity dyskowe (quota) dla %s %s (%u)\n" "System plików%s" #: .././quota/quota.c:91 #, c-format msgid " Blocks Quota Limit Warn/Time " msgstr " Bloki Quota Limit Czas ostrz. " #: .././quota/quota.c:92 #, c-format msgid " Blocks Quota Limit Warn/Time " msgstr " Bloki Quota Limit Czas ostrz. " #: .././quota/quota.c:95 #, c-format msgid " Files Quota Limit Warn/Time " msgstr " Pliki Quota Limit Czas ostrz. " #: .././quota/quota.c:96 #, c-format msgid " Files Quota Limit Warn/Time " msgstr " Pliki Quota Limit Czas ostrz. " #: .././quota/quota.c:99 #, c-format msgid "Realtime Quota Limit Warn/Time " msgstr "Realtime Quota Limit Czas ostrz. " #: .././quota/quota.c:100 #, c-format msgid " Realtime Quota Limit Warn/Time " msgstr " Realtime Quota Limit Czas ostrz. " #: .././quota/quota.c:236 #, c-format msgid "%s: cannot find user %s\n" msgstr "%s: nie można odnaleźć użytkownika %s\n" #: .././quota/quota.c:286 #, c-format msgid "%s: cannot find group %s\n" msgstr "%s: nie można odnaleźć grupy %s\n" #: .././quota/quota.c:347 #, c-format msgid "%s: must specify a project name/ID\n" msgstr "%s: należy podać nazwÄ™/ID projektu\n" #: .././quota/quota.c:360 #, c-format msgid "%s: cannot find project %s\n" msgstr "%s: nie można odnaleźć projektu %s\n" #: .././quota/quota.c:470 #, fuzzy msgid "[-bir] [-g|-p|-u] [-hnNv] [-f file] [id|name]..." msgstr "[-bir] [-gpu] [-hnNv] [-f plik] [id|nazwa]..." #: .././quota/quota.c:471 msgid "show usage and limits" msgstr "pokazanie wykorzystania i limitów" #: .././quota/report.c:34 .././quota/report.c:769 msgid "dump quota information for backup utilities" msgstr "zrzucenie informacji o limitach (quota) dla narzÄ™dzi backupowych" #: .././quota/report.c:36 #, c-format msgid "" "\n" " create a backup file which contains quota limits information\n" " -g -- dump out group quota limits\n" " -p -- dump out project quota limits\n" " -u -- dump out user quota limits (default)\n" " -f -- write the dump out to the specified file\n" "\n" msgstr "" "\n" " utworzenie pliku kopii zapasowej zawierajÄ…cego informacje o limitach " "(quota)\n" " -g - zrzucenie limitów dla grup\n" " -p - zrzucenie limitów dla projektów\n" " -u - zrzucenie limitów dla użytkowników (domyÅ›lne)\n" " -f - zapisanie zrzutu do podanego pliku\n" "\n" #: .././quota/report.c:48 #, fuzzy msgid "[-bir] [-gpu] [-ahntlLNU] [-f file]" msgstr "[-bir] [-gpu] [-ahntLNU] [-f plik]" #: .././quota/report.c:49 .././quota/report.c:779 msgid "report filesystem quota information" msgstr "raportowanie informacji o limitach (quota) w systemie plików" #: .././quota/report.c:51 #, fuzzy, c-format msgid "" "\n" " report used space and inodes, and quota limits, for a filesystem\n" " Example:\n" " 'report -igh'\n" " (reports inode usage for all groups, in an easy-to-read format)\n" " This command is the equivalent of the traditional repquota command, which\n" " prints a summary of the disk usage and quotas for the current filesystem,\n" " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -L -- lower ID bound to report on\n" " -U -- upper ID bound to report on\n" " -l -- look up names for IDs in lower-upper range\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" " -u -- report user usage and quota information\n" " -b -- report blocks-used information only\n" " -i -- report inodes-used information only\n" " -r -- report realtime-blocks-used information only\n" "\n" msgstr "" "\n" " informacje o wykorzystanym miejscu i i-wÄ™zÅ‚ach oraz limitach quota dla " "systemu\n" " plików\n" "\n" " PrzykÅ‚ad:\n" " 'report -igh'\n" " (raport o wykorzystaniu i-wÄ™złów dla wszystkich grup w czytelnym formacie)\n" "\n" " To polecenie jest odpowiednikiem tradycyjnego polecenia repquota, " "wypisujÄ…cego\n" " podsumowanie wykorzystania dysku i limitów dla bieżącego systemu plików " "lub\n" " wszystkich systemów plików.\n" " -a - informacje o wszystkich zamontowanych systemach plików z limitami\n" " -h - informacje w formacie czytelnym dla czÅ‚owieka\n" " -n - pominiÄ™cie tÅ‚umaczenia identyfikatorów na nazwy, wypisywanie ID\n" " -N - pominiÄ™cie poczÄ…tkowego nagłówka\n" " -t - zwiÄ™zÅ‚y format, ukrycie wierszy zerowych\n" " -L - dolna granica ID dla wypisywanych informacji\n" " -U - górna granica ID dla wypisywanych informacji\n" " -g - informacje o wykorzystanym miejscu i limitach dla grup\n" " -p - informacje o wykorzystanym miejscu i limitach dla projektów\n" " -u - informacje o wykorzystanym miejscu i limitach dla użytkowników\n" " -b - tylko informacje o wykorzystanych blokach\n" " -i - tylko informacje o wykorzystanych i-wÄ™zÅ‚ach\n" " -r - tylko informacje o wykorzystanych blokach realtime\n" "\n" #: .././quota/report.c:273 #, c-format msgid "%s quota on %s (%s)\n" msgstr "limit %s na %s (%s)\n" #: .././quota/report.c:298 .././quota/report.c:306 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr " Użyto MiÄ™kki Twardy Ostrzeżenie " #: .././quota/report.c:299 .././quota/report.c:307 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr " Użyto MiÄ™kki Twardy Ostrzeżenie " #: .././quota/report.c:302 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr " Użyto MiÄ™kki Twardy Ostrzeżenie" #: .././quota/report.c:303 #, c-format msgid " Used Soft Hard Warn/ Grace " msgstr " Użyto MiÄ™kki Twardy Ostrzeżenie " #: .././quota/report.c:778 msgid "[-bir] [-gpu] [-ahnt] [-f file]" msgstr "[-bir] [-gpu] [-ahnt] [-f plik]" #: .././quota/state.c:33 #, c-format msgid "" "\n" " turn filesystem quota off, both accounting and enforcement\n" "\n" " Example:\n" " 'off -uv' (switch off user quota on the current filesystem)\n" " This command is the equivalent of the traditional quotaoff command,\n" " which disables quota completely on a mounted filesystem.\n" " Note that there is no 'on' command - for XFS filesystems (with the\n" " exception of the root filesystem on IRIX) quota can only be enabled\n" " at mount time, through the use of one of the quota mount options.\n" "\n" " The state command is useful for displaying the current state. Using\n" " the -v (verbose) option with the 'off' command will display the quota\n" " state for the affected filesystem once the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " wyłączenie podsystemu quota (zarówno rozliczania jak i wymuszania)\n" "\n" " PrzykÅ‚ad:\n" " 'off -uv' (wyłączenie limitów użytkownika w bieżącym systemie plików)\n" "\n" " To polecenie jest odpowiednikiem tradycyjnego polecenia quotaoff,\n" " wyłączajÄ…cego caÅ‚kowicie limity na podmontowanym systemie plików.\n" " Należy zauważyć, że nie ma polecenia 'on' - dla systemów plików XFS\n" " (z wyjÄ…tkiem głównego systemu plików pod systemem IRIX) limity można\n" " włączyć wyłącznie na etapie montowania, poprzez użycie jednej z opcji\n" " quota programu mount.\n" "\n" " Polecenie state jest przydatne do wyÅ›wietlania aktualnego stanu. Użycie\n" " opcji -v (szczegółowość) dla polecenia 'off' wyÅ›wietli stan quoty dla\n" " danego systemu plików po zakoÅ„czeniu operacji.\n" " Rodzaj limitu którego dotyczy polecenie można wybrać opcjÄ… -g (grupy),\n" " -p (projekty) lub -u (użytkownicy); domyÅ›lnie polecenie dotyczy limitów\n" " użytkowników (można podać wiele rodzajów).\n" "\n" #: .././quota/state.c:56 #, c-format msgid "" "\n" " query the state of quota on the current filesystem\n" "\n" " This is a verbose status command, reporting whether or not accounting\n" " and/or enforcement are enabled for a filesystem, which inodes are in\n" " use as the quota state inodes, and how many extents and blocks are\n" " presently being used to hold that information.\n" " The quota type is specified via -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " odczytanie stanu podsystemu quota w bieżącym systemie plików\n" "\n" " Jest to polecenie szczegółowo informujÄ…ce o stanie, opisujÄ…ce czy włączone\n" " jest rozliczanie i/lub wymuszanie limitów w systemie plików, które i-wÄ™zÅ‚y\n" " sÄ… wykorzystywane jako i-wÄ™zÅ‚y stanu quot oraz ile ekstentów i bloków jest\n" " aktualnie używana do przechowywania tych informacji.\n" " Rodzaj limitów podaje siÄ™ opcjÄ… -g (grupy), -p (projekty) lub -u " "(użytkownicy);\n" " domyÅ›lnie polecenie dotyczy limitów użytkowników (można podać wiele " "rodzajów).\n" "\n" #: .././quota/state.c:72 #, c-format msgid "" "\n" " enable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and has quota accounting enabled, but not\n" " quota enforcement, enforcement can be enabled with this command.\n" " With the -v (verbose) option, the status of the filesystem will be\n" " reported after the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " włączenie wymuszania limitów w systemie plików\n" "\n" " JeÅ›li system plików jest podmontowany i ma włączone rozliczanie limitów,\n" " ale nie ma wymuszania limitów, można włączyć wymuszanie tym poleceniem.\n" " Z opcjÄ… -v (szczegółowość) po zakoÅ„czeniu operacji zostanie zraportowany\n" " stan systemu plików.\n" " Rodzaj limitów podaje siÄ™ opcjÄ… -g (grupy), -p (projekty) lub -u " "(użytkownicy);\n" " domyÅ›lnie polecenie dotyczy limitów użytkowników (można podać wiele " "rodzajów).\n" "\n" #: .././quota/state.c:88 #, c-format msgid "" "\n" " disable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and is currently enforcing quota, this\n" " provides a mechanism to switch off the enforcement, but continue to\n" " perform used space (and used inodes) accounting.\n" " The affected quota type is -g (groups), -p (projects) or -u (users).\n" "\n" msgstr "" "\n" " wyłączenie wymuszania limitów w systemie plików\n" "\n" " JeÅ›li system plików jest podmontowany i aktualnie wymusza przestrzeganie\n" " limitów, tym poleceniem można wyłączyć wymuszanie, ale nadal pozostawić\n" " rozliczanie wykorzystanego miejsca (oraz i-wÄ™złów).\n" " Rodzaj limitów podaje siÄ™ opcjÄ… -g (grupy), -p (projekty) lub -u " "(użytkownicy).\n" "\n" #: .././quota/state.c:102 #, c-format msgid "" "\n" " remove any space being used by the quota subsystem\n" "\n" " Once quota has been switched 'off' on a filesystem, the space that\n" " was allocated to holding quota metadata can be freed via this command.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" "\n" " zwolnienie miejsca zajmowanego przez podsystem quota\n" "\n" " Po wyłączeniu limitów dla systemu plików można tym poleceniem zwolnić " "miejsce\n" " przydzielone na przechowywanie metadanych quot.\n" " Rodzaj limitów podaje siÄ™ opcjÄ… -g (grupy), -p (projekty) lub -u " "(użytkownicy);\n" " domyÅ›lnie polecenie dotyczy limitów użytkowników (można podać wiele " "rodzajów).\n" "\n" #: .././quota/state.c:121 #, c-format msgid "%s quota state on %s (%s)\n" msgstr "stan limitów %s na %s (%s)\n" #: .././quota/state.c:123 #, c-format msgid " Accounting: %s\n" msgstr " Rozliczanie: %s\n" #: .././quota/state.c:123 .././quota/state.c:124 msgid "ON" msgstr "WÅÄ„CZONE" #: .././quota/state.c:123 .././quota/state.c:124 msgid "OFF" msgstr "WYÅÄ„CZONE" #: .././quota/state.c:124 #, c-format msgid " Enforcement: %s\n" msgstr " Wymuszanie: %s\n" #: .././quota/state.c:126 #, c-format msgid " Inode: #%llu (%llu blocks, %lu extents)\n" msgstr " I-wÄ™zeÅ‚: #%llu (%llu bloków, %lu ekstentów)\n" #: .././quota/state.c:131 #, c-format msgid " Inode: N/A\n" msgstr " I-wÄ™zeÅ‚: N/A\n" #: .././quota/state.c:140 #, c-format msgid "%s grace time: %s\n" msgstr "czas pobÅ‚ażliwoÅ›ci %s: %s\n" #: .././quota/state.c:212 #, c-format msgid "%s quota are not enabled on %s\n" msgstr "Limity %s nie sÄ… włączone na %s\n" #: .././quota/state.c:584 .././quota/state.c:601 .././quota/state.c:609 #: .././quota/state.c:617 msgid "[-gpu] [-v]" msgstr "[-gpu] [-v]" #: .././quota/state.c:585 msgid "permanently switch quota off for a path" msgstr "wyłączenie limitów na staÅ‚e dla Å›cieżki" #: .././quota/state.c:592 msgid "[-gpu] [-a] [-v] [-f file]" msgstr "[-gpu] [-a] [-v] [-f plik]" #: .././quota/state.c:593 msgid "get overall quota state information" msgstr "uzyskanie ogólnych informacji o stanie quot" #: .././quota/state.c:602 msgid "enable quota enforcement" msgstr "włączenie wymuszania limitów" #: .././quota/state.c:610 msgid "disable quota enforcement" msgstr "wyłączenie wymuszania limitów" #: .././quota/state.c:618 msgid "remove quota extents from a filesystem" msgstr "usuniÄ™cie ekstentów zwiÄ…zanych z limitami z systemu plików" #: .././quota/util.c:70 #, c-format msgid "[-none-]" msgstr "[-brak-]" #: .././quota/util.c:70 #, c-format msgid "[--none--]" msgstr "[--brak--]" #: .././quota/util.c:73 #, c-format msgid "[------]" msgstr "[------]" #: .././quota/util.c:73 #, c-format msgid "[--------]" msgstr "[--------]" # XXX: ngettext() #: .././quota/util.c:77 .././quota/util.c:80 msgid "day" msgstr "dzieÅ„" #: .././quota/util.c:77 .././quota/util.c:80 msgid "days" msgstr "dni" #: .././quota/util.c:205 msgid "Blocks" msgstr "Bloki" #: .././quota/util.c:205 msgid "Inodes" msgstr "I-wÄ™zÅ‚y" #: .././quota/util.c:205 msgid "Realtime Blocks" msgstr "Bloki realtime" #: .././quota/util.c:220 msgid "User" msgstr "użytkowników" #: .././quota/util.c:220 msgid "Group" msgstr "grup" #: .././quota/util.c:220 msgid "Project" msgstr "projektów" #: .././quota/util.c:428 #, c-format msgid "%s: open on %s failed: %s\n" msgstr "%s: open dla %s nie powiodÅ‚o siÄ™: %s\n" #: .././quota/util.c:434 #, c-format msgid "%s: fdopen on %s failed: %s\n" msgstr "%s: fdopen dla %s nie powiodÅ‚o siÄ™: %s\n" #: .././repair/agheader.c:40 #, c-format msgid "bad magic # 0x%x for agf %d\n" msgstr "błędna liczba magiczna 0x%x dla agf %d\n" #: .././repair/agheader.c:49 #, c-format msgid "bad version # %d for agf %d\n" msgstr "błędny numer wersji %d dla agf %d\n" #: .././repair/agheader.c:58 #, c-format msgid "bad sequence # %d for agf %d\n" msgstr "błędny numer sekwencji %d dla agf %d\n" #: .././repair/agheader.c:68 #, c-format msgid "bad length %d for agf %d, should be %d\n" msgstr "błędna dÅ‚ugość %d dla agf %d, powinno być %d\n" #: .././repair/agheader.c:81 #, c-format msgid "bad length %d for agf %d, should be %\n" msgstr "błędna dÅ‚ugość %d dla agf %d, powinno być %\n" #: .././repair/agheader.c:95 #, c-format msgid "flfirst %d in agf %d too large (max = %zu)\n" msgstr "flfirst %d w agf %d zbyt duże (maksimum = %zu)\n" #: .././repair/agheader.c:103 #, c-format msgid "fllast %d in agf %d too large (max = %zu)\n" msgstr "fllast %d w agf %d zbyt duże (maksimum = %zu)\n" #: .././repair/agheader.c:120 #, c-format msgid "bad uuid %s for agf %d\n" msgstr "błędny uuid %s dla agf %d\n" #: .././repair/agheader.c:139 #, c-format msgid "bad magic # 0x%x for agi %d\n" msgstr "błędna liczba magiczna 0x%x dla agi %d\n" #: .././repair/agheader.c:148 #, c-format msgid "bad version # %d for agi %d\n" msgstr "błędny numer wersji %d dla agi %d\n" #: .././repair/agheader.c:157 #, c-format msgid "bad sequence # %d for agi %d\n" msgstr "błędny numer sekwencji %d dla agi %d\n" #: .././repair/agheader.c:167 #, c-format msgid "bad length # %d for agi %d, should be %d\n" msgstr "błędna dÅ‚ugość %d dla agi %d, powinno być %d\n" #: .././repair/agheader.c:180 #, c-format msgid "bad length # %d for agi %d, should be %\n" msgstr "błędna dÅ‚ugość %d dla agi %d, powinno być %\n" #: .././repair/agheader.c:199 #, c-format msgid "bad uuid %s for agi %d\n" msgstr "błędny uuid %s dla agi %d\n" #: .././repair/agheader.c:305 #, c-format msgid "zeroing unused portion of %s superblock (AG #%u)\n" msgstr "zerowanie nieużywanej części superbloku %s (AG #%u)\n" #: .././repair/agheader.c:306 .././repair/agheader.c:324 msgid "primary" msgstr "głównego" #: .././repair/agheader.c:306 .././repair/agheader.c:324 msgid "secondary" msgstr "zapasowego" #: .././repair/agheader.c:323 #, c-format msgid "would zero unused portion of %s superblock (AG #%u)\n" msgstr "nieużywana część superbloku %s (AG #%u) zostaÅ‚aby wyzerowana\n" #: .././repair/agheader.c:341 #, c-format msgid "bad flags field in superblock %d\n" msgstr "błędne pole flag w superbloku %d\n" #: .././repair/agheader.c:364 #, c-format msgid "non-null user quota inode field in superblock %d\n" msgstr "niezerowe pole i-wÄ™zÅ‚a limitów użytkowników w superbloku %d\n" #: .././repair/agheader.c:379 #, c-format msgid "non-null group quota inode field in superblock %d\n" msgstr "niezerowe pole i-wÄ™zÅ‚a limitów grup w superbloku %d\n" #: .././repair/agheader.c:400 #, c-format msgid "non-null project quota inode field in superblock %d\n" msgstr "niezerowe pole i-wÄ™zÅ‚a limitów projektu w superbloku %d\n" #: .././repair/agheader.c:412 #, c-format msgid "non-null quota flags in superblock %d\n" msgstr "niezerowe flagi limitów w superbloku %d\n" #: .././repair/agheader.c:430 #, c-format msgid "bad inode alignment field in superblock %d\n" msgstr "błędne pole wyrównania i-wÄ™złów w superbloku %d\n" #: .././repair/agheader.c:443 #, c-format msgid "bad stripe unit/width fields in superblock %d\n" msgstr "błędne pola jednostki/szerokoÅ›ci pasa w superbloku %d\n" #: .././repair/agheader.c:461 #, c-format msgid "bad log/data device sector size fields in superblock %d\n" msgstr "błędne pola rozmiaru sektora urzÄ…dzenia logu/danych w superbloku %d\n" #: .././repair/agheader.c:492 #, c-format msgid "bad on-disk superblock %d - %s\n" msgstr "błędny superblok %d na dysku - %s\n" #: .././repair/agheader.c:499 #, c-format msgid "primary/secondary superblock %d conflict - %s\n" msgstr "konflikt głównego/zapasowego superbloku %d - %s\n" #: .././repair/attr_repair.c:70 #, c-format msgid "bad range claimed [%d, %d) in da block\n" msgstr "błędny przedziaÅ‚ [%d, %d) przypisany w bloku da\n" #: .././repair/attr_repair.c:77 #, c-format msgid "byte range end [%d %d) in da block larger than blocksize %d\n" msgstr "" "koniec przedziaÅ‚u bajtów [%d %d) w bloku da wiÄ™kszy niż rozmiar bloku %d\n" #: .././repair/attr_repair.c:84 #, c-format msgid "multiply claimed byte %d in da block\n" msgstr "wielokrotnie użyty bajt %d w bloku da\n" #: .././repair/attr_repair.c:164 msgid "No memory for ACL check!\n" msgstr "Brak pamiÄ™ci na sprawdzenie ACL!\n" #: .././repair/attr_repair.c:172 msgid "" "entry contains illegal value in attribute named SGI_ACL_FILE or " "SGI_ACL_DEFAULT\n" msgstr "" "wpis zawiera niedozwolonÄ… wartość w atrybucie SGI_ACL_FILE lub " "SGI_ACL_DEFAULT\n" #: .././repair/attr_repair.c:198 msgid "entry contains illegal value in attribute named SGI_MAC_LABEL\n" msgstr "wpis zawiera niedozwolonÄ… wartość w atrybucie SGI_MAC_LABEL\n" #: .././repair/attr_repair.c:204 msgid "entry contains illegal value in attribute named SGI_CAP_FILE\n" msgstr "wpis zawiera niedozwolonÄ… wartość w atrybucie SGI_CAP_FILE\n" #: .././repair/attr_repair.c:244 #, c-format msgid "there are no attributes in the fork for inode %\n" msgstr "nie ma atrybutów w gałęzi dla i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:252 #, c-format msgid "would junk the attribute fork since count is 0 for inode %\n" msgstr "" "gałąź atrybutów zostaÅ‚aby usuniÄ™ta ponieważ licznik wynosi 0 dla i-wÄ™zÅ‚a " "%\n" #: .././repair/attr_repair.c:272 msgid "zero length name entry in attribute fork," msgstr "wpis nazwy zerowej dÅ‚ugoÅ›ci w gałęzi atrybutów," #: .././repair/attr_repair.c:275 .././repair/attr_repair.c:295 #, c-format msgid " truncating attributes for inode % to %d\n" msgstr " uciÄ™to atrybuty dla i-wÄ™zÅ‚a % do %d\n" #: .././repair/attr_repair.c:280 .././repair/attr_repair.c:301 #, c-format msgid " would truncate attributes for inode % to %d\n" msgstr " atrybuty dla i-wÄ™zÅ‚a % zostaÅ‚yby uciÄ™te do %d\n" #: .././repair/attr_repair.c:292 msgid "name or value attribute lengths are too large,\n" msgstr "dÅ‚ugoÅ›ci nazwy lub wartoÅ›ci atrybutów sÄ… zbyt duże,\n" #: .././repair/attr_repair.c:314 msgid "entry contains illegal character in shortform attribute name\n" msgstr "wpis zawiera niedozwolony znak w nazwie atrybutu krótkiego\n" #: .././repair/attr_repair.c:320 msgid "entry has INCOMPLETE flag on in shortform attribute\n" msgstr "wpis ma flagÄ™ NIEPEÅNY w atrybucie krótkim\n" #: .././repair/attr_repair.c:338 #, c-format msgid "removing attribute entry %d for inode %\n" msgstr "usuniÄ™to wpis atrybutu %d dla i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:350 #, c-format msgid "would remove attribute entry %d for inode %\n" msgstr "wpis atrybutu %d dla i-wÄ™zÅ‚a % zostaÅ‚by usuniÄ™ty\n" #: .././repair/attr_repair.c:365 #, c-format msgid "" "would have corrected attribute entry count in inode % from %d to %d\n" msgstr "" "liczba wpisów atrybutów w i-węźle % zostaÅ‚aby poprawiona z %d na %d\n" #: .././repair/attr_repair.c:369 #, c-format msgid "corrected attribute entry count in inode %, was %d, now %d\n" msgstr "" "poprawiono liczbÄ™ wpisów atrybutów w i-węźle % - byÅ‚o %d, jest %d\n" #: .././repair/attr_repair.c:380 #, c-format msgid "" "would have corrected attribute totsize in inode % from %d to %d\n" msgstr "totsize atrybutów w i-węźle % zostaÅ‚by poprawiony z %d na %d\n" #: .././repair/attr_repair.c:385 #, c-format msgid "corrected attribute entry totsize in inode %, was %d, now %d\n" msgstr "" "poprawiono totsize wpisu atrybutów w i-węźle % - byÅ‚o %d, jest %d\n" #: .././repair/attr_repair.c:419 #, c-format msgid "remote block for attributes of inode % is missing\n" msgstr "brak odlegÅ‚ego bloku dla atrybutów i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:428 #, c-format msgid "can't read remote block for attributes of inode %\n" msgstr "nie można odczytać odlegÅ‚ego bloku dla atrybutów i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:435 #, c-format msgid "Corrupt remote block for attributes of inode %\n" msgstr "Uszkodzony odlegÅ‚y blok dla atrybutów i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:476 #, c-format msgid "" "attribute entry %d in attr block %u, inode % has bad name (namelen = " "%d)\n" msgstr "" "wpis atrybutu %d w bloku atrybutów %u, i-węźle % ma błędnÄ… nazwÄ™ " "(namelen = %d)\n" #: .././repair/attr_repair.c:493 #, c-format msgid "" "bad hashvalue for attribute entry %d in attr block %u, inode %\n" msgstr "" "błędna wartość hasza dla wpisu atrybutu %d w bloku atrybutów %u, i-węźle " "%\n" #: .././repair/attr_repair.c:503 #, c-format msgid "" "bad security value for attribute entry %d in attr block %u, inode %\n" msgstr "" "błędna wartość bezpieczeÅ„stwa dla wpisu atrybutu %d w bloku atrybutów %u, i-" "węźle %\n" #: .././repair/attr_repair.c:536 #, c-format msgid "" "inconsistent remote attribute entry %d in attr block %u, ino %\n" msgstr "" "niespójny wpis odlegÅ‚ego atrybutu %d w bloku atrybutów %u, i-węźle " "%\n" #: .././repair/attr_repair.c:546 #, c-format msgid "cannot malloc enough for remotevalue attribute for inode %\n" msgstr "" "nie można przydzielić wystarczajÄ…co dużo dla atrybutu remotevalue dla i-" "wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:548 msgid "SKIPPING this remote attribute\n" msgstr "POMINIĘTO ten atrybut odlegÅ‚y\n" #: .././repair/attr_repair.c:554 #, c-format msgid "remote attribute get failed for entry %d, inode %\n" msgstr "" "pobranie odlegÅ‚ego atrybutu nie powiodÅ‚o siÄ™ dla wpisu %d, i-wÄ™zÅ‚a " "%\n" #: .././repair/attr_repair.c:561 #, c-format msgid "remote attribute value check failed for entry %d, inode %\n" msgstr "" "sprawdzenie wartoÅ›ci odlegÅ‚ego atrybutu nie powiodÅ‚o siÄ™ dla wpisu %d, i-" "wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:600 #, c-format msgid "bad attribute count %d in attr block %u, inode %\n" msgstr "błędna liczba atrybutów %d w bloku atrybutów %u, i-węźle %\n" #: .././repair/attr_repair.c:615 #, c-format msgid "bad attribute nameidx %d in attr block %u, inode %\n" msgstr "błędny nameidx atrybutu %d w bloku atrybutów %u, i-węźle %\n" #: .././repair/attr_repair.c:624 #, c-format msgid "attribute entry #%d in attr block %u, inode % is INCOMPLETE\n" msgstr "" "wpis atrybutu #%d w bloku atrybutów %u, i-węźle % jest NIEPEÅNY\n" #: .././repair/attr_repair.c:635 #, c-format msgid "" "attribute entry %d in attr block %u, inode % claims already used " "space\n" msgstr "" "wpis atrybutu %d w bloku atrybutów %u, i-węźle % odwoÅ‚uje siÄ™ do już " "użytego miejsca\n" #: .././repair/attr_repair.c:658 #, c-format msgid "" "attribute entry %d in attr block %u, inode % claims used space\n" msgstr "" "wpis atrybutu %d w bloku atrybutów %u, i-węźle % odwoÅ‚uje siÄ™ do " "używanego miejsca\n" #: .././repair/attr_repair.c:682 #, c-format msgid "" "- resetting first used heap value from %d to %d in block %u of attribute " "fork of inode %\n" msgstr "" "- przestawiono pierwszÄ… używanÄ… wartość sterty z %d na %d w bloku %u gałęzi " "atrybutów i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:690 #, c-format msgid "" "- would reset first used value from %d to %d in block %u of attribute fork " "of inode %\n" msgstr "" "- pierwsza używana wartość zostaÅ‚aby przestawiona z %d na %d w bloku %u " "gałęzi atrybutów i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:700 #, c-format msgid "" "- resetting usedbytes cnt from %d to %d in block %u of attribute fork of " "inode %\n" msgstr "" "- przestawiono liczbÄ™ użytych bajtów z %d na %d w bloku %u gałęzi atrybutów " "i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:708 #, c-format msgid "" "- would reset usedbytes cnt from %d to %d in block %u of attribute fork of " "%\n" msgstr "" "- liczba użytych bajtów zostaÅ‚aby przestawiona z %d na %d w bloku %u gałęzi " "atrybutów i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:770 #, c-format msgid "can't map block %u for attribute fork for inode %\n" msgstr "" "nie można odwzorować bloku %u dla gałęzi atrybutów dla i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:780 #, c-format msgid "" "can't read file block %u (fsbno %) for attribute fork of inode " "%\n" msgstr "" "nie można odczytać bloku pliku %u (fsbno %) dla gałęzi atrybutów i-" "wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:792 #, c-format msgid "bad attribute leaf magic %#x for inode %\n" msgstr "błędna liczba magiczna liÅ›cia atrybutu %#x dla i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:823 #, c-format msgid "" "bad sibling back pointer for block %u in attribute fork for inode %\n" msgstr "" "błędny wskaźnik wsteczny dla bloku %u w gałęzi atrybutów dla i-wÄ™zÅ‚a " "%\n" #: .././repair/attr_repair.c:858 #, c-format msgid "bad hash path in attribute fork for inode %\n" msgstr "błędna Å›cieżka hasza w gałęzi atrybutów dla i-wÄ™zÅ‚a %\n" #: .././repair/attr_repair.c:940 #, fuzzy, c-format msgid "expected owner inode %, got %llu, attr block %\n" msgstr "" "oczekiwano i-wÄ™zÅ‚a wÅ‚aÅ›ciciela %, napotkano %llu, blok bmbt " "%\n" #: .././repair/attr_repair.c:947 #, fuzzy, c-format msgid "expected block %, got %llu, inode %attr block\n" msgstr "" "oczekiwano i-wÄ™zÅ‚a wÅ‚aÅ›ciciela %, napotkano %llu, blok bmbt " "%\n" #: .././repair/attr_repair.c:954 #, fuzzy, c-format msgid "wrong FS UUID, inode % attr block %\n" msgstr "błędny stan %d, i-wÄ™zeÅ‚ % blok bmap 0x%\n" #: .././repair/attr_repair.c:996 #, c-format msgid "block 0 of inode % attribute fork is missing\n" msgstr "brak bloku 0 i-wÄ™zÅ‚a % gałęzi atrybutów\n" #: .././repair/attr_repair.c:1003 #, c-format msgid "agno of attribute fork of inode % out of regular partition\n" msgstr "agno gałęzi atrybutów i-wÄ™zÅ‚a % spoza zwykÅ‚ej partycji\n" #: .././repair/attr_repair.c:1011 #, c-format msgid "can't read block 0 of inode % attribute fork\n" msgstr "nie można odczytać bloku 0 i-wÄ™zÅ‚a % gałęzi atrybutów\n" #: .././repair/attr_repair.c:1035 #, c-format msgid "" "clearing forw/back pointers in block 0 for attributes in inode %\n" msgstr "" "wyczyszczono wskaźniki forw/back w bloku 0 dla atrybutów w i-węźle " "%\n" #: .././repair/attr_repair.c:1044 #, c-format msgid "" "would clear forw/back pointers in block 0 for attributes in inode %\n" msgstr "" "wskaźniki forw/back w bloku 0 dla atrybutów w i-węźle % zostaÅ‚yby " "wyczyszczone\n" #: .././repair/attr_repair.c:1080 #, c-format msgid "bad attribute leaf magic # %#x for dir ino %\n" msgstr "" "błędna liczba magiczna liÅ›cia atrybutu %#x dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/attr_repair.c:1110 #, c-format msgid "Too many ACL entries, count %d\n" msgstr "Za dużo wpisów ACL, liczba %d\n" #: .././repair/attr_repair.c:1119 msgid "cannot malloc enough for ACL attribute\n" msgstr "nie można wykonać wystarczajÄ…cego malloc dla atrybutu ACL\n" #: .././repair/attr_repair.c:1120 msgid "SKIPPING this ACL\n" msgstr "POMINIĘTO ten ACL\n" #: .././repair/attr_repair.c:1170 .././repair/dinode.c:2065 #, c-format msgid "illegal attribute format %d, ino %\n" msgstr "niedozwolony format atrybutu %d, i-wÄ™zeÅ‚ %\n" #: .././repair/avl.c:1011 .././repair/avl64.c:1032 #, c-format msgid "avl_insert: Warning! duplicate range [%llu,%llu]\n" msgstr "avl_insert: Uwaga! powtórzony przedziaÅ‚ [%llu,%llu]\n" #: .././repair/avl.c:1206 .././repair/avl64.c:1227 #, c-format msgid "Command [fpdir] : " msgstr "Polecenie [fpdir] : " #: .././repair/avl.c:1215 .././repair/avl64.c:1236 #, c-format msgid "end of range ? " msgstr "koniec przedziaÅ‚u? " #: .././repair/avl.c:1226 .././repair/avl64.c:1247 #, c-format msgid "Cannot find %d\n" msgstr "Nie można odnaleźć %d\n" #: .././repair/avl.c:1239 .././repair/avl64.c:1260 #, c-format msgid "size of range ? " msgstr "rozmiar przedziaÅ‚u? " #: .././repair/avl.c:1250 .././repair/avl64.c:1271 #, c-format msgid "End of range ? " msgstr "Koniec przedziaÅ‚u? " #: .././repair/avl.c:1254 .././repair/avl64.c:1275 #, c-format msgid "checklen 0/1 ? " msgstr "checklen 0/1 ? " #: .././repair/avl.c:1261 .././repair/avl64.c:1282 #, c-format msgid "Found something\n" msgstr "Znaleziono coÅ›\n" #: .././repair/bmap.c:53 #, c-format msgid "" "Number of extents requested in blkmap_alloc (%d) overflows 32 bits.\n" "If this is not a corruption, then you will need a 64 bit system\n" "to repair this filesystem.\n" msgstr "" "Liczba ekstentów żądanych w blkmap_alloc (%d) przepeÅ‚nia 32 bity.\n" "JeÅ›li nie jest to efekt uszkodzenia, do naprawy tego systemu plików\n" "niezbÄ™dny jest system 64-bitowy.\n" #: .././repair/bmap.c:66 #, c-format msgid "malloc failed in blkmap_alloc (%zu bytes)\n" msgstr "malloc nie powiodÅ‚o siÄ™ w blkmap_alloc (%zu bajtów)\n" #: .././repair/bmap.c:189 #, c-format msgid "blkmap_getn malloc failed (% bytes)\n" msgstr "malloc w blkmap_getn nie powiodÅ‚o siÄ™ (% bajtów)\n" #: .././repair/bmap.c:296 #, c-format msgid "" "Number of extents requested in blkmap_grow (%d) overflows 32 bits.\n" "You need a 64 bit system to repair this filesystem.\n" msgstr "" "Liczba ekstentów żądanych w blkmap_grow (%d) przepeÅ‚nia 32 bity.\n" "Do naprawy tego systemu plików niezbÄ™dny jest system 64-bitowy.\n" #: .././repair/bmap.c:304 #, c-format msgid "" "Number of extents requested in blkmap_grow (%d) overflowed the\n" "maximum number of supported extents (%d).\n" msgstr "" "Liczba ekstentów żądanych w blkmap_grow (%d) przepeÅ‚niÅ‚a maksymalnÄ…\n" "liczbÄ™ obsÅ‚ugiwanych ekstentów (%d).\n" #: .././repair/bmap.c:312 msgid "realloc failed in blkmap_grow\n" msgstr "realloc nie powiodÅ‚o siÄ™ w blkmap_grow\n" #: .././repair/da_util.c:88 .././repair/prefetch.c:238 msgid "couldn't malloc dir2 buffer list\n" msgstr "nie można przydzielić listy bufora dir2\n" #: .././repair/da_util.c:105 #, fuzzy msgid "attribute" msgstr "atrybutów" #: .././repair/da_util.c:164 .././repair/da_util.c:585 #, fuzzy, c-format msgid "can't read %s block %u for inode %\n" msgstr "nie można odczytać bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/da_util.c:177 #, c-format msgid "found non-root LEAFN node in inode % bno = %u\n" msgstr "znaleziono niegłówny wÄ™zeÅ‚ LEAFN w i-węźle % bno = %u\n" #: .././repair/da_util.c:188 #, fuzzy, c-format msgid "bad %s magic number 0x%x in inode % bno = %u\n" msgstr "błędna liczba magiczna katalogu 0x%x w i-węźle % bno = %u\n" #: .././repair/da_util.c:199 #, fuzzy, c-format msgid "corrupt %s tree block %u for inode %\n" msgstr "uszkodzony blok %u w i-węźle katalogu %\n" #: .././repair/da_util.c:207 #, fuzzy, c-format msgid "bad %s record count in inode %, count = %d, max = %d\n" msgstr "" "błędna liczba rekordów w i-węźle %, liczba = %d, maksimum = %d\n" #: .././repair/da_util.c:221 #, c-format msgid "bad header depth for directory inode %\n" msgstr "błędna głębokość nagłówka dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/da_util.c:232 #, fuzzy, c-format msgid "bad %s btree for inode %\n" msgstr "błędne b-drzewo gałęzi atrybutów dla i-wÄ™zÅ‚a %\n" #: .././repair/da_util.c:282 #, c-format msgid "release_da_cursor_int got unexpected non-null bp, dabno = %u\n" msgstr "" "release_da_cursor_int otrzymaÅ‚o nieoczekiwany niepusty bp, dabno = %u\n" #: .././repair/da_util.c:360 #, fuzzy, c-format msgid "%s block used/count inconsistency - %d/%hu\n" msgstr "niespójność wartoÅ›ci used/count bloku katalogu - %d / %hu\n" #: .././repair/da_util.c:370 #, fuzzy, c-format msgid "%s block hashvalue inconsistency, expected > %u / saw %u\n" msgstr "" "niespójność wartoÅ›ci hasza bloku katalogu/atrybutu - oczekiwano > %u, " "widziano %u\n" #: .././repair/da_util.c:378 #, fuzzy, c-format msgid "bad %s forward block pointer, expected 0, saw %u\n" msgstr "" "błędny wskaźnik bloku w przód katalogu/atrybutu - oczekiwano 0, widziano %u\n" #: .././repair/da_util.c:383 #, fuzzy, c-format msgid "bad %s block in inode %\n" msgstr "błędny blok katalogu w i-węźle %\n" #: .././repair/da_util.c:413 #, fuzzy, c-format msgid "" "correcting bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "poprawiono błędne hashval w bloku katalogu nie bÄ™dÄ…cego liÅ›ciem\n" "\tw i-węźle (poziomu %d) %.\n" #: .././repair/da_util.c:421 #, fuzzy, c-format msgid "" "would correct bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "błędne hashval w bloku katalogu nie bÄ™dÄ…cego liÅ›ciem zostaÅ‚oby poprawione\n" "\tw i-węźle (poziomu %d) %.\n" #: .././repair/da_util.c:574 #, fuzzy, c-format msgid "can't get map info for %s block %u of inode %\n" msgstr "" "nie można uzyskać informacji o mapie dla bloku %u i-wÄ™zÅ‚a katalogu " "%\n" #: .././repair/da_util.c:602 #, fuzzy, c-format msgid "bad magic number %x in %s block %u for inode %\n" msgstr "błędna liczba magiczna %x w bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/da_util.c:609 #, fuzzy, c-format msgid "bad back pointer in %s block %u for inode %\n" msgstr "błędny wskaźnik wstecz w bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/da_util.c:615 #, fuzzy, c-format msgid "entry count %d too large in %s block %u for inode %\n" msgstr "liczba wpisów %d zbyt duża w bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/da_util.c:622 #, fuzzy, c-format msgid "bad level %d in %s block %u for inode %\n" msgstr "błędny poziom %d w bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/da_util.c:686 #, fuzzy, c-format msgid "" "correcting bad hashval in interior %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "poprawiono błędne hashval w wewnÄ™trznym bloku katalogu\n" "\tw i-węźle (poziomu %d) %.\n" #: .././repair/da_util.c:694 #, fuzzy, c-format msgid "" "would correct bad hashval in interior %s block\n" "\tin (level %d) in inode %.\n" msgstr "" "błędne hashval w wewnÄ™trznym bloku katalogu zostaÅ‚oby poprawione\n" "\tw i-węźle (poziomu %d) %.\n" #: .././repair/dino_chunks.c:57 #, c-format msgid "cannot read agbno (%u/%u), disk block %\n" msgstr "nie można odczytać agbno (%u/%u), blok dysku %\n" #: .././repair/dino_chunks.c:150 #, c-format msgid "uncertain inode block %d/%d already known\n" msgstr "niepewny blok i-wÄ™zÅ‚a %d/%d już znany\n" #: .././repair/dino_chunks.c:166 .././repair/dino_chunks.c:438 #: .././repair/dino_chunks.c:497 #, c-format msgid "inode block %d/%d multiply claimed, (state %d)\n" msgstr "blok i-wÄ™zÅ‚a %d/%d już przypisany (stan %d)\n" #: .././repair/dino_chunks.c:173 .././repair/dino_chunks.c:502 #, c-format msgid "inode block %d/%d bad state, (state %d)\n" msgstr "blok i-wÄ™zÅ‚a (%d/%d) w błędnym stanie (stan %d)\n" #: .././repair/dino_chunks.c:445 #, c-format msgid "uncertain inode block overlap, agbno = %d, ino = %\n" msgstr "niepewny blok i-wÄ™zÅ‚a pokrywa siÄ™, agbno = %d, i-wÄ™zeÅ‚ %\n" #: .././repair/dino_chunks.c:484 #, c-format msgid "uncertain inode block % already known\n" msgstr "niepewny blok i-wÄ™zÅ‚a % już znany\n" #: .././repair/dino_chunks.c:578 #, c-format msgid "bad state in block map %d\n" msgstr "błędny stan w mapie bloku %d\n" #: .././repair/dino_chunks.c:583 #, c-format msgid "inode block % multiply claimed, state was %d\n" msgstr "blok i-wÄ™zÅ‚a % wielokrotnie przydzielony, stan byÅ‚ %d\n" #: .././repair/dino_chunks.c:654 #, c-format msgid "failed to allocate %zd bytes of memory\n" msgstr "nie udaÅ‚o siÄ™ przydzielić %zd bajtów pamiÄ™ci\n" #: .././repair/dino_chunks.c:678 #, c-format msgid "cannot read inode %, disk block %, cnt %d\n" msgstr "nie można odczytać i-wÄ™zÅ‚a %, blok dysku %, cnt %d\n" #: .././repair/dino_chunks.c:834 #, c-format msgid "imap claims in-use inode % is free, " msgstr "imap twierdzi, że używany i-wÄ™zeÅ‚ % jest wolny, " #: .././repair/dino_chunks.c:839 msgid "correcting imap\n" msgstr "poprawiono imap\n" #: .././repair/dino_chunks.c:841 msgid "would correct imap\n" msgstr "imap zostaÅ‚oby poprawione\n" #: .././repair/dino_chunks.c:896 #, c-format msgid "cleared root inode %\n" msgstr "wyczyszczono główny i-wÄ™zeÅ‚ %\n" #: .././repair/dino_chunks.c:900 #, c-format msgid "would clear root inode %\n" msgstr "główny wÄ™zeÅ‚ % zostaÅ‚by wyczyszczony\n" #: .././repair/dino_chunks.c:908 #, c-format msgid "cleared realtime bitmap inode %\n" msgstr "wyczyszczono i-wÄ™zeÅ‚ bitmapy realtime %\n" #: .././repair/dino_chunks.c:912 #, c-format msgid "would clear realtime bitmap inode %\n" msgstr "i-wÄ™zeÅ‚ bitmapy realtime % zostaÅ‚by wyczyszczony\n" #: .././repair/dino_chunks.c:920 #, c-format msgid "cleared realtime summary inode %\n" msgstr "wyczyszczono i-wÄ™zeÅ‚ opisu realtime %\n" #: .././repair/dino_chunks.c:924 #, c-format msgid "would clear realtime summary inode %\n" msgstr "i-wÄ™zeÅ‚ opisu realtime % zostaÅ‚by wyczyszczony\n" #: .././repair/dino_chunks.c:928 #, c-format msgid "cleared inode %\n" msgstr "wyczyszczono i-wÄ™zeÅ‚ %\n" #: .././repair/dino_chunks.c:931 #, c-format msgid "would have cleared inode %\n" msgstr "i-wÄ™zeÅ‚ % zostaÅ‚by wyczyszczony\n" #: .././repair/dino_chunks.c:1122 .././repair/dino_chunks.c:1157 #: .././repair/dino_chunks.c:1271 msgid "found inodes not in the inode allocation tree\n" msgstr "znaleziono i-wÄ™zÅ‚y nieobecne w drzewie alokacji i-wÄ™złów\n" #: .././repair/dinode.c:54 msgid "real-time" msgstr "realtime" #: .././repair/dinode.c:55 msgid "regular" msgstr "zwykÅ‚ym" #: .././repair/dinode.c:78 #, c-format msgid "clearing inode % attributes\n" msgstr "wyczyszczono atrybuty i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:81 #, c-format msgid "would have cleared inode % attributes\n" msgstr "atrybuty i-wÄ™zÅ‚a % zostaÅ‚yby wyczyszczone\n" #: .././repair/dinode.c:444 #, c-format msgid "" "inode % - bad rt extent start block number %, offset " "%\n" msgstr "" "i-wÄ™zeÅ‚ % - błędny numer bloku poczÄ…tkowego ekstentu rt %, " "offset %\n" #: .././repair/dinode.c:452 #, c-format msgid "" "inode % - bad rt extent last block number %, offset " "%\n" msgstr "" "i-wÄ™zeÅ‚ % - błędny numer bloku koÅ„cowego ekstentu rt %, " "offset %\n" #: .././repair/dinode.c:460 #, c-format msgid "" "inode % - bad rt extent overflows - start %, end %, " "offset %\n" msgstr "" "i-wÄ™zeÅ‚ % - błędne przepeÅ‚nienie ekstentu rt - poczÄ…tek %, " "koniec %, offset %\n" #: .././repair/dinode.c:477 #, c-format msgid "malformed rt inode extent [% %] (fs rtext size = %u)\n" msgstr "" "znieksztaÅ‚cony ekstent i-wÄ™zÅ‚a rt [% %] (rozmiar fs rtext = " "%u)\n" #: .././repair/dinode.c:498 #, c-format msgid "" "data fork in rt ino % claims dup rt extent,off - %, start - " "%, count %\n" msgstr "" "gałąź danych w i-węźle rt % odwoÅ‚uje siÄ™ do powtórzonego ekstentu " "rt, offset %, poczÄ…tek %, liczba %\n" #: .././repair/dinode.c:517 #, c-format msgid "bad state in rt block map %\n" msgstr "błędny stan w mapie bloku rt %\n" #: .././repair/dinode.c:523 #, c-format msgid "" "data fork in rt inode % found metadata block % in rt bmap\n" msgstr "" "gałąź danych w i-węźle rt % - znaleziono blok metadanych % w " "bmapie rt\n" #: .././repair/dinode.c:531 #, c-format msgid "data fork in rt inode % claims used rt block %\n" msgstr "" "gałąź danych w i-węźle rt % odwoÅ‚uje siÄ™ do używanego bloku rt " "%\n" #: .././repair/dinode.c:537 #, c-format msgid "illegal state %d in rt block map %\n" msgstr "niedozwolony stan %d w mapie bloku rt %\n" #: .././repair/dinode.c:600 #, c-format msgid "" "bmap rec out of order, inode % entry %d [o s c] [% % " "%], %d [% % %]\n" msgstr "" "rekord bmap uszkodzony, i-wÄ™zeÅ‚ % wpis %d [o s c] [% " "% %], %d [% % %]\n" #: .././repair/dinode.c:616 #, c-format msgid "" "zero length extent (off = %, fsbno = %) in ino %\n" msgstr "" "ekstent zerowej dÅ‚ugoÅ›ci (off = %, fsbno = %) w i-węźle " "%\n" #: .././repair/dinode.c:647 #, c-format msgid "" "inode % - bad extent starting block number %, offset " "%\n" msgstr "" "i-wÄ™zeÅ‚ % - błędny numer bloku poczÄ…tkowego ekstentu %, " "offset %\n" #: .././repair/dinode.c:655 #, c-format msgid "" "inode % - bad extent last block number %, offset %\n" msgstr "" "i-wÄ™zeÅ‚ % - błędny numer bloku koÅ„cowego ekstentu %, offset " "%\n" #: .././repair/dinode.c:663 #, c-format msgid "" "inode % - bad extent overflows - start %, end %, " "offset %\n" msgstr "" "i-wÄ™zeÅ‚ % - błędne przepeÅ‚nienie ekstentu - poczÄ…tek %, " "koniec %, offset %\n" #: .././repair/dinode.c:675 #, fuzzy, c-format msgid "" "inode % - extent exceeds max offset - start %, count " "%, physical block %\n" msgstr "" "i-wÄ™zeÅ‚ % - offset ekstentu zbyt duży - poczÄ…tek %, liczba " "%, offset %\n" #: .././repair/dinode.c:696 #, c-format msgid "" "Fatal error: inode % - blkmap_set_ext(): %s\n" "\t%s fork, off - %, start - %, cnt %\n" msgstr "" "Błąd krytyczny: i-wÄ™zeÅ‚ % - blkmap_set_ext(): %s\n" "\tgałąź %s, offset %, poczÄ…tek %, liczba %\n" #: .././repair/dinode.c:729 #, c-format msgid "" "%s fork in ino % claims dup extent, off - %, start - " "%, cnt %\n" msgstr "" "gałąź %s w i-węźle % odwoÅ‚uje siÄ™ do powtórzonego ekstentu, offset " "%, poczÄ…tek %, liczba %\n" #: .././repair/dinode.c:748 #, c-format msgid "%s fork in ino % claims free block %\n" msgstr "gałąź %s w i-węźle % odwoÅ‚uje siÄ™ do wolnego bloku %\n" #: .././repair/dinode.c:757 #, c-format msgid "bad state in block map %\n" msgstr "błędny stan w mapie bloku %\n" #: .././repair/dinode.c:762 msgid "rmap claims metadata use!\n" msgstr "" #: .././repair/dinode.c:768 #, c-format msgid "%s fork in inode % claims metadata block %\n" msgstr "" "gałąź %s w i-węźle % odwoÅ‚uje siÄ™ do bloku metadanych %\n" #: .././repair/dinode.c:779 #, c-format msgid "%s fork in %s inode % claims used block %\n" msgstr "" "gałąź %s w i-węźle %s % odwoÅ‚uje siÄ™ do używanego bloku %\n" #: .././repair/dinode.c:785 #, c-format msgid "illegal state %d in block map %\n" msgstr "niedozwolony stan %d w mapie bloku %\n" #: .././repair/dinode.c:793 msgid "couldn't add reverse mapping\n" msgstr "" #: .././repair/dinode.c:805 #, c-format msgid "correcting nextents for inode %\n" msgstr "poprawiono nextents dla i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:897 #, c-format msgid "cannot read inode (%u/%u), disk block %\n" msgstr "nie można odczytać i-wÄ™zÅ‚a (%u/%u), blok dysku %\n" #: .././repair/dinode.c:965 #, c-format msgid "bad level %d in inode % bmap btree root block\n" msgstr "błędny poziom %d w bloku głównym bmap btree i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:971 #, c-format msgid "bad numrecs 0 in inode % bmap btree root block\n" msgstr "błędne numrecs 0 w bloku głównym bmap btree i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:980 #, c-format msgid "" "indicated size of %s btree root (%d bytes) greater than space in inode " "% %s fork\n" msgstr "" "oznaczony rozmiar korzenia b-drzewa %s (%d bajtów) wiÄ™kszy niż miejsce w i-" "węźle % gałęzi %s\n" #: .././repair/dinode.c:1001 #, fuzzy, c-format msgid "bad bmap btree ptr 0x% in ino %\n" msgstr "błędny wskaźnik bmap btree 0x%llx w i-węźle %\n" #: .././repair/dinode.c:1021 #, fuzzy, c-format msgid "" "correcting key in bmbt root (was %, now %) in inode " "% %s fork\n" msgstr "" "poprawiono klucz w korzeniu bmbt (byÅ‚ %llu, jest %) w i-węźle " "% gałęzi %s\n" #: .././repair/dinode.c:1033 #, fuzzy, c-format msgid "" "bad key in bmbt root (is %, would reset to %) in inode " "% %s fork\n" msgstr "" "błędny klucz w korzeniu bmbt (jest %llu, zostaÅ‚by przestawiony na %) " "w i-węźle % gałęzi %s\n" #: .././repair/dinode.c:1049 #, c-format msgid "out of order bmbt root key % in inode % %s fork\n" msgstr "" "niepoprawny klucz korzenia bmbt % w i-węźle % gałęzi %s\n" #: .././repair/dinode.c:1066 #, c-format msgid "" "extent count for ino % %s fork too low (%) for file format\n" msgstr "" "i-wÄ™zeÅ‚ %: liczba ekstentów dla odgałęzienia %s zbyt maÅ‚a " "(%) dla formatu pliku\n" #: .././repair/dinode.c:1077 #, c-format msgid "bad fwd (right) sibling pointer (saw % should be NULLFSBLOCK)\n" msgstr "" "błędny wskaźnik fwd (prawy) (widziano %, powinno być NULLFSBLOCK)\n" #: .././repair/dinode.c:1080 #, c-format msgid "\tin inode % (%s fork) bmap btree block %\n" msgstr "\tw i-węźle % (gałęzi %s) bloku bmap btree %\n" #: .././repair/dinode.c:1162 #, c-format msgid "local inode % data fork is too large (size = %lld, max = %d)\n" msgstr "" "gałąź danych lokalnego i-wÄ™zÅ‚a % zbyt duża (rozmiar = %lld, maksimum " "= %d)\n" #: .././repair/dinode.c:1170 #, c-format msgid "local inode % attr fork too large (size %d, max = %d)\n" msgstr "" "gałąź atrybutów lokalnego i-wÄ™zÅ‚a % zbyt duża (rozmiar %d, maksimum " "= %d)\n" #: .././repair/dinode.c:1177 #, c-format msgid "local inode % attr too small (size = %d, min size = %zd)\n" msgstr "" "gałąź atrybutów lokalnego i-wÄ™zÅ‚a % zbyt maÅ‚a (rozmiar = %d, minimum " "= %zd)\n" #: .././repair/dinode.c:1201 #, c-format msgid "" "mismatch between format (%d) and size (%) in symlink ino %\n" msgstr "" "niezgodność miÄ™dzy formatem (%d) a rozmiarem (%) w i-węźle " "dowiÄ…zania symbolicznego %\n" #: .././repair/dinode.c:1208 #, c-format msgid "" "mismatch between format (%d) and size (%) in symlink inode " "%\n" msgstr "" "niezgodność miÄ™dzy formatem (%d) a rozmiarem (%) w i-węźle " "dowiÄ…zania symbolicznego %\n" #: .././repair/dinode.c:1223 #, c-format msgid "bad number of extents (%d) in symlink % data fork\n" msgstr "" "błędna liczba ekstentów (%d) w gałęzi danych dowiÄ…zania symbolicznego " "%\n" #: .././repair/dinode.c:1235 #, c-format msgid "bad extent #%d offset (%) in symlink % data fork\n" msgstr "" "błędny offset ekstentu %d (%) w gałęzi danych dowiÄ…zania " "symbolicznego %\n" #: .././repair/dinode.c:1241 #, c-format msgid "bad extent #%d count (%) in symlink % data fork\n" msgstr "" "błędna liczba ekstentów #%d (%) w gałęzi danych dowiÄ…zania " "symbolicznego %\n" #: .././repair/dinode.c:1299 #, c-format msgid "cannot read inode %, file block %d, NULL disk block\n" msgstr "" "nie można odczytać i-wÄ™zÅ‚a %, blok pliku %d, zerowy blok dysku\n" #: .././repair/dinode.c:1321 #, c-format msgid "cannot read inode %, file block %d, disk block %\n" msgstr "" "nie można odczytać i-wÄ™zÅ‚a %, blok pliku %d, blok dysku %\n" #: .././repair/dinode.c:1327 #, c-format msgid "" "Bad symlink buffer CRC, block %, inode %.\n" "Correcting CRC, but symlink may be bad.\n" msgstr "" "Błędna suma kontrolna bufora dowiÄ…zania symbolicznego, blok %, i-" "wÄ™zeÅ‚ %.\n" "Poprawianie CRC, ale dowiÄ…zanie symboliczne może być błędne.\n" #: .././repair/dinode.c:1340 #, c-format msgid "bad symlink header ino %, file block %d, disk block %\n" msgstr "" "błędny i-wÄ™zeÅ‚ nagłówka dowiÄ…zania symbolicznego %, blok pliku %d, " "blok dysku %\n" #: .././repair/dinode.c:1383 #, c-format msgid "symlink in inode % too long (%llu chars)\n" msgstr "dowiÄ…zanie symboliczne w i-węźle % zbyt dÅ‚ugie (%llu znaków)\n" #: .././repair/dinode.c:1415 #, c-format msgid "found illegal null character in symlink inode %\n" msgstr "" "znaleziono niedozwolony znak null w i-węźle dowiÄ…zania symbolicznego " "%\n" #: .././repair/dinode.c:1440 #, c-format msgid "inode % has bad inode type (IFMNT)\n" msgstr "i-wÄ™zeÅ‚ % ma błędny typ i-wÄ™zÅ‚a (IFMNT)\n" #: .././repair/dinode.c:1451 #, c-format msgid "size of character device inode % != 0 (% bytes)\n" msgstr "" "rozmiar i-wÄ™zÅ‚a urzÄ…dzenia znakowego % != 0 (% bajtów)\n" #: .././repair/dinode.c:1456 #, c-format msgid "size of block device inode % != 0 (% bytes)\n" msgstr "" "rozmiar i-wÄ™zÅ‚a urzÄ…dzenia blokowego % != 0 (% bajtów)\n" #: .././repair/dinode.c:1461 #, c-format msgid "size of socket inode % != 0 (% bytes)\n" msgstr "rozmiar i-wÄ™zÅ‚a gniazda % != 0 (% bajtów)\n" #: .././repair/dinode.c:1466 #, c-format msgid "size of fifo inode % != 0 (% bytes)\n" msgstr "rozmiar i-wÄ™zÅ‚a potoku % != 0 (% bajtów)\n" #: .././repair/dinode.c:1470 #, c-format msgid "Internal error - process_misc_ino_types, illegal type %d\n" msgstr "Błąd wewnÄ™trzny - process_misc_ino_types, niedozwolony typ %d\n" #: .././repair/dinode.c:1497 #, c-format msgid "size of character device inode % != 0 (% blocks)\n" msgstr "" "rozmiar i-wÄ™zÅ‚a urzÄ…dzenia znakowego % != 0 (% bloków)\n" #: .././repair/dinode.c:1502 #, c-format msgid "size of block device inode % != 0 (% blocks)\n" msgstr "" "rozmiar i-wÄ™zÅ‚a urzÄ…dzenia blokowego % != 0 (% bloków)\n" #: .././repair/dinode.c:1507 #, c-format msgid "size of socket inode % != 0 (% blocks)\n" msgstr "rozmiar i-wÄ™zÅ‚a gniazda % != 0 (% bloków)\n" #: .././repair/dinode.c:1512 #, c-format msgid "size of fifo inode % != 0 (% blocks)\n" msgstr "rozmiar i-wÄ™zÅ‚a potoku % != 0 (% bloków)\n" #: .././repair/dinode.c:1590 #, c-format msgid "root inode % has bad type 0x%x\n" msgstr "i-wÄ™zeÅ‚ główny % ma błędny typ 0x%x\n" #: .././repair/dinode.c:1594 msgid "resetting to directory\n" msgstr "przestawiono na katalog\n" #: .././repair/dinode.c:1598 msgid "would reset to directory\n" msgstr "zostaÅ‚by przestawiony na katalog\n" #: .././repair/dinode.c:1604 #, c-format msgid "user quota inode % has bad type 0x%x\n" msgstr "i-wÄ™zeÅ‚ limitu użytkownika % ma błędny typ 0x%x\n" #: .././repair/dinode.c:1613 #, c-format msgid "group quota inode % has bad type 0x%x\n" msgstr "i-wÄ™zeÅ‚ limitu grupy % ma błędny typ 0x%x\n" #: .././repair/dinode.c:1622 #, c-format msgid "project quota inode % has bad type 0x%x\n" msgstr "i-wÄ™zeÅ‚ limitu projektu % ma błędny typ 0x%x\n" #: .././repair/dinode.c:1632 #, c-format msgid "realtime summary inode % has bad type 0x%x, " msgstr "i-wÄ™zeÅ‚ opisu realtime % ma błędny typ 0x%x, " #: .././repair/dinode.c:1635 .././repair/dinode.c:1656 msgid "resetting to regular file\n" msgstr "przestawiono na zwykÅ‚y plik\n" #: .././repair/dinode.c:1639 .././repair/dinode.c:1660 msgid "would reset to regular file\n" msgstr "zostaÅ‚by przestawiony na zwykÅ‚y plik\n" #: .././repair/dinode.c:1644 #, c-format msgid "bad # of extents (%u) for realtime summary inode %\n" msgstr "błędna liczba ekstentów (%u) dla i-wÄ™złą opisu realtime %\n" #: .././repair/dinode.c:1653 #, c-format msgid "realtime bitmap inode % has bad type 0x%x, " msgstr "i-wÄ™zeÅ‚ bitmapy realtime % ma błędny typ 0x%x, " #: .././repair/dinode.c:1665 #, c-format msgid "bad # of extents (%u) for realtime bitmap inode %\n" msgstr "błędna liczba ekstentów (%u) dla i-wÄ™złą bitmapy realtime %\n" #: .././repair/dinode.c:1700 #, c-format msgid "" "mismatch between format (%d) and size (%) in directory ino " "%\n" msgstr "" "niezgodność miÄ™dzy formatem (%d) a rozmiarem (%) w i-węźle katalogu " "%\n" #: .././repair/dinode.c:1706 #, c-format msgid "directory inode % has bad size %\n" msgstr "i-wÄ™zeÅ‚ katalogu % ma błędny rozmiar %\n" #: .././repair/dinode.c:1714 #, c-format msgid "bad data fork in symlink %\n" msgstr "błędna gałąź danych w dowiÄ…zaniu symbolicznym %\n" #: .././repair/dinode.c:1735 #, c-format msgid "found inode % claiming to be a real-time file\n" msgstr "znaleziono i-wÄ™zeÅ‚ % twierdzÄ…cy, że należy do pliku realtime\n" #: .././repair/dinode.c:1744 #, c-format msgid "" "realtime bitmap inode % has bad size % (should be " "%)\n" msgstr "" "i-wÄ™zeÅ‚ bitmapy realtime % ma błędny rozmiar % (powinien być " "%)\n" #: .././repair/dinode.c:1755 #, c-format msgid "" "realtime summary inode % has bad size % (should be %d)\n" msgstr "" "i-wÄ™zeÅ‚ opisu realtime % ma błędny rozmiar % (powinien być " "%d)\n" #: .././repair/dinode.c:1783 #, c-format msgid "bad attr fork offset %d in dev inode %, should be %d\n" msgstr "" "błędny offset gałęzi atrybutów %d w i-węźle urzÄ…dzenia %, powinien " "być %d\n" #: .././repair/dinode.c:1795 #, c-format msgid "bad attr fork offset %d in inode %, max=%d\n" msgstr "błędny offset gałęzi atrybutów %d w i-węźle %, maksimum=%d\n" #: .././repair/dinode.c:1802 #, c-format msgid "unexpected inode format %d\n" msgstr "nieoczekiwany format i-wÄ™zÅ‚a %d\n" #: .././repair/dinode.c:1823 #, c-format msgid "correcting nblocks for inode %, was %llu - counted %\n" msgstr "" "poprawiono nblocks dla i-wÄ™zÅ‚a % - byÅ‚o %llu, naliczono %\n" #: .././repair/dinode.c:1830 #, c-format msgid "bad nblocks %llu for inode %, would reset to %\n" msgstr "" "błędne nblocks %llu dla i-wÄ™zÅ‚a %, zostaÅ‚oby przestawione na " "%\n" #: .././repair/dinode.c:1838 #, c-format msgid "too many data fork extents (%) in inode %\n" msgstr "zbyt dużo ekstentów gałęzi danych (%) w i-węźle %\n" #: .././repair/dinode.c:1845 #, c-format msgid "correcting nextents for inode %, was %d - counted %\n" msgstr "" "poprawiono nextents dla i-wÄ™zÅ‚a % - byÅ‚o %d, naliczono %\n" #: .././repair/dinode.c:1853 #, c-format msgid "bad nextents %d for inode %, would reset to %\n" msgstr "" "błędne nextents %d dla i-wÄ™zÅ‚a %, zostaÅ‚oby przestawione na " "%\n" #: .././repair/dinode.c:1861 #, c-format msgid "too many attr fork extents (%) in inode %\n" msgstr "zbyt dużo ekstentów gałęzi atrybutów (%) w i-węźle %\n" #: .././repair/dinode.c:1868 #, c-format msgid "correcting anextents for inode %, was %d - counted %\n" msgstr "" "poprawiono anextents dla i-wÄ™zÅ‚a % - byÅ‚o %d, naliczono %\n" #: .././repair/dinode.c:1875 #, c-format msgid "bad anextents %d for inode %, would reset to %\n" msgstr "" "błędne anextents %d dla i-wÄ™zÅ‚a %, zostaÅ‚oby przestawione na " "%\n" #: .././repair/dinode.c:1887 #, c-format msgid "nblocks (%) smaller than nextents for inode %\n" msgstr "nblocks (%) mniejsze niż nextents dla i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:1952 .././repair/dinode.c:1990 #, c-format msgid "unknown format %d, ino % (mode = %d)\n" msgstr "nieznany format %d, i-wÄ™zeÅ‚ % (tryb = %d)\n" #: .././repair/dinode.c:1957 #, c-format msgid "bad data fork in inode %\n" msgstr "błędna gałąź danych w i-węźle %\n" #: .././repair/dinode.c:2028 #, c-format msgid "bad attribute format %d in inode %, " msgstr "błędny format atrybutów %d w i-węźle %, " #: .././repair/dinode.c:2031 msgid "resetting value\n" msgstr "przestawiono wartość\n" #: .././repair/dinode.c:2035 msgid "would reset value\n" msgstr "wartość zostaÅ‚aby przestawiona\n" #: .././repair/dinode.c:2080 #, c-format msgid "bad attribute fork in inode %" msgstr "błędna gałąź atrybutów w i-węźle %" #: .././repair/dinode.c:2084 msgid ", clearing attr fork\n" msgstr ", wyczyszczono gałąź atrybutów\n" #: .././repair/dinode.c:2093 msgid ", would clear attr fork\n" msgstr ", gałąź atrybutów zostaÅ‚aby wyczyszczona\n" #: .././repair/dinode.c:2121 #, c-format msgid "illegal attribute fmt %d, ino %\n" msgstr "niedozwolony format atrybutów %d, i-wÄ™zeÅ‚ %\n" #: .././repair/dinode.c:2141 #, c-format msgid "problem with attribute contents in inode %\n" msgstr "problem z zawartoÅ›ciÄ… atrybutu w i-węźle %\n" #: .././repair/dinode.c:2149 msgid "would clear attr fork\n" msgstr "gałąź atrybutów zostaÅ‚aby wyczyszczona\n" #: .././repair/dinode.c:2182 #, c-format msgid "" "clearing obsolete nlink field in version 2 inode %, was %d, now 0\n" msgstr "" "wyczyszczono przestarzaÅ‚e pole nlink w i-węźle % w wersji 2 - byÅ‚o " "%d, jest 0\n" #: .././repair/dinode.c:2188 #, c-format msgid "" "would clear obsolete nlink field in version 2 inode %, currently %d\n" msgstr "" "przestarzaÅ‚e pole nlink w i-węźle % w wersji 2 zostaÅ‚oby " "wyczyszczone, aktualnie %d\n" #: .././repair/dinode.c:2267 #, fuzzy, c-format msgid "bad CRC for inode %%c" msgstr "błędna gałąź danych w i-węźle %\n" #: .././repair/dinode.c:2271 msgid " will rewrite\n" msgstr "" #: .././repair/dinode.c:2274 #, fuzzy msgid " would rewrite\n" msgstr "tablica zostaÅ‚aby naprawiona\n" #: .././repair/dinode.c:2281 #, c-format msgid "bad magic number 0x%x on inode %%c" msgstr "błędna liczba magiczna 0x%x w i-węźle %%c" #: .././repair/dinode.c:2286 msgid " resetting magic number\n" msgstr " przestawiono liczbÄ™ magicznÄ…\n" #: .././repair/dinode.c:2290 msgid " would reset magic number\n" msgstr " liczba magiczna zostaÅ‚aby przestawiona\n" #: .././repair/dinode.c:2297 #, c-format msgid "bad version number 0x%x on inode %%c" msgstr "błędny numer wersji 0x%x w i-węźle %%c" #: .././repair/dinode.c:2302 msgid " resetting version number\n" msgstr " przestawiono numer wersji\n" #: .././repair/dinode.c:2307 msgid " would reset version number\n" msgstr " numer wersji zostaÅ‚by przestawiony\n" #: .././repair/dinode.c:2320 #, c-format msgid "inode identifier %llu mismatch on inode %\n" msgstr "niezgodność identyfikatora i-wÄ™zÅ‚a %llu dla i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:2330 #, c-format msgid "UUID mismatch on inode %\n" msgstr "niezgodność UUID-a dla i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:2343 #, c-format msgid "bad (negative) size % on inode %\n" msgstr "błędny (ujemny) rozmiar % w i-węźle %\n" #: .././repair/dinode.c:2376 #, c-format msgid "imap claims a free inode % is in use, " msgstr "imap odwoÅ‚uje siÄ™ do wolnego bloku %, który jest w użyciu, " #: .././repair/dinode.c:2378 msgid "correcting imap and clearing inode\n" msgstr "poprawiono imap i wyczyszczono i-wÄ™zeÅ‚\n" #: .././repair/dinode.c:2382 msgid "would correct imap and clear inode\n" msgstr "poprawiono by imap i wyczyszczono by i-wÄ™zeÅ‚\n" #: .././repair/dinode.c:2399 #, c-format msgid "bad inode format in inode %\n" msgstr "błędny format i-wÄ™zÅ‚a w i-węźle %\n" #: .././repair/dinode.c:2415 #, c-format msgid "Bad flags set in inode %\n" msgstr "Błędne flagi ustawione w i-węźle %\n" #: .././repair/dinode.c:2426 #, c-format msgid "inode % has RT flag set but there is no RT device\n" msgstr "i-wÄ™zeÅ‚ % ma ustawionÄ… flagÄ™ RT, ale nie ma urzÄ…dzenia RT\n" #: .././repair/dinode.c:2438 #, c-format msgid "inode % not rt bitmap\n" msgstr "i-wÄ™zeÅ‚ % nie jest bitmapÄ… rt\n" #: .././repair/dinode.c:2452 #, c-format msgid "directory flags set on non-directory inode %\n" msgstr "" "flagi katalogu ustawione dla nie bÄ™dÄ…cego katalogiem i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:2466 #, c-format msgid "file flags set on non-file inode %\n" msgstr "flagi pliku ustawione dla nie bÄ™dÄ…cego plikiem i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:2475 #, fuzzy msgid "fixing bad flags.\n" msgstr ", poprawiono błędne flagi.\n" #: .././repair/dinode.c:2479 #, fuzzy msgid "would fix bad flags.\n" msgstr ", poprawionoby błędne flagi.\n" #: .././repair/dinode.c:2494 #, fuzzy, c-format msgid "Bad flags2 set in inode %\n" msgstr "Błędne flagi ustawione w i-węźle %\n" #: .././repair/dinode.c:2504 #, c-format msgid "" "inode % is marked reflinked but file system does not support " "reflink\n" msgstr "" #: .././repair/dinode.c:2515 #, fuzzy, c-format msgid "reflink flag set on non-file inode %\n" msgstr "flagi pliku ustawione dla nie bÄ™dÄ…cego plikiem i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:2526 #, fuzzy, c-format msgid "Cannot have a reflinked realtime inode %\n" msgstr "wyczyszczono i-wÄ™zeÅ‚ bitmapy realtime %\n" #: .././repair/dinode.c:2536 #, fuzzy, c-format msgid "" "inode % has CoW extent size hint but file system does not support " "reflink\n" msgstr "i-wÄ™zeÅ‚ % ma ustawionÄ… flagÄ™ RT, ale nie ma urzÄ…dzenia RT\n" #: .././repair/dinode.c:2547 #, fuzzy, c-format msgid "CoW extent size flag set on non-file, non-directory inode %\n" msgstr "" "flagi katalogu ustawione dla nie bÄ™dÄ…cego katalogiem i-wÄ™zÅ‚a %\n" #: .././repair/dinode.c:2558 #, fuzzy, c-format msgid "Cannot have CoW extent size hint on a realtime inode %\n" msgstr "błędna liczba ekstentów (%u) dla i-wÄ™złą bitmapy realtime %\n" #: .././repair/dinode.c:2566 #, fuzzy msgid "fixing bad flags2.\n" msgstr ", poprawiono błędne flagi.\n" #: .././repair/dinode.c:2570 #, fuzzy msgid "would fix bad flags2.\n" msgstr ", poprawionoby błędne flagi.\n" #: .././repair/dinode.c:2621 #, c-format msgid "bad inode type %#o inode %\n" msgstr "błędny typ i-wÄ™zÅ‚a %#o w i-węźle %\n" #: .././repair/dinode.c:2645 #, c-format msgid "bad non-zero extent size %u for non-realtime/extsize inode %, " msgstr "" "błędny niezerowy rozmiar ekstentu %u dla extsize i-wÄ™zÅ‚a nie-realtime " "%, " #: .././repair/dinode.c:2648 .././repair/dinode.c:2671 msgid "resetting to zero\n" msgstr "przestawiono na zero\n" #: .././repair/dinode.c:2652 .././repair/dinode.c:2675 msgid "would reset to zero\n" msgstr "zostaÅ‚by przestawiony na zero\n" #: .././repair/dinode.c:2668 #, fuzzy, c-format msgid "" "Cannot have non-zero CoW extent size %u on non-cowextsize inode %, " msgstr "" "błędny niezerowy rozmiar ekstentu %u dla extsize i-wÄ™zÅ‚a nie-realtime " "%, " #: .././repair/dinode.c:2734 #, c-format msgid "problem with directory contents in inode %\n" msgstr "problem z zawartoÅ›ciÄ… katalogu w i-węźle %\n" #: .././repair/dinode.c:2742 #, c-format msgid "problem with symbolic link in inode %\n" msgstr "problem z dowiÄ…zaniem symbolicznym w i-węźle %\n" #: .././repair/dinode.c:2837 #, c-format msgid "processing inode %d/%d\n" msgstr "analiza i-wÄ™zÅ‚a %d/%d\n" #: .././repair/dir2.c:50 #, c-format msgid "malloc failed (%zu bytes) dir2_add_badlist:ino %\n" msgstr "" "malloc nie powiodÅ‚o siÄ™ (%zu bajtów) w dir2_add_badlist:ino %\n" #: .././repair/dir2.c:93 msgid "couldn't malloc dir2 shortform copy\n" msgstr "nie udaÅ‚o siÄ™ przydzielić krótkiej kopii dir2\n" #: .././repair/dir2.c:229 msgid "current" msgstr "bieżącego i-wÄ™zÅ‚a" #: .././repair/dir2.c:232 .././repair/dir2.c:693 msgid "invalid" msgstr "nieprawidÅ‚owego i-wÄ™zÅ‚a" #: .././repair/dir2.c:235 .././repair/dir2.c:695 msgid "realtime bitmap" msgstr "i-wÄ™zÅ‚a bitmapy realtime" #: .././repair/dir2.c:238 .././repair/dir2.c:697 msgid "realtime summary" msgstr "i-wÄ™zÅ‚a opisu realtime" #: .././repair/dir2.c:241 .././repair/dir2.c:699 msgid "user quota" msgstr "i-wÄ™zÅ‚a limitów użytkownika" #: .././repair/dir2.c:244 .././repair/dir2.c:701 msgid "group quota" msgstr "i-wÄ™zÅ‚a limitów grupy" #: .././repair/dir2.c:247 .././repair/dir2.c:703 msgid "project quota" msgstr "i-wÄ™zÅ‚a limitów projektu" #: .././repair/dir2.c:265 .././repair/dir2.c:733 msgid "free" msgstr "free" #: .././repair/dir2.c:282 .././repair/dir2.c:713 msgid "non-existent" msgstr "nie istniejÄ…cego i-wÄ™zÅ‚a" #: .././repair/dir2.c:287 #, c-format msgid "" "entry \"%*.*s\" in shortform directory % references %s inode " "%\n" msgstr "" "wpis \"%*.*s\" w krótkim katalogu % odwoÅ‚uje siÄ™ do %s %\n" #: .././repair/dir2.c:293 msgid "is zero length" msgstr "" #: .././repair/dir2.c:298 msgid "extends past end of dir" msgstr "" #: .././repair/dir2.c:304 #, fuzzy, c-format msgid "entry #%d %s in shortform dir %" msgstr "wpis zerowej dÅ‚ugoÅ›ci w krótkim katalogu %" #: .././repair/dir2.c:307 #, c-format msgid ", junking %d entries\n" msgstr ", wyrzucono %d wpisów\n" #: .././repair/dir2.c:310 #, c-format msgid ", would junk %d entries\n" msgstr ", %d wpisów zostaÅ‚oby wyrzucone\n" #: .././repair/dir2.c:330 #, c-format msgid "entry contains illegal character in shortform dir %\n" msgstr "wpis zawiera niedozwolony znak w krótkim katalogu %\n" #: .././repair/dir2.c:337 #, c-format msgid "entry contains offset out of order in shortform dir %\n" msgstr "wpis zawiera uszkodzony offset w krótkim katalogu %\n" #: .././repair/dir2.c:394 #, c-format msgid "junking entry \"%s\" in directory inode %\n" msgstr "wyrzucono wpis \"%s\" w i-węźle katalogu %\n" #: .././repair/dir2.c:398 #, c-format msgid "would have junked entry \"%s\" in directory inode %\n" msgstr "wpis \"%s\" w i-węźle katalogu % zostaÅ‚by wyrzucony\n" #: .././repair/dir2.c:423 #, c-format msgid "would have corrected entry count in directory % from %d to %d\n" msgstr "liczba wpisów w katalogu % zostaÅ‚aby poprawiona z %d na %d\n" #: .././repair/dir2.c:427 #, c-format msgid "corrected entry count in directory %, was %d, now %d\n" msgstr "poprawiono liczbÄ™ wpisów w katalogu % - byÅ‚o %d, jest %d\n" #: .././repair/dir2.c:438 #, c-format msgid "would have corrected i8 count in directory % from %d to %d\n" msgstr "liczba i8 zostaÅ‚aby poprawiona w katalogu % z %d na %d\n" #: .././repair/dir2.c:442 #, c-format msgid "corrected i8 count in directory %, was %d, now %d\n" msgstr "poprawiono liczbÄ™ i8 w katalogu % - byÅ‚o %d, jest %d\n" #: .././repair/dir2.c:456 #, c-format msgid "" "would have corrected directory % size from % to %\n" msgstr "" "rozmiar katalogu % zostaÅ‚by poprawiony z % na %\n" #: .././repair/dir2.c:461 #, c-format msgid "corrected directory % size, was %, now %\n" msgstr "" "poprawiono rozmiar katalogu % - byÅ‚o %, jest %\n" #: .././repair/dir2.c:473 #, c-format msgid "directory % offsets too high\n" msgstr "offsety zbyt duże w katalogu %\n" #: .././repair/dir2.c:479 #, c-format msgid "would have corrected entry offsets in directory %\n" msgstr "offsety wpisów w katalogu % zostaÅ‚yby poprawione\n" #: .././repair/dir2.c:483 #, c-format msgid "corrected entry offsets in directory %\n" msgstr "poprawiono offsety wpisów w katalogu %\n" #: .././repair/dir2.c:502 #, c-format msgid "bogus .. inode number (%) in directory inode %, " msgstr "błędny numer i-wÄ™zÅ‚a .. (%) w i-węźle katalogu %, " #: .././repair/dir2.c:506 .././repair/dir2.c:541 msgid "clearing inode number\n" msgstr "wyczyszczono numer i-wÄ™zÅ‚a\n" #: .././repair/dir2.c:512 .././repair/dir2.c:547 msgid "would clear inode number\n" msgstr "numer i-wÄ™zÅ‚a zostaÅ‚by wyczyszczony\n" #: .././repair/dir2.c:520 #, c-format msgid "" "corrected root directory % .. entry, was %, now %\n" msgstr "" "poprawiono wpis .. głównego katalogu % - byÅ‚o %, jest " "%\n" #: .././repair/dir2.c:528 #, c-format msgid "" "would have corrected root directory % .. entry from % to " "%\n" msgstr "" "wpis .. głównego katalogu % zostaÅ‚by poprawiony z % na " "%\n" #: .././repair/dir2.c:538 #, c-format msgid "bad .. entry in directory inode %, points to self, " msgstr "błędny wpis .. w i-węźle katalogu %, wskazuje na siebie, " #: .././repair/dir2.c:651 #, c-format msgid "corrupt block %u in directory inode %\n" msgstr "uszkodzony blok %u w i-węźle katalogu %\n" #: .././repair/dir2.c:654 msgid "\twill junk block\n" msgstr "\tblok zostanie wyrzucony\n" #: .././repair/dir2.c:656 msgid "\twould junk block\n" msgstr "\tblok zostaÅ‚by wyrzucony\n" #: .././repair/dir2.c:742 #, c-format msgid "" "entry \"%*.*s\" at block %d offset % in directory inode % " "references %s inode %\n" msgstr "" "wpis \"%*.*s\" w bloku %d offsecie % w i-węźle katalogu % " "odwoÅ‚uje siÄ™ do %s %\n" #: .././repair/dir2.c:765 #, c-format msgid "" "entry at block %u offset % in directory inode %has 0 " "namelength\n" msgstr "" "wpis w bloku %u offsecie % w i-węźle katalogu % ma zerowÄ… " "dÅ‚ugość nazwy\n" #: .././repair/dir2.c:778 #, c-format msgid "\tclearing inode number in entry at offset %...\n" msgstr "\twyczyszczono numer i-wÄ™zÅ‚a we wpisie o offsecie %...\n" #: .././repair/dir2.c:784 #, c-format msgid "\twould clear inode number in entry at offset %...\n" msgstr "" "\tnumer i-wÄ™zÅ‚a we wpisie o offsecie % zostaÅ‚by wyczyszczony...\n" #: .././repair/dir2.c:797 #, c-format msgid "" "entry at block %u offset % in directory inode % has illegal " "name \"%*.*s\": " msgstr "" "wpis w bloku %u offsecie % w i-węźle katalogu % ma " "niedozwolonÄ… nazwÄ™ \"%*.*s\": " #: .././repair/dir2.c:828 #, c-format msgid "bad .. entry in directory inode %, points to self: " msgstr "błędny wpis .. w i-węźle katalogu %, wskazuje na siebie: " #: .././repair/dir2.c:839 #, c-format msgid "bad .. entry in root directory inode %, was %: " msgstr "błędny wpis w i-węźle głównego katalogu %, byÅ‚o %: " #: .././repair/dir2.c:842 .././repair/dir2.c:875 .././repair/phase2.c:217 #: .././repair/phase2.c:226 .././repair/phase2.c:235 msgid "correcting\n" msgstr "poprawiono\n" #: .././repair/dir2.c:846 .././repair/dir2.c:879 .././repair/phase2.c:219 #: .././repair/phase2.c:228 .././repair/phase2.c:237 msgid "would correct\n" msgstr "zostaÅ‚by poprawiony\n" #: .././repair/dir2.c:859 #, c-format msgid "multiple .. entries in directory inode %: " msgstr "wiele wpisów .. w i-węźle katalogu %: " #: .././repair/dir2.c:872 #, c-format msgid "bad . entry in directory inode %, was %: " msgstr "błędny wpis . w i-węźle katalogu %, byÅ‚o %: " #: .././repair/dir2.c:884 #, c-format msgid "multiple . entries in directory inode %: " msgstr "wiele wpisów . w i-węźle katalogu %: " #: .././repair/dir2.c:894 #, c-format msgid "entry \"%*.*s\" in directory inode % points to self: " msgstr "wpis \"%*.*s\" w i-węźle katalogu % wskazuje na siebie: " #: .././repair/dir2.c:905 msgid "clearing entry\n" msgstr "wyczyszczono wpis\n" #: .././repair/dir2.c:907 msgid "would clear entry\n" msgstr "wpis zostaÅ‚by wyczyszczony\n" #: .././repair/dir2.c:920 #, c-format msgid "bad bestfree table in block %u in directory inode %: " msgstr "błędna tablica bestfree w bloku %u w i-węźle katalogu %: " #: .././repair/dir2.c:923 msgid "repairing table\n" msgstr "naprawiono tablicÄ™\n" #: .././repair/dir2.c:928 msgid "would repair table\n" msgstr "tablica zostaÅ‚aby naprawiona\n" #: .././repair/dir2.c:968 #, c-format msgid "block %u for directory inode % is missing\n" msgstr "brak bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:977 #, c-format msgid "can't read block %u for directory inode %\n" msgstr "nie można odczytać bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:988 #, c-format msgid "" "bad directory block magic # %#x in block %u for directory inode %\n" msgstr "" "błędna liczba magiczna bloku katalogu %#x w bloku %u dla i-wÄ™zÅ‚a katalogu " "%\n" #: .././repair/dir2.c:1040 #, c-format msgid "bad entry count in block %u of directory inode %\n" msgstr "błędna liczba wpisów w bloku %u i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:1048 #, c-format msgid "bad hash ordering in block %u of directory inode %\n" msgstr "błędna kolejność hasza w bloku %u i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:1056 #, c-format msgid "bad stale count in block %u of directory inode %\n" msgstr "błędna liczba stale %u i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:1105 #, c-format msgid "can't map block %u for directory inode %\n" msgstr "nie można odwzorować bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:1115 #, c-format msgid "can't read file block %u for directory inode %\n" msgstr "nie można odczytać bloku pliku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:1127 #, c-format msgid "bad directory leaf magic # %#x for directory inode % block %u\n" msgstr "" "błędna liczba magiczna liÅ›cia katalogu %#x dla i-wÄ™zÅ‚a katalogu % " "bloku %u\n" #: .././repair/dir2.c:1155 #, c-format msgid "bad sibling back pointer for block %u in directory inode %\n" msgstr "błędny wskaźnik wstecz dla bloku %u w i-węźle katalogu %\n" #: .././repair/dir2.c:1186 #, c-format msgid "bad hash path in directory %\n" msgstr "błędna Å›cieżka hasza w katalogu %\n" #: .././repair/dir2.c:1296 #, c-format msgid "block % for directory inode % is missing\n" msgstr "brak bloku % dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:1305 #, c-format msgid "can't read block % for directory inode %\n" msgstr "nie można odczytać bloku % dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/dir2.c:1313 #, c-format msgid "" "bad directory block magic # %#x in block % for directory inode " "%\n" msgstr "" "błędna liczba magiczna bloku katalogu %#x w bloku % dla i-wÄ™zÅ‚a " "katalogu %\n" #: .././repair/dir2.c:1394 #, c-format msgid "bad size/format for directory %\n" msgstr "błędny rozmiar/format dla katalogu %\n" #: .././repair/dir2.c:1401 #, c-format msgid "no . entry for directory %\n" msgstr "brak wpisu . dla katalogu %\n" #: .././repair/dir2.c:1411 #, c-format msgid "no .. entry for directory %\n" msgstr "brak wpisu .. dla katalogu %\n" #: .././repair/dir2.c:1413 #, c-format msgid "no .. entry for root directory %\n" msgstr "brak wpisu .. dla katalogu głównego %\n" #: .././repair/incore.c:230 #, c-format msgid "couldn't allocate realtime block map, size = %\n" msgstr "nie udaÅ‚o siÄ™ przydzielić mapy bloków realtime, size = %\n" #: .././repair/incore.c:295 msgid "couldn't allocate block map btree roots\n" msgstr "nie udaÅ‚o siÄ™ przydzielić korzeni b-drzewa mapy bloków\n" #: .././repair/incore.c:299 msgid "couldn't allocate block map locks\n" msgstr "nie udaÅ‚o siÄ™ przydzielić blokad mapy bloków\n" #: .././repair/incore_ext.c:135 .././repair/incore_ext.c:562 msgid "couldn't allocate new extent descriptor.\n" msgstr "nie udaÅ‚o siÄ™ przydzielić nowego deskryptora ekstentu.\n" #: .././repair/incore_ext.c:232 msgid "duplicate bno extent range\n" msgstr "powtórzony przedziaÅ‚ ekstentów bno\n" #: .././repair/incore_ext.c:369 msgid ": duplicate bno extent range\n" msgstr ": powtórzony przedziaÅ‚ ekstentów bno\n" #: .././repair/incore_ext.c:644 .././repair/incore_ext.c:699 msgid "duplicate extent range\n" msgstr "powtórzony przedziaÅ‚ ekstentów\n" #: .././repair/incore_ext.c:752 .././repair/incore_ext.c:756 msgid "couldn't malloc dup extent tree descriptor table\n" msgstr "" "nie udaÅ‚o siÄ™ przydzielić tablicy deskryptorów drzewa powtórzonych " "ekstentów\n" #: .././repair/incore_ext.c:761 msgid "couldn't malloc free by-bno extent tree descriptor table\n" msgstr "" "nie udaÅ‚o siÄ™ przydzielić tablicy deskryptorów drzewa wolnych ekstentów wg " "bno\n" #: .././repair/incore_ext.c:766 msgid "couldn't malloc free by-bcnt extent tree descriptor table\n" msgstr "" "nie udaÅ‚o siÄ™ przydzielić tablicy deskryptorów drzewa wolnych ekstentów wg " "bcnt\n" #: .././repair/incore_ext.c:772 msgid "couldn't malloc bno extent tree descriptor\n" msgstr "nie udaÅ‚o siÄ™ przydzielić deskryptora drzewa ekstentów wg bno\n" #: .././repair/incore_ext.c:776 msgid "couldn't malloc bcnt extent tree descriptor\n" msgstr "nie udaÅ‚o siÄ™ przydzielić deskryptora drzewa ekstentów wg bcnt\n" #: .././repair/incore_ext.c:787 msgid "couldn't malloc dup rt extent tree descriptor\n" msgstr "" "nie udaÅ‚o siÄ™ przydzielić deskryptora drzewa powtórzonych ekstentów rt\n" #: .././repair/incore_ino.c:47 msgid "could not allocate nlink array\n" msgstr "Nie udaÅ‚o siÄ™ przydzielić tablicy nlink\n" #: .././repair/incore_ino.c:225 msgid "could not allocate ftypes array\n" msgstr "nie udaÅ‚o siÄ™ przydzielić tablicy ftypes\n" #: .././repair/incore_ino.c:251 msgid "inode map malloc failed\n" msgstr "przydzielenie mapy i-wÄ™złów nie powiodÅ‚o siÄ™\n" #: .././repair/incore_ino.c:367 msgid "add_aginode_uncertain - duplicate inode range\n" msgstr "add_aginode_uncertain - powtórzony przedziaÅ‚ i-wÄ™złów\n" #: .././repair/incore_ino.c:462 msgid "add_inode - duplicate inode range\n" msgstr "add_inode - powtórzony przedziaÅ‚ i-wÄ™złów\n" #: .././repair/incore_ino.c:556 #, c-format msgid "good inode list is --\n" msgstr "lista dobrych i-wÄ™złów to:\n" #: .././repair/incore_ino.c:559 #, c-format msgid "uncertain inode list is --\n" msgstr "lista niepewnych i-wÄ™złów to:\n" #: .././repair/incore_ino.c:564 #, c-format msgid "agno %d -- no inodes\n" msgstr "agno %d - brak i-wÄ™złów\n" #: .././repair/incore_ino.c:568 #, c-format msgid "agno %d\n" msgstr "agno %d\n" #: .././repair/incore_ino.c:572 #, c-format msgid "\tptr = %lx, start = 0x%x, free = 0x%llx, confirmed = 0x%llx\n" msgstr "\tptr = %lx, start = 0x%x, wolne = 0x%llx, potwierdzone = 0x%llx\n" #: .././repair/incore_ino.c:623 msgid "couldn't malloc parent list table\n" msgstr "nie udaÅ‚o siÄ™ przydzielić tablicy listy rodziców\n" #: .././repair/incore_ino.c:634 .././repair/incore_ino.c:680 msgid "couldn't memalign pentries table\n" msgstr "nie udaÅ‚o siÄ™ memalign na tablicy pentries\n" #: .././repair/incore_ino.c:738 msgid "could not malloc inode extra data\n" msgstr "nie udaÅ‚o siÄ™ przydzielić dodatkowych danych i-wÄ™zÅ‚a\n" #: .././repair/incore_ino.c:804 msgid "couldn't malloc inode tree descriptor table\n" msgstr "nie udaÅ‚o siÄ™ przydzielić tablicy deskryptorów drzewa i-wÄ™złów\n" #: .././repair/incore_ino.c:808 msgid "couldn't malloc uncertain ino tree descriptor table\n" msgstr "" "nie udaÅ‚o siÄ™ przydzielić tablicy deskryptorów drzewa i-wÄ™złów niepewnych\n" #: .././repair/incore_ino.c:813 msgid "couldn't malloc inode tree descriptor\n" msgstr "nie udaÅ‚o siÄ™ przydzielić deskryptora drzewa i-wÄ™złów\n" #: .././repair/incore_ino.c:817 msgid "couldn't malloc uncertain ino tree descriptor\n" msgstr "nie udaÅ‚o siÄ™ przydzielić deskryptora drzewa i-wÄ™złów niepewnych\n" #: .././repair/incore_ino.c:825 msgid "couldn't malloc uncertain inode cache area\n" msgstr "" "nie udaÅ‚o siÄ™ przydzielić obszaru pamiÄ™ci podrÄ™cznej i-wÄ™złów niepewnych\n" #: .././repair/init.c:46 #, c-format msgid "getrlimit(RLIMIT_FSIZE) failed!\n" msgstr "getrlimit(RLIMIT_FSIZE) nie powiodÅ‚o siÄ™!\n" #: .././repair/init.c:54 #, c-format msgid "setrlimit failed - current: %lld, max: %lld\n" msgstr "setrlimit nie powiodÅ‚o siÄ™ - bieżący: %lld, max: %lld\n" #: .././repair/init.c:107 #, c-format msgid "" "Unmount or use the dangerous (-d) option to repair a read-only mounted " "filesystem\n" msgstr "" "Aby naprawić system plików zamontowany do odczytu, trzeba go odmontować lub " "użyć opcji niebezpiecznej (-d).\n" #: .././repair/init.c:109 msgid "couldn't initialize XFS library\n" msgstr "nie udaÅ‚o siÄ™ zainicjować biblioteki XFS\n" #: .././repair/phase1.c:28 msgid "Sorry, could not find valid secondary superblock\n" msgstr "Niestety nie znaleziono poprawnego zapasowego superbloku\n" #: .././repair/phase1.c:29 msgid "Exiting now.\n" msgstr "ZakoÅ„czono.\n" #: .././repair/phase1.c:40 #, c-format msgid "could not allocate ag header buffer (%d bytes)\n" msgstr "nie udaÅ‚o siÄ™ przydzielić bufora nagłówka ag (%d bajtów)\n" #: .././repair/phase1.c:58 msgid "Phase 1 - find and verify superblock...\n" msgstr "Faza 1 - szukanie i sprawdzanie superbloku...\n" #: .././repair/phase1.c:75 msgid "error reading primary superblock\n" msgstr "błąd podczas odczytu głównego superbloku\n" #: .././repair/phase1.c:81 #, c-format msgid "bad primary superblock - %s !!!\n" msgstr "błędny główny superblok - %s!!!\n" #: .././repair/phase1.c:88 #, c-format msgid "couldn't verify primary superblock - %s !!!\n" msgstr "nie udaÅ‚o siÄ™ sprawdzić głównego superbloku - %s!!!\n" #: .././repair/phase1.c:106 msgid "superblock has a features2 mismatch, correcting\n" msgstr "superblok ma niepasujÄ…ce features2, poprawianie\n" #: .././repair/phase1.c:123 #, c-format msgid "Enabling lazy-counters\n" msgstr "Włączanie leniwych liczników\n" #: .././repair/phase1.c:127 #, fuzzy, c-format msgid "Cannot disable lazy-counters on V5 fs\n" msgstr "Wyłączanie leniwych liczników\n" #: .././repair/phase1.c:132 #, c-format msgid "Disabling lazy-counters\n" msgstr "Wyłączanie leniwych liczników\n" #: .././repair/phase1.c:135 #, c-format msgid "Lazy-counters are already %s\n" msgstr "Leniwe liczniki już sÄ… %s\n" #: .././repair/phase1.c:136 msgid "enabled" msgstr "włączone" #: .././repair/phase1.c:136 msgid "disabled" msgstr "wyłączone" #: .././repair/phase1.c:143 msgid "writing modified primary superblock\n" msgstr "zapisano zmodyfikowany główny superblok\n" #: .././repair/phase1.c:146 msgid "would write modified primary superblock\n" msgstr "zmodyfikowany główny superblok zostaÅ‚by zapisany\n" #: .././repair/phase2.c:79 #, fuzzy, c-format msgid "zero_log: cannot find log head/tail (xlog_find_tail=%d)\n" msgstr "" "zero_log: nie znaleziono poczÄ…tku/koÅ„ca logu (xlog_find_tail=%d), wyzerowano " "go\n" #: .././repair/phase2.c:83 msgid "" "ERROR: The log head and/or tail cannot be discovered. Attempt to mount the\n" "filesystem to replay the log or use the -L option to destroy the log and\n" "attempt a repair.\n" msgstr "" #: .././repair/phase2.c:90 #, c-format msgid "zero_log: head block % tail block %\n" msgstr "zero_log: blok poczÄ…tku % blok koÅ„ca %\n" #: .././repair/phase2.c:96 msgid "" "ALERT: The filesystem has valuable metadata changes in a log which is being\n" "destroyed because the -L option was used.\n" msgstr "" "UWAGA: system plików zawiera wartoÅ›ciowe zmiany metadanych w logu, który " "jest\n" "niszczony, ponieważ użyto opcji -L.\n" #: .././repair/phase2.c:100 msgid "" "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running xfs_repair. If you are unable to mount the filesystem, then use\n" "the -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n" msgstr "" "BÅÄ„D: system plików zawiera wartoÅ›ciowe zmiany metadanych w logu, który\n" "musi być odtworzony. Należy podmontować system plików, aby odtworzyć log,\n" "a nastÄ™pnie odmontować go przed ponownym uruchomieniem xfs_repair. JeÅ›li\n" "systemu plików nie da siÄ™ podmontować, można użyć opcji -L, aby zniszczyć\n" "log i spróbować naprawić system plików.\n" "Należy zauważyć, że zniszczenie logu może spowodować uszkodzenia danych -\n" "proszÄ™ najpierw spróbować podmontować system plików.\n" #: .././repair/phase2.c:128 #, fuzzy msgid "failed to clear log" msgstr "%s: caÅ‚kowicie wyczyszczony log\n" #: .././repair/phase2.c:162 msgid "" "This filesystem has an external log. Specify log device with the -l " "option.\n" msgstr "" "Ten system plików ma zewnÄ™trzny log. Należy podać urzÄ…dzenie logu przy " "użyciu opcji -l.\n" #: .././repair/phase2.c:165 #, c-format msgid "Phase 2 - using external log on %s\n" msgstr "Faza 2 - użycie zewnÄ™trznego logu na %s\n" #: .././repair/phase2.c:167 msgid "Phase 2 - using internal log\n" msgstr "Faza 2 - użycie wewnÄ™trznego logu\n" #: .././repair/phase2.c:170 msgid " - zero log...\n" msgstr " - zerowanie logu...\n" #: .././repair/phase2.c:173 msgid " - scan filesystem freespace and inode maps...\n" msgstr "" " - przeszukiwanie wolnego miejsca i map i-wÄ™złów w systemie " "plików...\n" #: .././repair/phase2.c:189 msgid "root inode chunk not found\n" msgstr "nie znaleziono danych głównego i-wÄ™zÅ‚a\n" #: .././repair/phase2.c:208 msgid " - found root inode chunk\n" msgstr " - znaleziono dane głównego i-wÄ™zÅ‚a\n" #: .././repair/phase2.c:214 msgid "root inode marked free, " msgstr "główny i-wÄ™zeÅ‚ oznaczony jako wolny, " #: .././repair/phase2.c:223 msgid "realtime bitmap inode marked free, " msgstr "i-wÄ™zeÅ‚ bitmapy realtime oznaczony jako wolny, " #: .././repair/phase2.c:232 msgid "realtime summary inode marked free, " msgstr "i-wÄ™zeÅ‚ opisu realtime oznaczony jako wolny, " #: .././repair/phase3.c:47 #, c-format msgid "cannot read agi block % for ag %u\n" msgstr "nie można odczytać bloku agi % dla ag %u\n" #: .././repair/phase3.c:78 .././repair/phase4.c:142 .././repair/phase5.c:2260 #: .././repair/phase6.c:3134 #, c-format msgid " - agno = %d\n" msgstr " - agno = %d\n" #: .././repair/phase3.c:119 msgid "Phase 3 - for each AG...\n" msgstr "Faza 3 - dla każdej AG...\n" #: .././repair/phase3.c:121 msgid " - scan and clear agi unlinked lists...\n" msgstr " - przeszukiwanie i czyszczenie odłączonych list agi...\n" #: .././repair/phase3.c:123 msgid " - scan (but don't clear) agi unlinked lists...\n" msgstr "" " - przeszukiwanie (ale nie czyszczenie) odłączonych list agi...\n" #: .././repair/phase3.c:143 msgid " - process known inodes and perform inode discovery...\n" msgstr " - przetwarzanie znanych i-wÄ™złów i rozpoznawanie i-wÄ™złów...\n" #: .././repair/phase3.c:154 msgid " - process newly discovered inodes...\n" msgstr " - przetwarzanie nowo rozpoznanych i-wÄ™złów...\n" #: .././repair/phase3.c:159 #, fuzzy msgid "no memory for uncertain inode counts\n" msgstr "brak pamiÄ™ci na liczniki nagłówków ag\n" #: .././repair/phase4.c:165 #, c-format msgid "" "unable to finish adding attr/data fork reverse-mapping data for AG %u.\n" msgstr "" #: .././repair/phase4.c:181 #, c-format msgid "unable to add AG %u metadata reverse-mapping data.\n" msgstr "" #: .././repair/phase4.c:186 #, c-format msgid "unable to merge AG %u metadata reverse-mapping data.\n" msgstr "" #: .././repair/phase4.c:191 #, c-format msgid "%s while checking reverse-mappings" msgstr "" #: .././repair/phase4.c:206 #, c-format msgid "%s while computing reference count records.\n" msgstr "" #: .././repair/phase4.c:221 #, c-format msgid "%s while fixing inode reflink flags.\n" msgstr "" #: .././repair/phase4.c:236 #, c-format msgid "%s while checking reference counts" msgstr "" #: .././repair/phase4.c:290 msgid "Phase 4 - check for duplicate blocks...\n" msgstr "Faza 4 - sprawdzanie powtórzonych bloków...\n" #: .././repair/phase4.c:291 msgid " - setting up duplicate extent list...\n" msgstr " - tworzenie listy powtórzonych ekstentów...\n" #: .././repair/phase4.c:305 msgid "root inode would be lost\n" msgstr "główny i-wÄ™zeÅ‚ zostaÅ‚by utracony\n" #: .././repair/phase4.c:307 msgid "root inode lost\n" msgstr "główny i-wÄ™zeÅ‚ utracony\n" #: .././repair/phase4.c:324 #, c-format msgid "unknown block state, ag %d, block %d\n" msgstr "nieznany stan bloku, ag %d, blok %d\n" #: .././repair/phase4.c:357 #, c-format msgid "unknown rt extent state, extent %\n" msgstr "nieznany stan ekstentu rt, ekstent %\n" #: .././repair/phase4.c:406 msgid " - check for inodes claiming duplicate blocks...\n" msgstr "" " - szukanie i-wÄ™złów odwoÅ‚ujÄ…cych siÄ™ do powtórzonych bloków...\n" #: .././repair/phase5.c:223 msgid "could not set up btree block array\n" msgstr "nie udaÅ‚o siÄ™ utworzyć tablicy bloków b-drzewa\n" #: .././repair/phase5.c:244 msgid "error - not enough free space in filesystem\n" msgstr "błąd - za maÅ‚o wolnego miejsca w systemie plików\n" #: .././repair/phase5.c:259 #, fuzzy, c-format msgid "could not set up btree rmaps: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć tablicy bloków b-drzewa\n" #: .././repair/phase5.c:475 #, c-format msgid "can't rebuild fs trees -- not enough free space on ag %u\n" msgstr "" "nie można przebudować drzew systemu plików - za maÅ‚o wolnego miejsca w ag " "%u\n" #: .././repair/phase5.c:498 #, c-format msgid "ag %u - not enough free space to build freespace btrees\n" msgstr "" "ag %u - za maÅ‚o wolnego miejsca na przebudowanie b-drzew wolnego miejsca\n" #: .././repair/phase5.c:533 #, c-format msgid "not enough free blocks left to describe all free blocks in AG %u\n" msgstr "za maÅ‚o wolnych bloków na opisanie wszystkich wolnych bloków w AG %u\n" #: .././repair/phase5.c:1622 msgid "Insufficient memory to construct reverse-map cursor." msgstr "" #: .././repair/phase5.c:1928 msgid "Insufficient memory to construct refcount cursor." msgstr "" #: .././repair/phase5.c:2139 .././repair/phase5.c:2147 msgid "Insufficient memory saving lost blocks.\n" msgstr "" #: .././repair/phase5.c:2202 .././repair/xfs_repair.c:1032 msgid "couldn't get superblock\n" msgstr "nie udaÅ‚o siÄ™ pobrać superbloku\n" #: .././repair/phase5.c:2283 #, c-format msgid "unable to rebuild AG %u. Not enough free space in on-disk AG.\n" msgstr "" "nie udaÅ‚o siÄ™ przebudować AG %u. Za maÅ‚o wolnego miejsca w AG na dysku.\n" #: .././repair/phase5.c:2335 #, c-format msgid "unable to rebuild AG %u. No free space.\n" msgstr "nie udaÅ‚o siÄ™ przebudować AG %u. Brak wolnego miejsca.\n" #: .././repair/phase5.c:2459 #, c-format msgid "unable to add AG %u reverse-mapping data to btree.\n" msgstr "" #: .././repair/phase5.c:2519 msgid "Phase 5 - rebuild AG headers and trees...\n" msgstr "Faza 5 - przebudowywanie nagłówków i drzew AG...\n" #: .././repair/phase5.c:2548 msgid "cannot alloc sb_icount_ag buffers\n" msgstr "nie można przydzielić buforów sb_icount_ag\n" #: .././repair/phase5.c:2552 msgid "cannot alloc sb_ifree_ag buffers\n" msgstr "nie można przydzielić buforów sb_ifree_ag\n" #: .././repair/phase5.c:2556 msgid "cannot alloc sb_fdblocks_ag buffers\n" msgstr "nie można przydzielić buforów sb_fdblocks_ag\n" #: .././repair/phase5.c:2560 #, fuzzy msgid "cannot alloc lost block slab\n" msgstr "nie można przydzielić buforów sb_fdblocks_ag\n" #: .././repair/phase5.c:2579 msgid " - generate realtime summary info and bitmap...\n" msgstr " - generowanie opisu i bitmapy realtime...\n" #: .././repair/phase5.c:2584 msgid " - reset superblock...\n" msgstr " - przestawianie superbloku...\n" #: .././repair/phase5.c:2593 #, fuzzy msgid "Unable to reinsert lost blocks into filesystem.\n" msgstr "wprowadzanie błędów do systemu plików" #: .././repair/phase6.c:64 #, c-format msgid "malloc failed add_dotdot_update (%zu bytes)\n" msgstr "malloc nie powiodÅ‚o siÄ™ w add_dotdot_update (%zu bajtów)\n" #: .././repair/phase6.c:216 #, c-format msgid "malloc failed in dir_hash_add (%zu bytes)\n" msgstr "malloc nie powiodÅ‚o siÄ™ w dir_hash_add (%zu bajtów)\n" #: .././repair/phase6.c:270 msgid "ok" msgstr "ok" #: .././repair/phase6.c:271 msgid "duplicate leaf" msgstr "powtórzony liść" #: .././repair/phase6.c:272 msgid "hash value mismatch" msgstr "niezgodność wartoÅ›ci hasza" #: .././repair/phase6.c:273 msgid "no data entry" msgstr "brak wpisu danych" #: .././repair/phase6.c:274 msgid "no leaf entry" msgstr "brak wpisu liÅ›cia" #: .././repair/phase6.c:275 msgid "bad stale count" msgstr "błędna liczba stale" #: .././repair/phase6.c:283 #, c-format msgid "bad hash table for directory inode % (%s): " msgstr "błędna tablica haszujÄ…ca dla i-wÄ™zÅ‚a katalogu % (%s): " #: .././repair/phase6.c:286 msgid "rebuilding\n" msgstr "przebudowano\n" #: .././repair/phase6.c:288 msgid "would rebuild\n" msgstr "zostaÅ‚aby przebudowana\n" #: .././repair/phase6.c:324 msgid "calloc failed in dir_hash_init\n" msgstr "calloc nie powiodÅ‚o siÄ™ w dir_hash_init\n" #: .././repair/phase6.c:472 msgid "ran out of disk space!\n" msgstr "brak miejsca na dysku!\n" #: .././repair/phase6.c:474 #, c-format msgid "xfs_trans_reserve returned %d\n" msgstr "xfs_trans_reserve zwróciÅ‚o %d\n" #: .././repair/phase6.c:504 .././repair/phase6.c:606 #, c-format msgid "couldn't iget realtime bitmap inode -- error - %d\n" msgstr "nie udaÅ‚o siÄ™ wykonać iget dla i-wÄ™zÅ‚a bitmapy realtime - błąd %d\n" #: .././repair/phase6.c:562 #, c-format msgid "couldn't allocate realtime bitmap, error = %d\n" msgstr "nie udaÅ‚o siÄ™ przydzielić bitmapy realtime, błąd = %d\n" #: .././repair/phase6.c:575 #, c-format msgid "allocation of the realtime bitmap failed, error = %d\n" msgstr "przydzielenie bitmapy realtime nie powiodÅ‚o siÄ™, błąd = %d\n" #: .././repair/phase6.c:620 #, c-format msgid "couldn't map realtime bitmap block %, error = %d\n" msgstr "nie udaÅ‚o siÄ™ odwzorować bloku bitmapy realtime %, błąd = %d\n" #: .././repair/phase6.c:633 #, c-format msgid "" "can't access block % (fsbno %) of realtime bitmap inode " "%\n" msgstr "" "brak dostÄ™pu do bloku % (fsbno %) i-wÄ™zÅ‚a bitmapy realtime " "%\n" #: .././repair/phase6.c:677 .././repair/phase6.c:751 #, c-format msgid "couldn't iget realtime summary inode -- error - %d\n" msgstr "nie udaÅ‚o siÄ™ wykonać iget dla i-wÄ™zÅ‚a opisu realtime - błąd %d\n" #: .././repair/phase6.c:691 #, c-format msgid "couldn't map realtime summary inode block %, error = %d\n" msgstr "" "nie udaÅ‚o siÄ™ odwzorować bloku i-wÄ™zÅ‚a opisu realtime %, błąd = %d\n" #: .././repair/phase6.c:704 #, c-format msgid "" "can't access block % (fsbno %) of realtime summary inode " "%\n" msgstr "" "brak dostÄ™pu do bloku % (fsbno %) i-wÄ™zÅ‚a opisu realtime " "%\n" #: .././repair/phase6.c:814 #, c-format msgid "couldn't allocate realtime summary inode, error = %d\n" msgstr "nie udaÅ‚o siÄ™ przydzielić i-wÄ™zÅ‚a opisu realtime, błąd = %d\n" #: .././repair/phase6.c:827 #, c-format msgid "allocation of the realtime summary ino failed, error = %d\n" msgstr "przydzielenie i-wÄ™zÅ‚a opisu realtime nie powiodÅ‚o siÄ™, błąd = %d\n" #: .././repair/phase6.c:856 #, c-format msgid "could not iget root inode -- error - %d\n" msgstr "nie udaÅ‚o siÄ™ wykonać iget dla głównego i-wÄ™zÅ‚a - błąd %d\n" #: .././repair/phase6.c:933 #, c-format msgid "%d - couldn't iget root inode to obtain %s\n" msgstr "%d - nie udaÅ‚o siÄ™ wykonać iget dla głównego wÄ™zÅ‚a, aby uzyskać %s\n" #: .././repair/phase6.c:963 #, c-format msgid "%s inode allocation failed %d\n" msgstr "przydzielenie i-wÄ™złą %s nie powiodÅ‚o siÄ™ - %d\n" #: .././repair/phase6.c:1010 #, c-format msgid "can't make %s, createname error %d\n" msgstr "nie można zrobić %s, błąd createname %d\n" #: .././repair/phase6.c:1030 #, c-format msgid "%s directory creation failed -- bmapf error %d\n" msgstr "tworzenie katalogu %s nie powiodÅ‚o siÄ™ - błąd bmapf %d\n" #: .././repair/phase6.c:1072 #, c-format msgid "%d - couldn't iget orphanage inode\n" msgstr "%d - nie udaÅ‚o siÄ™ wykonać iget dla i-wÄ™zÅ‚a sierociÅ„ca\n" #: .././repair/phase6.c:1083 #, c-format msgid "%d - couldn't iget disconnected inode\n" msgstr "%d - nie udaÅ‚o siÄ™ wykonać iget dla odłączonego i-wÄ™zÅ‚a\n" #: .././repair/phase6.c:1104 .././repair/phase6.c:1146 #: .././repair/phase6.c:1202 #, c-format msgid "space reservation failed (%d), filesystem may be out of space\n" msgstr "" "nie udaÅ‚o siÄ™ zarezerwować miejsca (%d), może brakować miejsca w systemie " "plików\n" #: .././repair/phase6.c:1115 .././repair/phase6.c:1158 #: .././repair/phase6.c:1213 #, c-format msgid "name create failed in %s (%d), filesystem may be out of space\n" msgstr "" "tworzenie nazwy nie powiodÅ‚o siÄ™ w %s (%d), może brakować miejsca w systemie " "plików\n" #: .././repair/phase6.c:1128 #, c-format msgid "creation of .. entry failed (%d), filesystem may be out of space\n" msgstr "" "tworzenie wpisu .. nie powiodÅ‚o siÄ™ (%d), może brakować miejsca w systemie " "plików\n" #: .././repair/phase6.c:1137 #, c-format msgid "bmap finish failed (err - %d), filesystem may be out of space\n" msgstr "" "zakoÅ„czenie bmap nie powiodÅ‚o siÄ™ (błąd %d), może brakować miejsca w " "systemie plików\n" #: .././repair/phase6.c:1177 #, c-format msgid "name replace op failed (%d), filesystem may be out of space\n" msgstr "" "operacja zastÄ…pienia nazwy nie powiodÅ‚a siÄ™ (%d), może brakować miejsca w " "systemie plików\n" #: .././repair/phase6.c:1184 .././repair/phase6.c:1223 #: .././repair/phase6.c:1357 #, c-format msgid "bmap finish failed (%d), filesystem may be out of space\n" msgstr "" "zakoÅ„czenie bmap nie powiodÅ‚o siÄ™ (%d), może brakować miejsca w systemie " "plików\n" #: .././repair/phase6.c:1242 msgid ", marking entry to be junked\n" msgstr ", zaznaczono wpis do wyrzucenia\n" #: .././repair/phase6.c:1246 msgid ", would junk entry\n" msgstr ", wpis zostaÅ‚by wyrzucony\n" #: .././repair/phase6.c:1279 #, c-format msgid "rebuilding directory inode %\n" msgstr "przebudowywanie i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:1301 #, c-format msgid "xfs_bmap_last_offset failed -- error - %d\n" msgstr "xfs_bmap_last_offset nie powiodÅ‚o siÄ™ - błąd %d\n" #: .././repair/phase6.c:1308 #, c-format msgid "xfs_bunmapi failed -- error - %d\n" msgstr "xfs_bunmapi nie powiodÅ‚o siÄ™ - błąd %d\n" #: .././repair/phase6.c:1316 #, fuzzy, c-format msgid "xfs_dir_init failed -- error - %d\n" msgstr "xfs_bunmapi nie powiodÅ‚o siÄ™ - błąd %d\n" #: .././repair/phase6.c:1349 #, c-format msgid "" "name create failed in ino % (%d), filesystem may be out of space\n" msgstr "" "tworzenie nazwy nie powiodÅ‚o siÄ™ w i-węźle % (%d), może brakować " "miejsca w systemie plików\n" #: .././repair/phase6.c:1412 #, c-format msgid "shrink_inode failed inode % block %u\n" msgstr "shrink_inode nie powiodÅ‚o siÄ™ dla i-wÄ™zÅ‚a % bloku %u\n" #: .././repair/phase6.c:1503 .././repair/phase6.c:2300 #, c-format msgid "realloc failed in %s (%zu bytes)\n" msgstr "realloc nie powiodÅ‚o siÄ™ w %s (bajtów: %zu)\n" #: .././repair/phase6.c:1560 #, c-format msgid "empty data block %u in directory inode %: " msgstr "pusty blok danych %u w i-węźle katalogu %: " #: .././repair/phase6.c:1564 #, c-format msgid "corrupt block %u in directory inode %: " msgstr "uszkodzony blok %u w i-węźle katalogu %: " #: .././repair/phase6.c:1568 msgid "junking block\n" msgstr "wyrzucono blok\n" #: .././repair/phase6.c:1571 msgid "would junk block\n" msgstr "blok zostaÅ‚by wyrzucony\n" #: .././repair/phase6.c:1593 #, c-format msgid "" "bad directory block magic # %#x for directory inode % block %d: " msgstr "" "błędna liczba magiczna bloku katalogu %#x dla i-wÄ™zÅ‚a katalogu % " "bloku %d: " #: .././repair/phase6.c:1596 #, c-format msgid "fixing magic # to %#x\n" msgstr "poprawiono liczbÄ™ magicznÄ… na %#x\n" #: .././repair/phase6.c:1600 #, c-format msgid "would fix magic # to %#x\n" msgstr "liczba magiczna zostaÅ‚aby poprawiona na %#x\n" #: .././repair/phase6.c:1621 #, c-format msgid "directory inode % block %u has consecutive free entries: " msgstr "i-wÄ™zeÅ‚ katalogu % blok %u ma kolejne wolne wpisy: " #: .././repair/phase6.c:1625 msgid "joining together\n" msgstr "połączono\n" #: .././repair/phase6.c:1634 msgid "would join together\n" msgstr "zostaÅ‚yby połączone\n" #: .././repair/phase6.c:1667 #, c-format msgid "" "entry \"%s\" in directory inode % points to non-existent inode " "%" msgstr "" "wpis \"%s\" w i-węźle katalogu % wskazuje na nie istniejÄ…cy i-wÄ™zeÅ‚ " "%" #: .././repair/phase6.c:1684 #, c-format msgid "" "entry \"%s\" in directory inode % points to free inode %" msgstr "" "wpis \"%s\" w i-węźle katalogu % wskazuje na wolny i-wÄ™zeÅ‚ %" #: .././repair/phase6.c:1702 .././repair/phase6.c:2627 #, c-format msgid "%s (ino %) in root (%) is not a directory" msgstr "" "%s (i-wÄ™zeÅ‚ %) w katalogu głównym (%) nie jest katalogiem" #: .././repair/phase6.c:1724 .././repair/phase6.c:2649 #, c-format msgid "entry \"%s\" (ino %) in dir % is a duplicate name" msgstr "" "wpis \"%s\" (i-wÄ™zeÅ‚ %) w katalogu % jest powtórzonÄ… nazwÄ…" #: .././repair/phase6.c:1755 #, c-format msgid "" "entry \"%s\" (ino %) in dir % is not in the the first block" msgstr "" "wpis \"%s\" (i-wÄ™zeÅ‚ %) w katalogu % nie jest w pierwszym " "bloku" #: .././repair/phase6.c:1781 #, c-format msgid "entry \"%s\" in dir % is not the first entry" msgstr "wpis \"%s\" w katalogu % nie jest pierwszym wpisem" #: .././repair/phase6.c:1807 .././repair/phase6.c:2718 #, c-format msgid "" "would fix ftype mismatch (%d/%d) in directory/child inode %/" "%\n" msgstr "" "niezgodność ftype (%d/%d) w i-węźle katalogu/potomnym %/% " "zostaÅ‚aby poprawiona\n" #: .././repair/phase6.c:1812 .././repair/phase6.c:2723 #, c-format msgid "" "fixing ftype mismatch (%d/%d) in directory/child inode %/%\n" msgstr "" "niezgodność ftype (%d/%d) w i-węźle katalogu/potomnym %/% " "zostanie poprawiona\n" #: .././repair/phase6.c:1845 #, c-format msgid "" "entry \"%s\" in dir % points to an already connected directory inode " "%\n" msgstr "" "wpis \"%s\" w katalogu % wskazuje na już podłączony i-wÄ™zeÅ‚ katalogu " "%\n" #: .././repair/phase6.c:1854 .././repair/phase6.c:2687 #, c-format msgid "" "entry \"%s\" in dir ino % doesn't have a .. entry, will set it in " "ino %.\n" msgstr "" "wpis \"%s\" w i-węźle katalogu % nie ma wpisu .., zostanie ustawiony " "w i-węźle %.\n" #: .././repair/phase6.c:1864 #, c-format msgid "" "entry \"%s\" in dir inode % inconsistent with .. value (%) " "in ino %\n" msgstr "" "wpis \"%s\" w i-węźle katalogu % niespójny z wartoÅ›ciÄ… .. " "(%) w i-węźle %\n" #: .././repair/phase6.c:1876 #, c-format msgid "\twill clear entry \"%s\"\n" msgstr "\twpis \"%s\" zostanie wyczyszczony\n" #: .././repair/phase6.c:1879 #, c-format msgid "\twould clear entry \"%s\"\n" msgstr "\twpis \"%s\" zostaÅ‚by wyczyszczony\n" #: .././repair/phase6.c:1912 #, fuzzy, c-format msgid "expected owner inode %, got %llu, directory block %\n" msgstr "" "oczekiwano i-wÄ™zÅ‚a wÅ‚aÅ›ciciela %, napotkano %llu, blok bmbt " "%\n" #: .././repair/phase6.c:1919 #, fuzzy, c-format msgid "expected block %, got %llu, directory inode %\n" msgstr "nie można odczytać bloku % dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:1926 #, fuzzy, c-format msgid "wrong FS UUID, directory inode % block %\n" msgstr "i-wÄ™zeÅ‚ katalogu % ma błędny rozmiar %\n" #: .././repair/phase6.c:1986 #, fuzzy, c-format msgid "leaf block %u for directory inode % bad CRC\n" msgstr "błędna koÅ„cówka bloku liÅ›cia %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:1991 #, c-format msgid "can't read block %u for directory inode %, error %d\n" msgstr "nie można odczytać bloku %u dla i-wÄ™zÅ‚a katalogu %, błąd %d\n" #: .././repair/phase6.c:2009 .././repair/phase6.c:2132 #, c-format msgid "leaf block %u for directory inode % bad header\n" msgstr "błędny nagłówek bloku liÅ›cia %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:2035 #, c-format msgid "leaf block %u for directory inode % bad tail\n" msgstr "błędna koÅ„cówka bloku liÅ›cia %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:2089 #, c-format msgid "can't read leaf block %u for directory inode %, error %d\n" msgstr "" "nie można odczytać bloku liÅ›cia %u dla i-wÄ™zÅ‚a katalogu %, błąd %d\n" #: .././repair/phase6.c:2101 #, c-format msgid "unknown magic number %#x for block %u in directory inode %\n" msgstr "" "nieznana liczba magiczna %#x dla bloku %u w i-węźle katalogu %\n" #: .././repair/phase6.c:2157 #, c-format msgid "can't read freespace block %u for directory inode %, error %d\n" msgstr "" "nie można odczytać bloku wolnego miejsca %u dla i-wÄ™zÅ‚a katalogu %, " "błąd %d\n" #: .././repair/phase6.c:2172 #, c-format msgid "free block %u for directory inode % bad header\n" msgstr "błędny nagłówek wolnego bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:2190 #, c-format msgid "free block %u entry %i for directory ino % bad\n" msgstr "błędny wpis wolnego bloku %u numer %i dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:2200 #, c-format msgid "free block %u for directory inode % bad nused\n" msgstr "błędna liczba nused w wolnym bloku %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:2211 #, c-format msgid "missing freetab entry %u for directory inode %\n" msgstr "brak wpisu freetab %u dla i-wÄ™zÅ‚a katalogu %\n" #: .././repair/phase6.c:2250 #, c-format msgid "malloc failed in %s (% bytes)\n" msgstr "malloc nie powiodÅ‚o siÄ™ w %s (bajtów: %)\n" #: .././repair/phase6.c:2264 #, c-format msgid "calloc failed in %s (%zu bytes)\n" msgstr "calloc nie powiodÅ‚o siÄ™ w %s (bajtów: %zu)\n" #: .././repair/phase6.c:2313 #, c-format msgid "can't read data block %u for directory inode % error %d\n" msgstr "" "nie można odczytać bloku danych %u dla i-wÄ™zÅ‚a katalogu %, błąd %d\n" #: .././repair/phase6.c:2420 msgid "would junk entry\n" msgstr "wpis zostaÅ‚by wyrzucony\n" #: .././repair/phase6.c:2444 msgid "junking entry\n" msgstr "wyrzucono wpis\n" #: .././repair/phase6.c:2490 #, c-format msgid "would set .. in sf dir inode % to %\n" msgstr "" "wpis .. w i-węźle katalogu sf % zostaÅ‚by ustawiony na %\n" #: .././repair/phase6.c:2494 #, c-format msgid "setting .. in sf dir inode % to %\n" msgstr "ustawiono wpis .. w i-węźle katalogu sf % na %\n" #: .././repair/phase6.c:2594 #, c-format msgid "" "entry \"%s\" in shortform directory % references non-existent inode " "%\n" msgstr "" "wpis \"%s\" w krótkim katalogu % odwoÅ‚uje siÄ™ do nie istniejÄ…cego i-" "wÄ™zÅ‚a %\n" #: .././repair/phase6.c:2611 #, c-format msgid "" "entry \"%s\" in shortform directory inode % points to free inode " "%\n" msgstr "" "wpis \"%s\" w i-węźle krótkiego katalogu % wskazuje na wolny i-wÄ™zeÅ‚ " "%\n" #: .././repair/phase6.c:2673 #, c-format msgid "" "entry \"%s\" in directory inode % references already connected inode " "%.\n" msgstr "" "wpis \"%s\" w i-węźle katalogu % odwoÅ‚uje siÄ™ do już podłączonego i-" "wÄ™zÅ‚a %.\n" #: .././repair/phase6.c:2696 #, c-format msgid "" "entry \"%s\" in directory inode % not consistent with .. value " "(%) in inode %,\n" msgstr "" "wpis \"%s\" w i-węźle katalogu % niespójny z wartoÅ›ciÄ… .. " "(%) w i-węźle %,\n" #: .././repair/phase6.c:2753 #, c-format msgid "would fix i8count in inode %\n" msgstr "i8count w i-węźle % zostaÅ‚oby poprawione\n" #: .././repair/phase6.c:2768 #, c-format msgid "fixing i8count in inode %\n" msgstr "poprawiono i8count w i-węźle %\n" #: .././repair/phase6.c:2788 #, c-format msgid "setting size to % bytes to reflect junked entries\n" msgstr "ustawiono rozmiar na %, aby odzwierciedlaÅ‚ wyrzucone wpisy\n" #: .././repair/phase6.c:2827 .././repair/phase6.c:2831 .././repair/phase7.c:52 #, c-format msgid "couldn't map inode %, err = %d\n" msgstr "nie udaÅ‚o siÄ™ odwzorować i-wÄ™zÅ‚a %, błąd = %d\n" #: .././repair/phase6.c:2932 msgid "recreating root directory .. entry\n" msgstr "ponowne tworzenie wpisu .. głównego katalogu\n" #: .././repair/phase6.c:2948 #, c-format msgid "can't make \"..\" entry in root inode %, createname error %d\n" msgstr "" "nie można utworzyć wpisu \"..\" w i-węźle głównego katalogu %, błąd " "createname %d\n" #: .././repair/phase6.c:2958 msgid "would recreate root directory .. entry\n" msgstr "wpis .. głównego katalogu zostaÅ‚by ponownie utworzony\n" #: .././repair/phase6.c:2982 #, c-format msgid "would create missing \".\" entry in dir ino %\n" msgstr "brakujÄ…cy wpis \".\" w i-węźle katalogu % zostaÅ‚by utworzony\n" #: .././repair/phase6.c:2989 #, c-format msgid "creating missing \".\" entry in dir ino %\n" msgstr "tworzenie brakujÄ…cego wpisu \".\" w i-węźle katalogu %\n" #: .././repair/phase6.c:3005 #, c-format msgid "can't make \".\" entry in dir ino %, createname error %d\n" msgstr "" "nie można utworzyć wpisu \".\" w i-węźle katalogu %, błąd createname " "%d\n" #: .././repair/phase6.c:3101 #, c-format msgid "disconnected dir inode %, " msgstr "odłączony i-wÄ™zeÅ‚ katalogu %, " #: .././repair/phase6.c:3103 #, c-format msgid "disconnected inode %, " msgstr "odłączony i-wÄ™zeÅ‚ %, " #: .././repair/phase6.c:3107 #, c-format msgid "moving to %s\n" msgstr "przeniesiono do %s\n" #: .././repair/phase6.c:3110 #, c-format msgid "would move to %s\n" msgstr "zostaÅ‚by przeniesiony do %s\n" #: .././repair/phase6.c:3195 msgid "Phase 6 - check inode connectivity...\n" msgstr "Faza 6 - sprawdzanie łącznoÅ›ci i-wÄ™złów...\n" #: .././repair/phase6.c:3209 msgid "reinitializing root directory\n" msgstr "ponowne inicjowanie głównego katalogu\n" #: .././repair/phase6.c:3214 msgid "would reinitialize root directory\n" msgstr "główny katalog zostaÅ‚by ponownie zainicjowany\n" #: .././repair/phase6.c:3220 msgid "reinitializing realtime bitmap inode\n" msgstr "ponowne inicjowanie i-wÄ™zÅ‚a bitmapy realtime\n" #: .././repair/phase6.c:3224 msgid "would reinitialize realtime bitmap inode\n" msgstr "i-wÄ™zeÅ‚ bitmapy realtime zostaÅ‚by ponownie zainicjowany\n" #: .././repair/phase6.c:3230 msgid "reinitializing realtime summary inode\n" msgstr "ponowne inicjowanie i-wÄ™zÅ‚a opisu realtime\n" #: .././repair/phase6.c:3234 msgid "would reinitialize realtime summary inode\n" msgstr "i-wÄ™zeÅ‚ opisu realtime zostaÅ‚by ponownie zainicjowany\n" #: .././repair/phase6.c:3240 msgid " - resetting contents of realtime bitmap and summary inodes\n" msgstr " - przestawianie zawartoÅ›ci i-wÄ™złów bitmapy i opisu realtime\n" #: .././repair/phase6.c:3243 .././repair/phase6.c:3248 msgid "Warning: realtime bitmap may be inconsistent\n" msgstr "Uwaga: bitmapa realtime może być niespójna\n" #: .././repair/phase6.c:3254 msgid " - traversing filesystem ...\n" msgstr " - przechodzenie systemu plików...\n" #: .././repair/phase6.c:3277 msgid " - traversal finished ...\n" msgstr " - przechodzenie zakoÅ„czone...\n" #: .././repair/phase6.c:3278 #, c-format msgid " - moving disconnected inodes to %s ...\n" msgstr " - przenoszenie odłączonych i-wÄ™złów do %s...\n" #: .././repair/phase7.c:56 #, c-format msgid "couldn't map inode %, err = %d, can't compare link counts\n" msgstr "" "nie udaÅ‚o siÄ™ odwzorować i-wÄ™zÅ‚a %, błąd %d, nie można porównać " "liczby dowiÄ…zaÅ„\n" #: .././repair/phase7.c:68 #, c-format msgid "resetting inode % nlinks from %u to %u\n" msgstr "przestawiono nlinks i-wÄ™zÅ‚a % z %u na %u\n" #: .././repair/phase7.c:74 #, c-format msgid "would have reset inode % nlinks from %u to %u\n" msgstr "nlinks i-wÄ™zÅ‚a % zostaÅ‚oby przestawione z %u na %u\n" #: .././repair/phase7.c:142 msgid "Phase 7 - verify and correct link counts...\n" msgstr "Faza 7 - sprawdzanie i poprawianie liczby dowiÄ…zaÅ„...\n" #: .././repair/phase7.c:144 msgid "Phase 7 - verify link counts...\n" msgstr "Faza 7 - sprawdzanie liczby dowiÄ…zaÅ„...\n" #: .././repair/prefetch.c:543 msgid "prefetch corruption\n" msgstr "uszkodzenie prefetch\n" #: .././repair/prefetch.c:704 .././repair/prefetch.c:817 #, c-format msgid "failed to create prefetch thread: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć wÄ…tku prefetch: %s\n" #: .././repair/prefetch.c:854 msgid "failed to initialize prefetch mutex\n" msgstr "nie udaÅ‚o siÄ™ zainicjować muteksu prefetch\n" #: .././repair/prefetch.c:856 .././repair/prefetch.c:858 msgid "failed to initialize prefetch cond var\n" msgstr "nie udaÅ‚o siÄ™ zainicjować zmiennej warunkowej prefetch\n" #: .././repair/progress.c:16 msgid "inodes" msgstr "i-wÄ™złów" #: .././repair/progress.c:20 msgid "directories" msgstr "katalogów" #: .././repair/progress.c:22 msgid "allocation groups" msgstr "grup alokacji" #: .././repair/progress.c:24 msgid "AGI unlinked buckets" msgstr "odłączonych kubeÅ‚ków AGI" #: .././repair/progress.c:28 msgid "realtime extents" msgstr "ekstentów realtime" #: .././repair/progress.c:30 msgid "unlinked lists" msgstr "odłączonych list" #: .././repair/progress.c:37 #, c-format msgid " - %02d:%02d:%02d: %s - %llu of %llu %s done\n" msgstr " - %02d:%02d:%02d: %s - sprawdzono %llu z %llu %s\n" #: .././repair/progress.c:39 #, c-format msgid " - %02d:%02d:%02d: %s - %llu %s done\n" msgstr " - %02d:%02d:%02d: %s - sprawdzono %llu %s\n" #: .././repair/progress.c:51 msgid "scanning filesystem freespace" msgstr "przeszukiwanie wolnego miejsca w systemie plików" #: .././repair/progress.c:53 msgid "scanning agi unlinked lists" msgstr "przeszukiwanie odłączonych list agi" #: .././repair/progress.c:55 msgid "check uncertain AG inodes" msgstr "sprawdzanie niepewnych i-wÄ™złów AG" #: .././repair/progress.c:57 msgid "process known inodes and inode discovery" msgstr "przetwarzanie znanych i-wÄ™złów i rozpoznawanie i-wÄ™złów" #: .././repair/progress.c:59 msgid "process newly discovered inodes" msgstr "przetwarzanie nowo rozpoznanych i-wÄ™złów" #: .././repair/progress.c:61 msgid "setting up duplicate extent list" msgstr "tworzenie listy powtórzonych ekstentów" #: .././repair/progress.c:63 msgid "initialize realtime bitmap" msgstr "inicjowanie bitmapy realtime" #: .././repair/progress.c:65 msgid "reset realtime bitmaps" msgstr "ponowne tworzenie bitmapy realtime" #: .././repair/progress.c:67 msgid "check for inodes claiming duplicate blocks" msgstr "szukanie i-wÄ™złów odwoÅ‚ujÄ…cych siÄ™ do powtórzonych bloków" #: .././repair/progress.c:69 msgid "rebuild AG headers and trees" msgstr "przebudowywanie nagłówków i drzew AG" #: .././repair/progress.c:71 msgid "traversing filesystem" msgstr "przechodzenie systemu plików" #: .././repair/progress.c:73 msgid "traversing all unattached subtrees" msgstr "przechodzenie wszystkich odłączonych poddrzew" #: .././repair/progress.c:75 msgid "moving disconnected inodes to lost+found" msgstr "przenoszenie odłączonych i-wÄ™złów do lost+found" #: .././repair/progress.c:77 msgid "verify and correct link counts" msgstr "sprawdzanie i poprawianie liczby dowiÄ…zaÅ„" #: .././repair/progress.c:79 msgid "verify link counts" msgstr "sprawdzanie liczby dowiÄ…zaÅ„" #: .././repair/progress.c:118 msgid "cannot malloc pointer to done vector\n" msgstr "nie udaÅ‚o siÄ™ przydzielić wskaźnika do wektora wykonania\n" #: .././repair/progress.c:135 msgid "unable to create progress report thread\n" msgstr "nie udaÅ‚o siÄ™ utworzyć wÄ…tku raportowania postÄ™pu\n" #: .././repair/progress.c:178 msgid "progress_rpt: cannot malloc progress msg buffer\n" msgstr "progress_rpt: nie udaÅ‚o siÄ™ przydzielić bufora komunikatów postÄ™pu\n" #: .././repair/progress.c:191 msgid "progress_rpt: cannot create timer\n" msgstr "progress_rpt: nie można utworzyć zegara\n" #: .././repair/progress.c:194 msgid "progress_rpt: cannot set timer\n" msgstr "progress_rpt: nie można ustawić zegara\n" #: .././repair/progress.c:218 msgid "progress_rpt: cannot lock progress mutex\n" msgstr "progress_rpt: nie można zablokować muteksu\n" #: .././repair/progress.c:255 .././repair/progress.c:358 #, c-format msgid "%s" msgstr "%s" #: .././repair/progress.c:263 #, c-format msgid "" "\t- %02d:%02d:%02d: Phase %d: elapsed time %s - processed %d %s per minute\n" msgstr "" "\t- %02d:%02d:%02d: Faza %d: miniony czas %s - przetworzono %d %s na minutÄ™\n" #: .././repair/progress.c:268 #, c-format msgid "" "\t- %02d:%02d:%02d: Phase %d: %%% done - estimated remaining time " "%s\n" msgstr "" "\t- %02d:%02d:%02d: Faza %d: %%% zrobione - przewidywany pozostaÅ‚y " "czas %s\n" #: .././repair/progress.c:276 msgid "progress_rpt: error unlock msg mutex\n" msgstr "progress_rpt: błąd odblokowywania muteksu komunikatów\n" #: .././repair/progress.c:282 msgid "cannot delete timer\n" msgstr "nie można usunąć zegara\n" #: .././repair/progress.c:296 msgid "set_progress_msg: cannot lock progress mutex\n" msgstr "set_progress_msg: nie można zablokować mutekstu postÄ™pu\n" #: .././repair/progress.c:306 msgid "set_progress_msg: cannot unlock progress mutex\n" msgstr "set_progress_msg: nie można odblokować mutekstu postÄ™pu\n" #: .././repair/progress.c:326 msgid "print_final_rpt: cannot lock progress mutex\n" msgstr "print_final_rpt: nie można zablokować mutekstu postÄ™pu\n" #: .././repair/progress.c:362 msgid "print_final_rpt: cannot unlock progress mutex\n" msgstr "print_final_rpt: nie można odblokować muteksu postÄ™pu\n" #: .././repair/progress.c:411 #, c-format msgid "%02d:%02d:%02d" msgstr "%02d:%02d:%02d" #: .././repair/progress.c:433 #, c-format msgid "%d week" msgstr "%d tygodni" #: .././repair/progress.c:434 .././repair/progress.c:444 #: .././repair/progress.c:460 .././repair/progress.c:478 #: .././repair/progress.c:493 msgid "s" msgstr " " # XXX: ngettext() #: .././repair/progress.c:443 #, c-format msgid "%d day" msgstr "%d dni" #: .././repair/progress.c:450 .././repair/progress.c:467 #: .././repair/progress.c:485 .././repair/progress.c:495 msgid ", " msgstr ", " #: .././repair/progress.c:459 #, c-format msgid "%d hour" msgstr "%d godzin" #: .././repair/progress.c:477 #, c-format msgid "%d minute" msgstr "%d minut" #: .././repair/progress.c:492 #, c-format msgid "%d second" msgstr "%d sekund" #: .././repair/progress.c:513 #, c-format msgid "" "\n" " XFS_REPAIR Summary %s\n" msgstr "" "\n" " Podsumowanie XFS_REPAIR %s\n" #: .././repair/progress.c:515 msgid "Phase\t\tStart\t\tEnd\t\tDuration\n" msgstr "Faza\t\tPoczÄ…tek\tKoniec\t\tCzas trwania\n" #: .././repair/progress.c:520 .././repair/progress.c:523 #, c-format msgid "Phase %d:\tSkipped\n" msgstr "Faza %d:\tPominiÄ™ta\n" #: .././repair/progress.c:527 #, c-format msgid "Phase %d:\t%02d/%02d %02d:%02d:%02d\t%02d/%02d %02d:%02d:%02d\t%s\n" msgstr "Faza %d:\t%02d.%02d %02d:%02d:%02d\t%02d.%02d %02d:%02d:%02d\t%s\n" #: .././repair/progress.c:533 #, c-format msgid "" "\n" "Total run time: %s\n" msgstr "" "\n" "CaÅ‚kowity czas trwania: %s\n" #: .././repair/rmap.c:112 #, fuzzy msgid "couldn't allocate per-AG reverse map roots\n" msgstr "nie udaÅ‚o siÄ™ przydzielić korzeni b-drzewa mapy bloków\n" #: .././repair/rmap.c:119 msgid "Insufficient memory while allocating reverse mapping slabs." msgstr "" #: .././repair/rmap.c:124 .././repair/rmap.c:363 msgid "" "Insufficient memory while allocating raw metadata reverse mapping slabs." msgstr "" #: .././repair/rmap.c:130 msgid "Insufficient memory while allocating refcount item slabs." msgstr "" #: .././repair/rmap.c:736 msgid "Insufficient memory while recreating refcount tree." msgstr "" #: .././repair/rmap.c:993 msgid "would rebuild corrupt rmap btrees.\n" msgstr "" #: .././repair/rmap.c:1036 #, c-format msgid "" "Missing reverse-mapping record for (%u/%u) %slen %u owner % %s%soff " "%\n" msgstr "" #: .././repair/rmap.c:1040 .././repair/rmap.c:1058 .././repair/rmap.c:1068 msgid "unwritten " msgstr "" #: .././repair/rmap.c:1044 .././repair/rmap.c:1062 .././repair/rmap.c:1072 #, fuzzy msgid "attr " msgstr "atrybutów" #: .././repair/rmap.c:1046 .././repair/rmap.c:1064 .././repair/rmap.c:1074 msgid "bmbt " msgstr "" #: .././repair/rmap.c:1054 #, c-format msgid "" "Incorrect reverse-mapping: saw (%u/%u) %slen %u owner % %s%soff " "%; should be (%u/%u) %slen %u owner % %s%soff %\n" msgstr "" #: .././repair/rmap.c:1189 #, fuzzy, c-format msgid "setting reflink flag on inode %\n" msgstr "poprawiono nextents dla i-wÄ™zÅ‚a %\n" #: .././repair/rmap.c:1193 #, fuzzy, c-format msgid "clearing reflink flag on inode %\n" msgstr "wyczyszczono i-wÄ™zeÅ‚ bitmapy realtime %\n" #: .././repair/rmap.c:1264 #, fuzzy, c-format msgid "Unable to fix reflink flag on inode %.\n" msgstr "problem z dowiÄ…zaniem symbolicznym w i-węźle %\n" #: .././repair/rmap.c:1325 msgid "would rebuild corrupt refcount btrees.\n" msgstr "" #: .././repair/rmap.c:1358 .././repair/rmap.c:1369 #, c-format msgid "Missing reference count record for (%u/%u) len %u count %u\n" msgstr "" #: .././repair/rmap.c:1380 #, c-format msgid "" "Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) " "len %u nlinks %u\n" msgstr "" #: .././repair/rmap.c:1422 .././repair/rmap.c:1453 #, fuzzy, c-format msgid "failed to fix AGFL on AG %d, error %d\n" msgstr "%s: nie udaÅ‚o siÄ™ odnaleźć poczÄ…tku ani koÅ„ca, błąd: %d\n" #: .././repair/rt.c:47 msgid "couldn't allocate memory for incore realtime bitmap.\n" msgstr "nie udaÅ‚o siÄ™ przydzielić pamiÄ™ci dla bitmapy realtime.\n" #: .././repair/rt.c:51 msgid "couldn't allocate memory for incore realtime summary info.\n" msgstr "nie udaÅ‚o siÄ™ przydzielić pamiÄ™ci dla opisu realtime.\n" #: .././repair/rt.c:203 #, c-format msgid "can't find block %d for rtbitmap inode\n" msgstr "nie można odnaleźć bloku %d dla i-wÄ™zÅ‚a bitmapy realtime\n" #: .././repair/rt.c:211 #, c-format msgid "can't read block %d for rtbitmap inode\n" msgstr "nie można odczytać bloku %d dla i-wÄ™zÅ‚a bitmapy realtime\n" #: .././repair/rt.c:265 #, c-format msgid "block %d for rtsummary inode is missing\n" msgstr "brak bloku %d dla i-wÄ™zÅ‚a opisu realtime\n" #: .././repair/rt.c:273 #, c-format msgid "can't read block %d for rtsummary inode\n" msgstr "nie można odczytać bloku %d dla i-wÄ™zÅ‚a opisu realtime\n" #: .././repair/sb.c:125 msgid "error finding secondary superblock -- failed to memalign buffer\n" msgstr "" "błąd podczas szukania zapasowego superbloku - nie udaÅ‚o siÄ™ memalign bufora\n" #: .././repair/sb.c:162 msgid "found candidate secondary superblock...\n" msgstr "znaleziono potencjalny zapasowy superblok...\n" #: .././repair/sb.c:174 msgid "verified secondary superblock...\n" msgstr "sprawdzono zapasowy superblok...\n" #: .././repair/sb.c:179 msgid "unable to verify superblock, continuing...\n" msgstr "nie udaÅ‚o siÄ™ sprawdzić superbloku, kontynuacja...\n" #: .././repair/sb.c:229 msgid "" "\n" "attempting to find secondary superblock...\n" msgstr "" "\n" "próba odnalezienia zapasowego superbloku...\n" #: .././repair/sb.c:510 msgid "failed to memalign superblock buffer\n" msgstr "nie udaÅ‚o siÄ™ wykonać memalign dla bufora superbloku\n" #: .././repair/sb.c:517 msgid "couldn't seek to offset 0 in filesystem\n" msgstr "nie udaÅ‚o siÄ™ wykonać seek na offset 0 w systemie plików\n" #: .././repair/sb.c:527 msgid "primary superblock write failed!\n" msgstr "zapis głównego superbloku nie powiódÅ‚ siÄ™!\n" #: .././repair/sb.c:545 #, c-format msgid "error reading superblock %u -- failed to memalign buffer\n" msgstr "" "błąd podczas odczytu superbloku %u - nie udaÅ‚o siÄ™ wykonać memalign dla " "bufora\n" #: .././repair/sb.c:556 #, c-format msgid "error reading superblock %u -- seek to offset % failed\n" msgstr "" "błąd podczas odczytu superbloku %u - seek na offset % nie powiódÅ‚ " "siÄ™\n" #: .././repair/sb.c:565 #, c-format msgid "superblock read failed, offset %, size %d, ag %u, rval %d\n" msgstr "" "odczyt superbloku nie powiódÅ‚ siÄ™, offset %, rozmiar %d, ag %u, rval " "%d\n" #: .././repair/sb.c:612 msgid "couldn't malloc geometry structure\n" msgstr "nie udaÅ‚o siÄ™ przydzielić struktury geometrii\n" #: .././repair/sb.c:766 msgid "" "Only two AGs detected and they do not match - cannot validate filesystem " "geometry.\n" "Use the -o force_geometry option to proceed.\n" msgstr "" "Wykryto tylko dwie AG i nie zgadzajÄ… siÄ™ - nie można sprawdzić poprawnoÅ›ci " "geometrii systemu plików.\n" "ProszÄ™ użyć opcji -o force_geometry, aby kontynuować.\n" #: .././repair/sb.c:782 msgid "" "Only one AG detected - cannot validate filesystem geometry.\n" "Use the -o force_geometry option to proceed.\n" msgstr "" "Wykryto tylko dwie AG - nie można sprawdzić poprawnoÅ›ci geometrii systemu " "plików.\n" "ProszÄ™ użyć opcji -o force_geometry, aby kontynuować.\n" #: .././repair/sb.c:797 msgid "Not enough matching superblocks - cannot proceed.\n" msgstr "Za maÅ‚o pasujÄ…cych superbloków - nie można kontynuować.\n" #: .././repair/sb.c:812 msgid "could not read superblock\n" msgstr "nie udaÅ‚o siÄ™ odczytać superbloku\n" #: .././repair/scan.c:85 .././repair/scan.c:140 #, c-format msgid "can't read btree block %d/%d\n" msgstr "nie można odczytać bloku b-drzewa %d/%d\n" #: .././repair/scan.c:89 .././repair/scan.c:152 #, c-format msgid "btree block %d/%d is suspect, error %d\n" msgstr "blok b-drzewa %d/%d jest podejrzany, błąd %d\n" #: .././repair/scan.c:213 #, c-format msgid "bad magic # %#x in inode % (%s fork) bmbt block %\n" msgstr "" "błędna liczba magiczna %#x w i-węźle % (gałąź %s) blok bmbt " "%\n" #: .././repair/scan.c:219 #, c-format msgid "" "expected level %d got %d in inode %, (%s fork) bmbt block %\n" msgstr "" "oczekiwano poziomu %d, a uzyskano %d w i-węźle %, (gałęzi %s) blok " "bmbt %\n" #: .././repair/scan.c:229 #, c-format msgid "expected owner inode %, got %llu, bmbt block %\n" msgstr "" "oczekiwano i-wÄ™zÅ‚a wÅ‚aÅ›ciciela %, napotkano %llu, blok bmbt " "%\n" #: .././repair/scan.c:237 #, fuzzy, c-format msgid "expected block %, got %llu, bmbt block %\n" msgstr "" "oczekiwano i-wÄ™zÅ‚a wÅ‚aÅ›ciciela %, napotkano %llu, blok bmbt " "%\n" #: .././repair/scan.c:246 #, c-format msgid "wrong FS UUID, bmbt block %\n" msgstr "" #: .././repair/scan.c:266 #, c-format msgid "" "bad fwd (right) sibling pointer (saw % parent block says %)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "błędny wskaźnik w przód (prawy) (widziano %, blok nadrzÄ™dny mówi " "%)\n" "\tw i-węźle % (gałęzi %s) bloku bmap btree %\n" #: .././repair/scan.c:276 #, c-format msgid "" "bad back (left) sibling pointer (saw %llu parent block says %)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "błędny wskaźnik wstecz (lewy) (widziano %llu, blok nadrzÄ™dny mówi " "%)\n" "\tw i-węźle % (gałęzi %s) bloku bmap btree %\n" #: .././repair/scan.c:291 #, c-format msgid "" "bad back (left) sibling pointer (saw %llu should be NULL (0))\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "błędny wskaźnik wstecz (lewy) (widziano %llu, powinien być NULL (0))\n" "\tw i-węźle % (gałęzi %s) bloku bmap btree %\n" #: .././repair/scan.c:339 #, c-format msgid "inode 0x%bmap block 0x% claimed, state is %d\n" msgstr "i-wÄ™zeÅ‚ 0x% blok bmap 0x% przypisany, stan to %d\n" #: .././repair/scan.c:346 #, c-format msgid "inode 0x% bmap block 0x% claimed, state is %d\n" msgstr "i-wÄ™zeÅ‚ 0x% blok bmap 0x% przypisany, stan to %d\n" #: .././repair/scan.c:361 #, c-format msgid "bad state %d, inode % bmap block 0x%\n" msgstr "błędny stan %d, i-wÄ™zeÅ‚ % blok bmap 0x%\n" #: .././repair/scan.c:389 #, fuzzy, c-format msgid "couldn't add inode % bmbt block % reverse-mapping data." msgstr "nie można odczytać i-wÄ™zÅ‚a %, blok dysku %, cnt %d\n" #: .././repair/scan.c:397 .././repair/scan.c:448 #, c-format msgid "inode % bad # of bmap records (%u, min - %u, max - %u)\n" msgstr "" "błędna liczba rekordów bmap w i-węźle % (%u, minimum - %u, maksimum " "- %u)\n" #: .././repair/scan.c:427 #, c-format msgid "" "out-of-order bmap key (file offset) in inode %, %s fork, fsbno " "%\n" msgstr "" "uszkodzony klucz bmap (offset pliku) w i-węźle %, gałęzi %s, fsbno " "%\n" #: .././repair/scan.c:465 #, c-format msgid "bad bmap btree ptr 0x%llx in ino %\n" msgstr "błędny wskaźnik bmap btree 0x%llx w i-węźle %\n" #: .././repair/scan.c:493 #, c-format msgid "" "correcting bt key (was %llu, now %) in inode %\n" "\t\t%s fork, btree block %\n" msgstr "" "poprawiono klucz bt (byÅ‚o %llu, jest %) w i-węźle %\n" "\t\tgałąź %s, blok b-drzewa %\n" #: .././repair/scan.c:505 #, c-format msgid "" "bad btree key (is %llu, should be %) in inode %\n" "\t\t%s fork, btree block %\n" msgstr "" "błędny klucz b-drzewa (jest %llu, powinno być %) w i-węźle " "%\n" "\t\tgałąź %s, blok b-drzewa %\n" #: .././repair/scan.c:523 #, c-format msgid "" "bad fwd (right) sibling pointer (saw % should be NULLFSBLOCK)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" "błędny wskaźnik w przód (prawy) (widziano %, powinien być " "NULLFSBLOCK)\n" "\tw i-węźle % (gałęzi %s) bloku bmap btree %\n" #: .././repair/scan.c:581 .././repair/scan.c:958 #, c-format msgid "bad magic # %#x in bt%s block %d/%d\n" msgstr "błędna liczba magiczna %#x w bloku bt%s %d/%d\n" #: .././repair/scan.c:599 .././repair/scan.c:977 #, c-format msgid "expected level %d got %d in bt%s block %d/%d\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku bt%s %d/%d\n" #: .././repair/scan.c:613 #, c-format msgid "" "%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "blok b-drzewa wolnego miejsca %s przypisany (stan %d), agno %d, bno %d, " "podejrzany %d\n" #: .././repair/scan.c:633 .././repair/scan.c:734 .././repair/scan.c:1008 #: .././repair/scan.c:1152 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w bt%s, blok %u/%u\n" #: .././repair/scan.c:651 .././repair/scan.c:1043 .././repair/scan.c:1329 #, c-format msgid "invalid start block %u in record %u of %s btree block %u/%u\n" msgstr "błędny blok poczÄ…tkowy %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:657 .././repair/scan.c:1049 .././repair/scan.c:1335 #, c-format msgid "invalid length %u in record %u of %s btree block %u/%u\n" msgstr "błędna dÅ‚ugość %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:704 #, c-format msgid "block (%d,%d-%d) multiply claimed by %s space tree, state - %d\n" msgstr "" "blok (%d,%d-%d) wielokrotnie przypisany do drzewa miejsca %s, stan - %d\n" #: .././repair/scan.c:833 #, fuzzy, c-format msgid "" "Static meta block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" "blok (%d,%d-%d) wielokrotnie przypisany do drzewa miejsca %s, stan - %d\n" #: .././repair/scan.c:842 #, fuzzy, c-format msgid "AG meta block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" "blok (%d,%d-%d) wielokrotnie przypisany do drzewa miejsca %s, stan - %d\n" #: .././repair/scan.c:850 #, fuzzy, c-format msgid "inode block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" "blok (%d,%d-%d) wielokrotnie przypisany do drzewa miejsca %s, stan - %d\n" #: .././repair/scan.c:858 #, fuzzy, c-format msgid "" "AG refcount block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" "blok (%d,%d-%d) wielokrotnie przypisany do drzewa miejsca %s, stan - %d\n" #: .././repair/scan.c:867 #, fuzzy, c-format msgid "in use block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" "blok (%d,%d-%d) wielokrotnie przypisany do drzewa miejsca %s, stan - %d\n" #: .././repair/scan.c:889 #, fuzzy, c-format msgid "unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%\n" msgstr "" "blok (%d,%d-%d) wielokrotnie przypisany do drzewa miejsca %s, stan - %d\n" #: .././repair/scan.c:989 #, fuzzy, c-format msgid "%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "blok b-drzewa wolnego miejsca %s przypisany (stan %d), agno %d, bno %d, " "podejrzany %d\n" #: .././repair/scan.c:1033 #, fuzzy, c-format msgid "invalid flags in record %u of %s btree block %u/%u\n" msgstr "błędna dÅ‚ugość %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:1062 #, fuzzy, c-format msgid "invalid owner in rmap btree record %d (% %u) block %u/%u\n" msgstr "rekord b-drzewa bno poza kolejnoÅ›ciÄ…: %d (%u %u), blok %u/%u\n" #: .././repair/scan.c:1069 #, c-format msgid "" "record %d of block (%u/%u) in %s btree cannot have non-inode owner with " "flags\n" msgstr "" #: .././repair/scan.c:1073 #, c-format msgid "" "record %d of block (%u/%u) in %s btree cannot have non-inode owner with " "offset\n" msgstr "" #: .././repair/scan.c:1094 #, fuzzy, c-format msgid "" "out-of-order rmap btree record %d (%u % % %u) block %u/%u\n" msgstr "rekord b-drzewa bno poza kolejnoÅ›ciÄ…: %d (%u %u), blok %u/%u\n" #: .././repair/scan.c:1103 .././repair/scan.c:1381 #, c-format msgid "" "record %d in block (%u/%u) of %s tree should be merged with previous record\n" msgstr "" #: .././repair/scan.c:1118 #, c-format msgid "record %d greater than high key of block (%u/%u) in %s tree\n" msgstr "" #: .././repair/scan.c:1174 #, fuzzy, c-format msgid "invalid flags in key %u of %s btree block %u/%u\n" msgstr "błędna dÅ‚ugość %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:1180 #, c-format msgid "key %d greater than high key of block (%u/%u) in %s tree\n" msgstr "" #: .././repair/scan.c:1206 #, fuzzy, c-format msgid "invalid flags in high key %u of %s btree block %u/%u\n" msgstr "błędna dÅ‚ugość %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:1257 #, fuzzy, c-format msgid "bad magic # %#x in %s btree block %d/%d\n" msgstr "błędna liczba magiczna %#x w bloku bt%s %d/%d\n" #: .././repair/scan.c:1265 #, fuzzy, c-format msgid "expected level %d got %d in %s btree block %d/%d\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku bt%s %d/%d\n" #: .././repair/scan.c:1279 #, fuzzy, c-format msgid "%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "blok b-drzewa i-wÄ™złów przypisany (stan %d), agno %d, bno %d, podejrzany %d\n" #: .././repair/scan.c:1298 .././repair/scan.c:1415 #, fuzzy, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n" msgstr "" "błędna liczba rekordów b-drzewa (%u, min=%u, max=%u) w bt%s, blok %u/%u\n" #: .././repair/scan.c:1316 #, fuzzy, c-format msgid "" "leftover CoW extent has incorrect refcount in record %u of %s btree block %u/" "%u\n" msgstr "błędna dÅ‚ugość %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:1321 #, fuzzy, c-format msgid "" "leftover CoW extent has invalid startblock in record %u of %s btree block %u/" "%u\n" msgstr "błędny blok poczÄ…tkowy %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:1356 #, c-format msgid "extent (%u/%u) len %u claimed, state is %d\n" msgstr "" #: .././repair/scan.c:1363 #, fuzzy, c-format msgid "invalid reference count %u in record %u of %s btree block %u/%u\n" msgstr "błędna dÅ‚ugość %u w rekordzie %u bloku b-drzewa %s %u/%u\n" #: .././repair/scan.c:1370 #, fuzzy, c-format msgid "out-of-order %s btree record %d (%u %u) block %u/%u\n" msgstr "rekord b-drzewa bno poza kolejnoÅ›ciÄ…: %d (%u %u), blok %u/%u\n" #: .././repair/scan.c:1496 #, fuzzy, c-format msgid "badly aligned %s rec (starting inode = %)\n" msgstr "błędnie wyrównany rekord i-wÄ™zÅ‚a (poczÄ…tkowy i-wÄ™zeÅ‚ = %)\n" #: .././repair/scan.c:1510 #, fuzzy, c-format msgid "bad starting inode # (% (0x%x 0x%x)) in %s rec, skipping rec\n" msgstr "" "błędny numer poczÄ…tkowego i-wÄ™zÅ‚a (% (0x%x 0x%x)) w rekordzie i-" "wÄ™zÅ‚a, pominiÄ™to rekord\n" #: .././repair/scan.c:1519 #, fuzzy, c-format msgid "bad ending inode # (% (0x%x 0x%zx)) in %s rec, skipping rec\n" msgstr "" "błędny numer koÅ„cowego i-wÄ™zÅ‚a (% (0x%x 0x%zx)) w rekordzie i-wÄ™zÅ‚a, " "pominiÄ™to rekord\n" #: .././repair/scan.c:1584 #, fuzzy, c-format msgid "" "ir_holemask/ir_free mismatch, %s chunk %d/%u, holemask 0x%x free 0x%llx\n" msgstr "" "niezgodność ir_freecount/free, porcja i-wÄ™złów %d/%u, freecount %d nfree %d\n" #: .././repair/scan.c:1671 #, c-format msgid "" "inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n" msgstr "" "część i-wÄ™zÅ‚a odwoÅ‚uje siÄ™ do używanego bloku, blok inobt - agno %d, bno %d, " "inopb %d\n" #: .././repair/scan.c:1689 #, c-format msgid "" "inode rec for ino % (%d/%d) overlaps existing rec (start %d/%d)\n" msgstr "" "rekord i-wÄ™zÅ‚a dla i-wÄ™zÅ‚a % (%d/%d) nachodzi na istniejÄ…cy rekord " "(poczÄ…tek %d/%d)\n" #: .././repair/scan.c:1713 #, c-format msgid "ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n" msgstr "" "niezgodność ir_freecount/free, porcja i-wÄ™złów %d/%u, freecount %d nfree %d\n" #: .././repair/scan.c:1721 .././repair/scan.c:1911 #, fuzzy, c-format msgid "invalid inode count, inode chunk %d/%u, count %d ninodes %d\n" msgstr "" "niezgodność finobt ir_freecount/free, porcja i-wÄ™złów %d/%u, freecount %d " "nfree %d\n" #: .././repair/scan.c:1775 #, fuzzy, c-format msgid "" "sparse inode chunk claims inode block, finobt block - agno %d, bno %d, inopb " "%d\n" msgstr "" "część i-wÄ™zÅ‚a odwoÅ‚uje siÄ™ do używanego bloku, blok finobt - agno %d, bno " "%d, inopb %d\n" #: .././repair/scan.c:1790 .././repair/scan.c:1802 #, c-format msgid "" "inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb " "%d\n" msgstr "" "część i-wÄ™zÅ‚a odwoÅ‚uje siÄ™ do nieÅ›ledzonego bloku, blok finobt - agno %d, " "bno %d, inopb %d\n" #: .././repair/scan.c:1812 #, c-format msgid "" "inode chunk claims used block, finobt block - agno %d, bno %d, inopb %d\n" msgstr "" "część i-wÄ™zÅ‚a odwoÅ‚uje siÄ™ do używanego bloku, blok finobt - agno %d, bno " "%d, inopb %d\n" #: .././repair/scan.c:1834 #, c-format msgid "" "finobt rec for ino % (%d/%u) does not match existing rec (%d/%d)\n" msgstr "" "rekord finobt dla i-wÄ™zÅ‚a % (%d/%u) nie pasuje do istniejÄ…cego " "rekordu (%d/%d)\n" #: .././repair/scan.c:1876 #, c-format msgid "undiscovered finobt record, ino % (%d/%u)\n" msgstr "nie rozpoznany rekord finobt, i-wÄ™zeÅ‚ % (%d/%u)\n" #: .././repair/scan.c:1898 #, c-format msgid "" "finobt ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n" msgstr "" "niezgodność finobt ir_freecount/free, porcja i-wÄ™złów %d/%u, freecount %d " "nfree %d\n" #: .././repair/scan.c:1904 #, c-format msgid "finobt record with no free inodes, inode chunk %d/%u\n" msgstr "rekord finobt bez wolnych i-wÄ™złów, porcja i-wÄ™złów %d/%u\n" #: .././repair/scan.c:1957 #, c-format msgid "bad magic # %#x in inobt block %d/%d\n" msgstr "błędna liczba magiczna %#x w bloku inobt %d/%d\n" #: .././repair/scan.c:1965 #, c-format msgid "expected level %d got %d in inobt block %d/%d\n" msgstr "oczekiwano poziomu %d, a uzyskano %d w bloku inobt %d/%d\n" #: .././repair/scan.c:1988 #, c-format msgid "inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" "blok b-drzewa i-wÄ™złów przypisany (stan %d), agno %d, bno %d, podejrzany %d\n" #: .././repair/scan.c:2011 #, c-format msgid "dubious inode btree block header %d/%d\n" msgstr "wÄ…tpliwy nagłówek bloku b-drzewa i-wÄ™złów %d/%d\n" #: .././repair/scan.c:2129 #, c-format msgid "can't read agfl block for ag %d\n" msgstr "nie można odczytać bloku agfl dla ag %d\n" #: .././repair/scan.c:2133 #, c-format msgid "agfl has bad CRC for ag %d\n" msgstr "agfl ma błędnÄ… sumÄ™ kontrolnÄ… dla ag %d\n" #: .././repair/scan.c:2154 #, c-format msgid "bad agbno %u in agfl, agno %d\n" msgstr "błędne agbno %u w agfl, agno %d\n" #: .././repair/scan.c:2163 #, c-format msgid "freeblk count %d != flcount %d in ag %d\n" msgstr "liczba freeblk %d != flcount %d w ag %d\n" #: .././repair/scan.c:2189 #, c-format msgid "bad agbno %u for btbno root, agno %d\n" msgstr "błędne agbno %u dla głównego btbno, agno %d\n" #: .././repair/scan.c:2201 #, c-format msgid "bad agbno %u for btbcnt root, agno %d\n" msgstr "błędne agbno %u dla głównego btbcnt, agno %d\n" #: .././repair/scan.c:2220 #, fuzzy, c-format msgid "bad rmapbt block count %u, saw %u\n" msgstr "błędna liczba bloków dla blockuse: %s\n" #: .././repair/scan.c:2224 #, fuzzy, c-format msgid "bad agbno %u for rmapbt root, agno %d\n" msgstr "błędne agbno %u dla głównego inobt, agno %d\n" #: .././repair/scan.c:2241 #, fuzzy, c-format msgid "bad refcountbt block count %u, saw %u\n" msgstr "błędna liczba bloków dla blockuse: %s\n" #: .././repair/scan.c:2245 #, fuzzy, c-format msgid "bad agbno %u for refcntbt root, agno %d\n" msgstr "błędne agbno %u dla głównego finobt, agno %d\n" #: .././repair/scan.c:2263 #, c-format msgid "agf_btreeblks %u, counted % in ag %u\n" msgstr "agf_btreeblks %u, naliczono % w ag %u\n" #: .././repair/scan.c:2287 #, c-format msgid "bad agbno %u for inobt root, agno %d\n" msgstr "błędne agbno %u dla głównego inobt, agno %d\n" #: .././repair/scan.c:2300 #, c-format msgid "bad agbno %u for finobt root, agno %d\n" msgstr "błędne agbno %u dla głównego finobt, agno %d\n" #: .././repair/scan.c:2317 #, c-format msgid "agi_freecount %u, counted %u in ag %u finobt\n" msgstr "agi_freecount %u, naliczono %u w ag %u finobt\n" #: .././repair/scan.c:2327 #, c-format msgid "agi unlinked bucket %d is %u in ag %u (inode=%)\n" msgstr "niedowiÄ…zany kubeÅ‚ek agi %d to %u w ag %u (i-wÄ™zeÅ‚=%)\n" #: .././repair/scan.c:2358 msgid "can't allocate memory for superblock\n" msgstr "nie można przydzielić pamiÄ™ci dla superbloku\n" #: .././repair/scan.c:2365 msgid "root superblock" msgstr "główny superblok" #: .././repair/scan.c:2374 msgid "agf block" msgstr "blok agf" #: .././repair/scan.c:2383 msgid "agi block" msgstr "blok agi" #: .././repair/scan.c:2404 #, c-format msgid "reset bad sb for ag %d\n" msgstr "przestawiono błędny superblok dla ag %d\n" #: .././repair/scan.c:2407 #, c-format msgid "would reset bad sb for ag %d\n" msgstr "błędny superblok dla ag %d zostaÅ‚by przestawiony\n" #: .././repair/scan.c:2412 #, c-format msgid "reset bad agf for ag %d\n" msgstr "przestawiono błędne agf dla ag %d\n" #: .././repair/scan.c:2415 #, c-format msgid "would reset bad agf for ag %d\n" msgstr "błędne agf dla ag %d zostaÅ‚oby przestawione\n" #: .././repair/scan.c:2420 #, c-format msgid "reset bad agi for ag %d\n" msgstr "przestawiono błędne agi dla ag %d\n" #: .././repair/scan.c:2423 #, c-format msgid "would reset bad agi for ag %d\n" msgstr "błędna agi dla ag %d zostaÅ‚oby przestawione\n" #: .././repair/scan.c:2428 #, c-format msgid "bad uncorrected agheader %d, skipping ag...\n" msgstr "błędny nie poprawiony agheader %d, pominiÄ™to ag...\n" #: .././repair/scan.c:2491 #, c-format msgid "can't get %s for ag %d\n" msgstr "nie można uzyskać %s dla ag %d\n" #: .././repair/scan.c:2511 msgid "no memory for ag header counts\n" msgstr "brak pamiÄ™ci na liczniki nagłówków ag\n" #: .././repair/scan.c:2537 #, c-format msgid "sb_icount %, counted %\n" msgstr "sb_icount %, naliczono %\n" #: .././repair/scan.c:2542 #, c-format msgid "sb_ifree %, counted %\n" msgstr "sb_ifree %, naliczono %\n" #: .././repair/scan.c:2547 #, c-format msgid "sb_fdblocks %, counted %\n" msgstr "sb_fdblocks %, naliczono %\n" #: .././repair/scan.c:2553 #, fuzzy, c-format msgid "used blocks %, counted %\n" msgstr "sb_fdblocks %, naliczono %\n" #: .././repair/threads.c:90 #, c-format msgid "cannot create worker threads, error = [%d] %s\n" msgstr "nie można utworzyć wÄ…tków pracujÄ…cych, błąd: [%d] %s\n" #: .././repair/threads.c:108 #, c-format msgid "cannot allocate worker item, error = [%d] %s\n" msgstr "nie można przydzielić elementu pracujÄ…cego, błąd: [%d] %s\n" #: .././repair/versions.c:68 #, c-format msgid "bogus quota flags 0x%x set in superblock" msgstr "niepoprawne flagi limitów 0x%x ustawione w superbloku" #: .././repair/versions.c:74 msgid ", bogus flags will be cleared\n" msgstr ", błędne flagi zostanÄ… wyczyszczone\n" #: .././repair/versions.c:76 msgid ", bogus flags would be cleared\n" msgstr ", błędne flagi zostaÅ‚yby wyczyszczone\n" #: .././repair/versions.c:115 .././repair/versions.c:120 #: .././repair/versions.c:125 msgid "Shared Version bit set. Not supported. Ever.\n" msgstr "" #: .././repair/versions.c:138 msgid "This filesystem has uninitialized extent flags.\n" msgstr "Ten system plików ma niezainicjowane flagi ekstentów.\n" #: .././repair/versions.c:144 msgid "" "This filesystem uses feature(s) not yet supported in this release.\n" "Please run a more recent version of xfs_repair.\n" msgstr "" "Ten system plików używa możliwoÅ›ci jeszcze nie obsÅ‚ugiwanych w tym wydaniu.\n" "ProszÄ™ uruchomić nowszÄ… wersjÄ™ xfs_repair.\n" #: .././repair/versions.c:150 #, c-format msgid "WARNING: unknown superblock version %d\n" msgstr "UWAGA: nieznana wersja superbloku %d\n" #: .././repair/versions.c:153 msgid "This filesystem contains features not understood by this program.\n" msgstr "Ten system plików zawiera cechÄ™ nie rozumianÄ… przez ten program.\n" #: .././repair/versions.c:161 msgid "" "WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twill be downgraded. This may cause loss of filesystem meta-data\n" msgstr "" "UWAGA: zabroniono superblock-feature-bits-allowed, ale ten\n" "\tsuperblok ma ustawione bity cech. Superblok zostanie zdegradowany.\n" "\tMoże to spowodować utratÄ™ metadanych systemu plików.\n" #: .././repair/versions.c:166 msgid "" "WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twould be downgraded. This might cause loss of filesystem\n" "\tmeta-data.\n" msgstr "" "UWAGA: zabroniono superblock-feature-bits-allowed, ale ten\n" "\tsuperblok ma ustawione bity cech. Superblok zostaÅ‚by zdegradowany.\n" "\tMogÅ‚oby to spowodować utratÄ™ metadanych systemu plików.\n" #: .././repair/versions.c:182 #, c-format msgid "" "Superblock has unknown compat/rocompat/incompat features (0x%x/0x%x/0x%x).\n" "Using a more recent xfs_repair is recommended.\n" msgstr "" #: .././repair/versions.c:194 msgid "" "WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attributes will be removed.\n" msgstr "" "UWAGA: zabroniono używania atrybutów, ale ten system plików zawiera\n" "\tatrybuty. System plików zostanie zdegradowany, a wszystkie\n" "\tatrybuty usuniÄ™te.\n" #: .././repair/versions.c:199 msgid "" "WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attributes would be removed.\n" msgstr "" "UWAGA: zabroniono używania atrybutów, ale ten system plików zawiera\n" "\tatrybuty. System plików zostaÅ‚by zdegradowany, a wszystkie\n" "\tatrybuty usuniÄ™te.\n" #: .././repair/versions.c:212 msgid "" "WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attr2 attributes will be removed.\n" msgstr "" "UWAGA: zabroniono używania atrybutów attr2, ale ten system plików\n" "\tzawiera atrybuty. System plików zostanie zdegradowany, a wszystkie\n" "\tatrybuty attr2 usuniÄ™te.\n" #: .././repair/versions.c:217 msgid "" "WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attr2 attributes would be removed.\n" msgstr "" "UWAGA: zabroniono używania atrybutów attr2, ale ten system plików\n" "\tzawiera atrybuty. System plików zostaÅ‚by zdegradowany, a wszystkie\n" "\tatrybuty attr2 usuniÄ™te.\n" #: .././repair/versions.c:229 msgid "" "WARNING: you have a V1 inode filesystem. It will be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././repair/versions.c:234 msgid "" "WARNING: you have a V1 inode filesystem. It would be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././repair/versions.c:244 msgid "" "WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem will be downgraded and\n" "\tall quota information will be removed.\n" msgstr "" "UWAGA: zabroniono używania limitów (quot), ale ten system plików\n" "\tzawiera limity. System plików zostanie zdegradowany, a wszystkie\n" "\tinformacje o limitach usuniÄ™te.\n" #: .././repair/versions.c:249 msgid "" "WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem would be downgraded and\n" "\tall quota information would be removed.\n" msgstr "" "UWAGA: zabroniono używania limitów (quot), ale ten system plików\n" "\tzawiera limity. System plików zostaÅ‚by zdegradowany, a wszystkie\n" "\tinformacje o limitach usuniÄ™te.\n" #: .././repair/versions.c:277 msgid "" "WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem will be downgraded.\n" "\tThis will permanently degrade the performance of this filesystem.\n" msgstr "" "UWAGA: zabroniono używania wyrównanych i-wÄ™złów, ale ten system plików\n" "\tzawiera wyrównane i-wÄ™zÅ‚y. System plików zostanie zdegradowany.\n" "\tTrwale zdegraduje to wydajność tego systemu plików.\n" #: .././repair/versions.c:282 msgid "" "WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem would be downgraded.\n" "\tThis would permanently degrade the performance of this filesystem.\n" msgstr "" "UWAGA: zabroniono używania wyrównanych i-wÄ™złów, ale ten system plików\n" "\tzawiera wyrównane i-wÄ™zÅ‚y. System plików zostaÅ‚by zdegradowany.\n" "\tTrwale zdegradowaÅ‚oby to wydajność tego systemu plików.\n" #: .././repair/xfs_repair.c:85 #, c-format msgid "" "Usage: %s [options] device\n" "\n" "Options:\n" " -f The device is a file\n" " -L Force log zeroing. Do this as a last resort.\n" " -l logdev Specifies the device where the external log resides.\n" " -m maxmem Maximum amount of memory to be used in megabytes.\n" " -n No modify mode, just checks the filesystem for damage.\n" " -P Disables prefetching.\n" " -r rtdev Specifies the device where the realtime section resides.\n" " -v Verbose output.\n" " -c subopts Change filesystem parameters - use xfs_admin.\n" " -o subopts Override default behaviour, refer to man page.\n" " -t interval Reporting interval in seconds.\n" " -d Repair dangerously.\n" " -V Reports version and exits.\n" msgstr "" "SkÅ‚adnia: %s [opcje] urzÄ…dzenie\n" "\n" "Opcje:\n" " -f UrzÄ…dzenie jest plikiem\n" " -L Wymuszenie wyzerowania logu. Wykonywać tylko w " "ostatecznoÅ›ci.\n" " -l urz_logu OkreÅ›lenie urzÄ…dzenia z zewnÄ™trznym logiem.\n" " -m maks_pam Maksymalna ilość pamiÄ™ci do użycia w megabajtach.\n" " -n Tryb bez modyfikacji, tylko sprawdzenie systemu plików.\n" " -P Wyłączenie prefetch.\n" " -r urz_rt OkreÅ›lenie urzÄ…dzenia z sekcjÄ… realtime.\n" " -v Szczegółowe wyjÅ›cie.\n" " -c podopcje Zmiana parametrów systemu plików przy użyciu xfs_admina.\n" " -o podopcje Zmiana domyÅ›lnego zachowania, wiÄ™cej na stronie manuala.\n" " -t czas Okres informowania o postÄ™pach w minutach.\n" " -d Naprawianie w sposób niebezpieczny.\n" " -V Wypisanie informacji o wersji i zakoÅ„czenie.\n" #: .././repair/xfs_repair.c:111 msgid "no error" msgstr "brak błędu" #: .././repair/xfs_repair.c:112 msgid "bad magic number" msgstr "błędna liczba magiczna" #: .././repair/xfs_repair.c:113 msgid "bad blocksize field" msgstr "błędne pole blocksize" #: .././repair/xfs_repair.c:114 msgid "bad blocksize log field" msgstr "błędne pole logu blocksize" #: .././repair/xfs_repair.c:115 msgid "bad or unsupported version" msgstr "błędna lub nie obsÅ‚ugiwana wersja" #: .././repair/xfs_repair.c:117 msgid "filesystem mkfs-in-progress bit set" msgstr "ustawiony bit mkfs-in-progress systemu plików" #: .././repair/xfs_repair.c:119 msgid "inconsistent filesystem geometry information" msgstr "niespójne informacje o geometrii systemu plików" #: .././repair/xfs_repair.c:121 msgid "bad inode size or inconsistent with number of inodes/block" msgstr "błędny rozmiar i-wÄ™zÅ‚a lub niespójność z liczbÄ… i-wÄ™złów/blok" #: .././repair/xfs_repair.c:122 msgid "bad sector size" msgstr "błędny rozmiar sektora" #: .././repair/xfs_repair.c:124 msgid "AGF geometry info conflicts with filesystem geometry" msgstr "informacje o geometrii AGF sÄ… w konflikcie z geometriÄ… systemu plików" #: .././repair/xfs_repair.c:126 msgid "AGI geometry info conflicts with filesystem geometry" msgstr "informacje o geometrii AGI sÄ… w konflikcie z geometriÄ… systemu plików" #: .././repair/xfs_repair.c:128 msgid "AG superblock geometry info conflicts with filesystem geometry" msgstr "" "informacje o geometrii superbloku AG sÄ… w konflikcie z geometriÄ… systemu " "plików" #: .././repair/xfs_repair.c:129 msgid "attempted to perform I/O beyond EOF" msgstr "próbowano wykonać operacjÄ™ we/wy poza koÅ„cem pliku" #: .././repair/xfs_repair.c:131 msgid "inconsistent filesystem geometry in realtime filesystem component" msgstr "niespójna geometria systemu plików w skÅ‚adniku realtime" #: .././repair/xfs_repair.c:133 msgid "maximum indicated percentage of inodes > 100%" msgstr "okreÅ›lono maksymalny procent i-wÄ™złów > 100%" #: .././repair/xfs_repair.c:135 msgid "inconsistent inode alignment value" msgstr "niespójna wartość wyrównania i-wÄ™zÅ‚a" #: .././repair/xfs_repair.c:137 msgid "not enough secondary superblocks with matching geometry" msgstr "za maÅ‚o zapasowych superbloków o pasujÄ…cej geometrii" #: .././repair/xfs_repair.c:139 msgid "bad stripe unit in superblock" msgstr "błędna jednostka pasa w superbloku" #: .././repair/xfs_repair.c:141 msgid "bad stripe width in superblock" msgstr "błędna szerokość pasa w superbloku" #: .././repair/xfs_repair.c:143 msgid "bad shared version number in superblock" msgstr "błędny numer wersji współdzielenia w superbloku" #: .././repair/xfs_repair.c:145 msgid "bad CRC in superblock" msgstr "błędna suma kontrolna w superbloku" #: .././repair/xfs_repair.c:150 #, c-format msgid "bad error code - %d\n" msgstr "błędny kod błędu - %d\n" #: .././repair/xfs_repair.c:158 #, c-format msgid "-%c %s option cannot have a value\n" msgstr "opcja -%c %s nie przyjmuje wartoÅ›ci\n" #: .././repair/xfs_repair.c:248 msgid "-o ihash option has been removed and will be ignored\n" msgstr "opcja -o ihash zostaÅ‚a usuniÄ™ta i zostanie zignorowana\n" #: .././repair/xfs_repair.c:253 msgid "-o bhash option cannot be used with -m option\n" msgstr "opcja -o bhash nie może być użyta wraz z opcjÄ… -m\n" #: .././repair/xfs_repair.c:305 msgid "-m option cannot be used with -o bhash option\n" msgstr "opcja -m nie może być użyta wraz z opcjÄ… -o bhash\n" #: .././repair/xfs_repair.c:347 #, c-format msgid "" "\n" "fatal error -- " msgstr "" "\n" "błąd krytyczny - " #: .././repair/xfs_repair.c:474 #, c-format msgid "sb root inode value % %sinconsistent with calculated value %u\n" msgstr "" "wartość i-wÄ™zÅ‚a głównego superbloku % %sniespójna z obliczonÄ… " "wartoÅ›ciÄ… %u\n" #: .././repair/xfs_repair.c:481 #, c-format msgid "resetting superblock root inode pointer to %u\n" msgstr "przestawiono wskaźnik i-wÄ™zÅ‚a głównego superbloku na %u\n" #: .././repair/xfs_repair.c:485 #, c-format msgid "would reset superblock root inode pointer to %u\n" msgstr "wskaźnik i-wÄ™zÅ‚a głównego superbloku zostaÅ‚by przestawiony na %u\n" #: .././repair/xfs_repair.c:497 #, c-format msgid "" "sb realtime bitmap inode % %sinconsistent with calculated value %u\n" msgstr "" "i-wÄ™zeÅ‚ bitmapy realtime superbloku % %sniespójny z obliczonÄ… " "wartoÅ›ciÄ… %u\n" #: .././repair/xfs_repair.c:504 #, c-format msgid "resetting superblock realtime bitmap ino pointer to %u\n" msgstr "przestawiono wskaźnik i-wÄ™zÅ‚a bitmapy realtime superbloku na %u\n" #: .././repair/xfs_repair.c:508 #, c-format msgid "would reset superblock realtime bitmap ino pointer to %u\n" msgstr "" "wskaźnik i-wÄ™zÅ‚a bitmapy realtime superbloku zostaÅ‚by przestawiony na %u\n" #: .././repair/xfs_repair.c:520 #, c-format msgid "" "sb realtime summary inode % %sinconsistent with calculated value %u\n" msgstr "" "i-wÄ™zeÅ‚ opisu realtime superbloku % %sniespójny z obliczonÄ… " "wartoÅ›ciÄ… %u\n" #: .././repair/xfs_repair.c:527 #, c-format msgid "resetting superblock realtime summary ino pointer to %u\n" msgstr "przestawiono wskaźnik i-wÄ™zÅ‚a opisu realtime superbloku na %u\n" #: .././repair/xfs_repair.c:531 #, c-format msgid "would reset superblock realtime summary ino pointer to %u\n" msgstr "" "wskaźnik i-wÄ™zÅ‚a opisu realtime superbloku zostaÅ‚by przestawiony na %u\n" #: .././repair/xfs_repair.c:587 #, c-format msgid "Maximum metadata LSN (%d:%d) is ahead of log (%d:%d).\n" msgstr "" #: .././repair/xfs_repair.c:591 #, c-format msgid "Would format log to cycle %d.\n" msgstr "" #: .././repair/xfs_repair.c:595 #, c-format msgid "Format log to cycle %d.\n" msgstr "" #: .././repair/xfs_repair.c:663 msgid "" "Primary superblock would have been modified.\n" "Cannot proceed further in no_modify mode.\n" "Exiting now.\n" msgstr "" "Główny superblok zostaÅ‚by zmodyfikowany.\n" "Nie można kontynuować w trybie bez modyfikacji.\n" "ZakoÅ„czono.\n" #: .././repair/xfs_repair.c:671 msgid "" "Primary superblock bad after phase 1!\n" "Exiting now.\n" msgstr "" "NieprawidÅ‚owy główny superblok po fazie 1!\n" "Koniec dziaÅ‚ania.\n" #: .././repair/xfs_repair.c:682 #, fuzzy, c-format msgid "%s: couldn't stat \"%s\"\n" msgstr "%s: nie udaÅ‚o siÄ™ wykonać stat na źródle \"%s\"\n" #: .././repair/xfs_repair.c:699 msgid "" "Cannot get host filesystem geometry.\n" "Repair may fail if there is a sector size mismatch between\n" "the image and the host filesystem.\n" msgstr "" "Nie można pobrać geometrii systemu plików hosta.\n" "Naprawienie może siÄ™ nie powieść, jeÅ›li istnieje niespójność rozmiaru\n" "sektora miÄ™dzy obrazem a systemem plików hosta.\n" #: .././repair/xfs_repair.c:711 msgid "" "Sector size on host filesystem larger than image sector size.\n" "Cannot turn off direct IO, so exiting.\n" msgstr "" "Rozmiar sektora na systemie plików hosta wiÄ™kszy niż rozmiar sektora " "obrazu.\n" "Nie można wyłączyć bezpoÅ›redniego we/wy - zakoÅ„czono dziaÅ‚anie.\n" #: .././repair/xfs_repair.c:728 #, c-format msgid "%s: cannot repair this filesystem. Sorry.\n" msgstr "%s: niestety nie można naprawić tego systemu plików.\n" #: .././repair/xfs_repair.c:804 #, c-format msgid " - reporting progress in intervals of %s\n" msgstr " - informowanie o postÄ™pie w odstÄ™pach %s\n" #: .././repair/xfs_repair.c:849 #, c-format msgid "" " - max_mem = %lu, icount = %, imem = %, dblock = " "%, dmem = %\n" msgstr "" " - max_mem = %lu, icount = %, imem = %, dblock = " "%, dmem = %\n" #: .././repair/xfs_repair.c:858 #, c-format msgid "" "Required memory for repair is greater that the maximum specified\n" "with the -m option. Please increase it to at least %lu.\n" msgstr "" "Pamięć wymagana do naprawy przekracza maksimum okreÅ›lone opcjÄ… -m.\n" "ProszÄ™ jÄ… zwiÄ™kszyć do co najmniej %lu.\n" #: .././repair/xfs_repair.c:863 #, c-format msgid "" "Memory available for repair (%luMB) may not be sufficient.\n" "At least %luMB is needed to repair this filesystem efficiently\n" "If repair fails due to lack of memory, please\n" msgstr "" "Pamięć dostÄ™pna przy naprawie (%luMB) może nie być wystarczajÄ…ca.\n" "Aby wydajnie naprawić ten system plików, niezbÄ™dne jest co najmniej %luMB.\n" "JeÅ›li naprawa nie powiedzie siÄ™ z powodu braku pamiÄ™ci, proszÄ™\n" #: .././repair/xfs_repair.c:869 msgid "turn prefetching off (-P) to reduce the memory footprint.\n" msgstr "wyłączyć prefetch (-P), aby zmniejszyć zużycie pamiÄ™ci.\n" #: .././repair/xfs_repair.c:872 #, c-format msgid "increase system RAM and/or swap space to at least %luMB.\n" msgstr "" "proszÄ™ rozszerzyć rozmiar RAM systemu i/lub przestrzeni wymiany do co " "najmniej %luMB.\n" #: .././repair/xfs_repair.c:887 #, c-format msgid " - block cache size set to %d entries\n" msgstr " - rozmiar bufora bloku ustawiony na %d wpisów\n" #: .././repair/xfs_repair.c:912 msgid "Found unsupported filesystem features. Exiting now.\n" msgstr "Znaleziono nie obsÅ‚ugiwane cechy systemu plików. ZakoÅ„czono.\n" #: .././repair/xfs_repair.c:930 #, c-format msgid "No modify flag set, skipping phase 5\n" msgstr "Ustawiono flagÄ™ braku modyfikacji, pominiÄ™to fazÄ™ 5\n" #: .././repair/xfs_repair.c:950 msgid "Inode allocation btrees are too corrupted, skipping phases 6 and 7\n" msgstr "B-drzewa alokacji i-wÄ™złów sÄ… zbyt uszkodzone, pominiÄ™to fazy 6 i 7\n" #: .././repair/xfs_repair.c:956 msgid "Warning: no quota inodes were found. Quotas disabled.\n" msgstr "Uwaga: nie znaleziono i-wÄ™złów limitów (quot). Limity wyłączone.\n" #: .././repair/xfs_repair.c:959 msgid "Warning: no quota inodes were found. Quotas would be disabled.\n" msgstr "" "Uwaga: nie znaleziono i-wÄ™złów limitów (quot). Limity zostaÅ‚yby wyłączone.\n" #: .././repair/xfs_repair.c:964 msgid "Warning: quota inodes were cleared. Quotas disabled.\n" msgstr "Uwaga: i-wÄ™zÅ‚y limitów (quot) byÅ‚y wyczyszczone. Limity wyłączone.\n" #: .././repair/xfs_repair.c:967 msgid "Warning: quota inodes would be cleared. Quotas would be disabled.\n" msgstr "" "Uwaga: i-wÄ™zÅ‚y limitów (quot) zostaÅ‚yby wyczyszczone. Limity zostaÅ‚yby " "wyłączone.\n" #: .././repair/xfs_repair.c:973 msgid "" "Warning: user quota information was cleared.\n" "User quotas can not be enforced until limit information is recreated.\n" msgstr "" "Uwaga: informacje o limitach użytkowników byÅ‚y wyczyszczone.\n" "Limity użytkowników nie mogÄ… być wymuszone do czasu odtworzenia informacji.\n" #: .././repair/xfs_repair.c:977 msgid "" "Warning: user quota information would be cleared.\n" "User quotas could not be enforced until limit information was recreated.\n" msgstr "" "Uwaga: informacje o limitach użytkowników zostaÅ‚yby wyczyszczone.\n" "Limity użytkowników nie mogÅ‚yby być wymuszone do czasu odtworzenia " "informacji.\n" #: .././repair/xfs_repair.c:985 msgid "" "Warning: group quota information was cleared.\n" "Group quotas can not be enforced until limit information is recreated.\n" msgstr "" "Uwaga: informacje o limitach grup byÅ‚y wyczyszczone.\n" "Limity grup nie mogÄ… być wymuszone do czasu odtworzenia informacji.\n" #: .././repair/xfs_repair.c:989 msgid "" "Warning: group quota information would be cleared.\n" "Group quotas could not be enforced until limit information was recreated.\n" msgstr "" "Uwaga: informacje o limitach grup zostaÅ‚yby wyczyszczone.\n" "Limity grup nie mogÅ‚yby być wymuszone do czasu odtworzenia informacji.\n" #: .././repair/xfs_repair.c:997 msgid "" "Warning: project quota information was cleared.\n" "Project quotas can not be enforced until limit information is recreated.\n" msgstr "" "Uwaga: informacje o limitach projektów byÅ‚y wyczyszczone.\n" "Limity projektów nie mogÄ… być wymuszone do czasu odtworzenia informacji.\n" #: .././repair/xfs_repair.c:1001 msgid "" "Warning: project quota information would be cleared.\n" "Project quotas could not be enforced until limit information was recreated.\n" msgstr "" "Uwaga: informacje o limitach projektów zostaÅ‚yby wyczyszczone.\n" "Limity projektów nie mogÅ‚yby być wymuszone do czasu odtworzenia informacji.\n" #: .././repair/xfs_repair.c:1018 msgid "No modify flag set, skipping filesystem flush and exiting.\n" msgstr "" "Flaga braku modyfikacji ustawiona, pominiÄ™to zrzucanie systemu plików, " "zakoÅ„czono.\n" #: .././repair/xfs_repair.c:1037 msgid "Note - quota info will be regenerated on next quota mount.\n" msgstr "" "Uwaga - informacje o limitach zostanÄ… ponownie wygenerowane przy nastÄ™pnym " "montowaniu.\n" #: .././repair/xfs_repair.c:1044 #, fuzzy, c-format msgid "" "Note - stripe unit (%d) and width (%d) were copied from a backup " "superblock.\n" "Please reset with mount -o sunit=,swidth= if necessary\n" msgstr "" "Uwaga - pola jednostki pasa (%d) i szerokoÅ›ci pasa (%d) zostaÅ‚y " "przestawione.\n" "ProszÄ™ ustawić przy użyciu mount -o sunit=,swidth=\n" #: .././repair/xfs_repair.c:1068 msgid "done\n" msgstr "gotowe\n" #: .././repair/xfs_repair.c:1072 msgid "Repair of readonly mount complete. Immediate reboot encouraged.\n" msgstr "" "Naprawa systemu zamontowanego tylko do odczytu zakoÅ„czona. Zalecany " "natychmiastowy restart systemu.\n" #: .././rtcp/xfs_rtcp.c:30 #, c-format msgid "%s [-e extsize] [-p] [-V] source target\n" msgstr "%s [-e rozm_fragmentu] [-p] [-V] źródÅ‚o cel\n" #: .././rtcp/xfs_rtcp.c:69 #, c-format msgid "%s: must specify files to copy\n" msgstr "%s: trzeba podać pliki do skopiowania\n" #: .././rtcp/xfs_rtcp.c:84 #, c-format msgid "%s: stat of %s failed\n" msgstr "%s: stat na %s nie powiodÅ‚o siÄ™\n" #: .././rtcp/xfs_rtcp.c:91 #, c-format msgid "%s: final argument is not directory\n" msgstr "%s: ostatni argument nie jest katalogiem\n" #: .././rtcp/xfs_rtcp.c:138 #, c-format msgid "%s: failed stat on %s: %s\n" msgstr "%s: nie udaÅ‚o siÄ™ wykonać stat na %s: %s\n" #: .././rtcp/xfs_rtcp.c:159 #, c-format msgid "%s: %s filesystem has no realtime partition\n" msgstr "%s: system plików %s nie ma partycji realtime\n" #: .././rtcp/xfs_rtcp.c:180 .././rtcp/xfs_rtcp.c:208 #, c-format msgid "%s: open of %s failed: %s\n" msgstr "%s: otwarcie %s nie powiodÅ‚o siÄ™: %s\n" #: .././rtcp/xfs_rtcp.c:197 #, c-format msgid "%s: set attributes on %s failed: %s\n" msgstr "%s: ustawienie atrybutów dla %s nie powiodÅ‚o siÄ™: %s\n" #: .././rtcp/xfs_rtcp.c:215 #, c-format msgid "%s: get attributes of %s failed: %s\n" msgstr "%s: pobranie atrybutów %s nie powiodÅ‚o siÄ™: %s\n" #: .././rtcp/xfs_rtcp.c:225 .././rtcp/xfs_rtcp.c:262 #, c-format msgid "%s: %s is not a realtime file.\n" msgstr "%s: %s nie jest plikiem realtime.\n" #: .././rtcp/xfs_rtcp.c:235 #, c-format msgid "%s: %s file extent size is %d, instead of %d.\n" msgstr "%s: plik %s ma rozmiar ekstentu %d zamiast %d.\n" #: .././rtcp/xfs_rtcp.c:248 .././rtcp/xfs_rtcp.c:271 #, c-format msgid "%s: open of %s source failed: %s\n" msgstr "%s: otwarcie źródÅ‚a %s nie powiodÅ‚o siÄ™: %s\n" #: .././rtcp/xfs_rtcp.c:285 #, c-format msgid "%s: couldn't get direct I/O information: %s\n" msgstr "%s: nie udaÅ‚o siÄ™ uzyskać informacji o bezpoÅ›rednim we/wy: %s\n" #: .././rtcp/xfs_rtcp.c:295 #, c-format msgid "%s: extent size %d not a multiple of %d.\n" msgstr "%s: rozmiar ekstentu %d nie jest wielokrotnoÅ›ciÄ… %d.\n" #: .././rtcp/xfs_rtcp.c:309 #, c-format msgid "The size of %s is not a multiple of %d.\n" msgstr "Rozmiar %s nie jest wielokrotnoÅ›ciÄ… %d.\n" #: .././rtcp/xfs_rtcp.c:312 #, c-format msgid "%s will be padded to %lld bytes.\n" msgstr "%s: zostanie dopeÅ‚niony do %lld bajtów.\n" #: .././rtcp/xfs_rtcp.c:318 #, c-format msgid "" "Use the -p option to pad %s to a size which is a multiple of %d bytes.\n" msgstr "" "Można użyć opcji -p do dopeÅ‚nienia %s do rozmiaru bÄ™dÄ…cego wielokrotnoÅ›ciÄ… " "%d bajtów.\n" #: .././rtcp/xfs_rtcp.c:360 #, c-format msgid "%s: write error: %s\n" msgstr "%s: błąd zapisu: %s\n" #: .././rtcp/xfs_rtcp.c:388 #, c-format msgid "%s: could not open %s: %s\n" msgstr "%s: nie udaÅ‚o siÄ™ otworzyć %s: %s\n" #: .././copy/xfs_copy.c:155 msgid "lseek64 error" msgstr "błąd lseek64" #: .././copy/xfs_copy.c:256 #, c-format msgid "%s: lseek64 error on target %d \"%s\" at offset %lld\n" msgstr "%s: błąd lseek64 przy celu %d \"%s\" pod offsetem %lld\n" #: .././copy/xfs_copy.c:383 #, c-format msgid "%s: lseek64 failure at offset %lld\n" msgstr "%s: niepowodzenie lseek64 pod offsetem %lld\n" #: .././db/write.c:58 #, fuzzy msgid "" "\n" " The 'write' command takes on different personalities depending on the\n" " type of object being worked with.\n" "\n" " Write has 3 modes:\n" " 'struct mode' - is active anytime you're looking at a filesystem object\n" " which contains individual fields (ex: an inode).\n" " 'data mode' - is active anytime you set a disk address directly or set\n" " the type to 'data'.\n" " 'string mode' - only used for writing symlink blocks.\n" "\n" " Examples:\n" " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n" " 'write fname \"hello\\000\"' - write superblock fname.\n" " (note: in struct mode strings are not null terminated)\n" " 'write fname #6669736800' - write superblock fname with " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - write superblock uuid.\n" " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n" " 'write lshift 3' - shift the block 3 bytes to the left\n" " 'write sequence 1 5' - write a cycle of number [1-5] through\n" " the entire block.\n" " String mode: 'write \"This_is_a_filename\" - write null terminated " "string.\n" "\n" " In data mode type 'write' by itself for a list of specific commands.\n" "\n" " Specifying the -c option will allow writes of invalid (corrupt) data.\n" "\n" msgstr "" "\n" " Polecenie 'write' ma różne osobowoÅ›ci w zależnoÅ›ci od rodzaju obiektu,\n" " na jakim pracuje.\n" "\n" " Zapis ma trzy tryby:\n" " 'struct' (strukturalny) - aktywny w przypadku oglÄ…dania obiektu systemu\n" " plików zawierajÄ…cego poszczególne pola (np. i-wÄ™zeÅ‚).\n" " 'data' (danych) - aktywny w przypadku bezpoÅ›redniego ustawienia adresu\n" " na dysku lub ustawienia typu na 'data'.\n" " 'string' (znakowy) - używany tylko przy zapisie bloków dowiÄ…zaÅ„\n" " symbolicznych.\n" "\n" " PrzykÅ‚ady:\n" " Tryb strukturalny: 'write core.uid 23' - ustawienie pola uid i-wÄ™zÅ‚a na " "23\n" " 'write fname \"hello\\000\"' - zapis nazwy pliku sb\n" " (uwaga: w trybie strukturalnym Å‚aÅ„cuchy nie sÄ… " "zakaÅ„czane)\n" " 'write fname #6669736800' - zapis nazwy pliku sb w " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - zapis UUID-a superbloku.\n" " Tryb danych: 'write fill 0xff' - wypeÅ‚nienie bloku bajtam 0xff\n" " 'write lshift 3' - przesuniÄ™cie bloku o 3 bajty w lewo\n" " 'write sequence 1 5' zapis cyklicznie liczb [1-5] " "przez\n" " caÅ‚y blok.\n" " Tryb znakowy: 'write \"To_jest_nazwa_pliku\" - zapis Å‚aÅ„cucha\n" " zakoÅ„czonego znakiem NUL.\n" "\n" " W trybie danych samo 'write' wypisze listÄ™ bardziej specyficznych poleceÅ„.\n" "\n" #: .././db/write.c:137 msgid "Allowing write of corrupted data\n" msgstr "" #: .././db/dquot.c:37 msgid "[projid|gid|uid]" msgstr "[projid|gid|uid]" #: .././db/dquot.c:38 msgid "set current address to project, group or user quota block" msgstr "" "ustawienie bieżącego adresu na blok limitu projektu, grupy lub użytkownika" #: .././growfs/xfs_growfs.c:64 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" msgstr "" "metadane=%-22s isize=%-6u agcount=%u, agsize=%u bloków\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u\n" "dane =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u bloków\n" "nazwy =wersja %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, wersja=%u\n" " =%-22s sectsz=%-5u sunit=%u bloków, lazy-count=%u\n" "realtime=%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" #: .././io/init.c:35 #, c-format msgid "Usage: %s [-adfmnrRstVx] [-p prog] [-c cmd]... file\n" msgstr "SkÅ‚adnia: %s [-adfmnrRstVx] [-p program] [-c polecenie]... plik\n" #: .././io/reflink.c:85 #, c-format msgid "Extents did not match.\n" msgstr "" #: .././io/attr.c:58 #, c-format msgid "" "\n" " displays the set of extended inode flags associated with the current file\n" "\n" " Each individual flag is displayed as a single character, in this order:\n" " r -- file data is stored in the realtime section\n" " p -- file has preallocated extents (cannot be changed using chattr)\n" " i -- immutable, file cannot be modified\n" " a -- append-only, file can only be appended to\n" " s -- all updates are synchronous\n" " A -- the access time is not updated for this inode\n" " d -- do not include this file in a dump of the filesystem\n" " t -- child created in this directory has realtime bit set by default\n" " P -- child created in this directory has parents project ID by default\n" " n -- symbolic links cannot be created in this directory\n" " e -- for non-realtime files, observe the inode extent size value\n" " E -- children created in this directory inherit the extent size value\n" " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, but only list attributes on directories\n" " -a -- show all flags which can be set alongside those which are set\n" " -v -- verbose mode; show long names of flags, not single characters\n" "\n" msgstr "" "\n" " wyÅ›wietlanie zbioru rozszerzonych flag i-wÄ™złów zwiÄ…zanych z bieżącym " "plikiem\n" "\n" " Każda flaga jest wyÅ›wietlana jako pojedynczy znak, w tej kolejnoÅ›ci:\n" " r - dane pliku sÄ… zapisane w sekcji realtime\n" " p - plik ma już przydzielone ekstenty (nie do zmiany przez chattr)\n" " i - niezmienny, pliku nie można modyfikować\n" " a - tylko do dopisywania, do pliku można tylko dopisywać\n" " s - wszystkie uaktualnienia sÄ… synchroniczne\n" " A - czas dostÄ™pu nie jest uaktualniany dla tego i-wÄ™zÅ‚a\n" " d - nie dołączanie pliku do zrzutu systemu plików\n" " t - wpisy tworzone w tym katalogu majÄ… domyÅ›lnie ustawiony bit realtime\n" " P - wpisy tworzone w tym katalogu majÄ… domyÅ›lnie ID projektu rodzica\n" " n - w tym katalogu nie można tworzyć dowiÄ…zaÅ„ symbolicznych\n" " e - dla plików nie-realtime - przestrzeganie wartoÅ›ci rozmiaru ekstentu i-" "wÄ™zÅ‚a\n" " E - wpisy tworzone w tym katalogu dziedziczÄ… wartość rozmiaru ekstentu\n" " f - nie uwzglÄ™dnianie tego pliku przy defragmentacji systemu plików\n" " S - włączenie przydzielania strumieni plikowych dla tego katalogu\n" "\n" " Opcje:\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale wypisywanie atrybutów tylko " "katalogów\n" " -a - pokazywanie wszystkich flag, które można ustawić, obok ustawionych\n" " -v - tryb szczegółowy; pokazywanie dÅ‚ugich nazw flag zamiast pojedynczych " "znaków\n" "\n" #: .././io/attr.c:89 #, c-format msgid "" "\n" " modifies the set of extended inode flags associated with the current file\n" "\n" " Examples:\n" " 'chattr +a' - sets the append-only flag\n" " 'chattr -a' - clears the append-only flag\n" "\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, only modifying attributes on directories\n" " +/-r -- set/clear the realtime flag\n" " +/-i -- set/clear the immutable flag\n" " +/-a -- set/clear the append-only flag\n" " +/-s -- set/clear the sync flag\n" " +/-A -- set/clear the no-atime flag\n" " +/-d -- set/clear the no-dump flag\n" " +/-t -- set/clear the realtime inheritance flag\n" " +/-P -- set/clear the project ID inheritance flag\n" " +/-n -- set/clear the no-symbolic-links flag\n" " +/-e -- set/clear the extent-size flag\n" " +/-E -- set/clear the extent-size inheritance flag\n" " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " Note1: user must have certain capabilities to modify immutable/append-" "only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" " Note3: the realtime flag can only be set if the filesystem has a realtime\n" " section, and the (regular) file must be empty when the flag is set.\n" "\n" msgstr "" "\n" " zmiana zbioru rozszerzonych flag i-wÄ™złów zwiÄ…zanych z bieżącym plikiem\n" "\n" " PrzykÅ‚ady:\n" " 'chattr +a' - ustawia flagÄ™ tylko do dopisywania\n" " 'chattr -a' - zdejmuje flagÄ™ tylko do dopisywania\n" "\n" " -R - rekurencyjne zagłębianie siÄ™ (przydatne kiedy bieżący plik jest " "katalogiem)\n" " -D - rekurencyjne zagłębianie siÄ™, ale zmiana atrybutów tylko katalogów\n" " +/-r - ustawienie/zdjÄ™cie flagi realtime\n" " +/-i - ustawienie/zdjÄ™cie flagi immutable (niezmiennoÅ›ci)\n" " +/-a - ustawienie/zdjÄ™cie flagi append-only (tylko do dopisywania)\n" " +/-s - ustawienie/zdjÄ™cie flagi sync (synchronicznego zapisu)\n" " +/-A - ustawienie/zdjÄ™cie flagi no-atime\n" " +/-d - ustawienie/zdjÄ™cie flagi no-dump\n" " +/-t - ustawienie/zdjÄ™cie flagi dziedziczenia realtime\n" " +/-P - ustawienie/zdjÄ™cie flagi dziedziczenia ID projektu\n" " +/-n - ustawienie/zdjÄ™cie flagi braku dowiÄ…zaÅ„ symbolicznych\n" " +/-e - ustawienie/zdjÄ™cie flagi rozmiaru ekstentu\n" " +/-E - ustawienie/zdjÄ™cie flagi dziedziczenia rozmiaru ekstentu\n" " +/-f - ustawienie/zdjÄ™cie flagi no-defrag\n" " +/-S - ustawienie/zdjÄ™cie flagi przydzielania strumieni plikowych\n" " Uwaga1: użytkownik musi mieć pewne uprawnienia do zmiany flag\n" " immutable/append-only\n" " Uwaga2: plików immutable/append-only nie można usuwać; usuwanie tych " "plików\n" " wymaga zdjÄ™cia flag immutable/append-only przed usuniÄ™ciem.\n" " Uwaga3: flagÄ™ realtime można ustawić tylko jeÅ›li system plików ma sekcjÄ™\n" " realtime i (zwykÅ‚y) plik musi być pusty przy ustawianiu flagi.\n" "\n" #: .././io/bmap.c:30 #, c-format msgid "" "\n" " prints the block mapping for an XFS file's data or attribute forks\n" " Example:\n" " 'bmap -vp' - tabular format verbose map, including unwritten extents\n" "\n" " bmap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are " "unwritten.)\n" " -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" " Note: the bmap for non-regular files can be obtained provided the file\n" " was opened appropriately (in particular, must be opened read-only).\n" "\n" msgstr "" "\n" " wypisanie mapowania bloków dla danych lub atrybutów pliku na XFS-ie\n" " PrzykÅ‚ad:\n" " 'bmap -vp' - szczegółowa mapa w formacie tabeli wraz z nie zapisanymi\n" " ekstentami\n" "\n" " bmap wypisuje mapÄ™ bloków dysku używanych przez bieżący plik.\n" " Mapa opisuje każdy ekstent użyty przez plik, a także regiony w pliku\n" " nie majÄ…ce przypisanych bloków (dziury).\n" " DomyÅ›lnie każda linia listingu przyjmuje nastÄ™pujÄ…cÄ… postać:\n" " ekstent: [offsetpocz..offsetkoÅ„c]: blokpocz..blokkoÅ„c\n" " Dziury sÄ… oznaczane przez zastÄ…pienie blokpocz..blokkoÅ„c przez 'dziura'.\n" " Wszystkie offsety w plikach i bloki dysku sÄ… w jednostkach 512-bajtowych.\n" " -a - wypisanie mapy gałęzi atrybutów zamiast gałęzi danych.\n" " -d - pominiÄ™cie zdarzenia odczytu DMAPI, pokazanie części offline jako " "dziur.\n" " -l - wyÅ›wietlenie także dÅ‚ugoÅ›ci każdego fragmentu w 512-bajtowych " "blokach.\n" " -n - odpytanie n ekstentów.\n" " -p - wypisanie także nie zapisanych ekstentów (z -v pokazuje, które sÄ… nie\n" " zapisane).\n" " -v - szczegółowe informacje z podaniem informacji ag; legenda drugim -v\n" " Uwaga: bmap dla plików nie bÄ™dÄ…cych plikami zwykÅ‚ymi można uzyskać pod\n" " warunkiem, że plik zostaÅ‚ otwarty odpowiednio (w szczególnoÅ›ci musi być\n" " otwarty tylko do odczytu).\n" "\n" #: .././io/open.c:762 msgid "[-acdrstxT] [path]" msgstr "[-acdrstxT] [Å›cieżka]" #: .././io/prealloc.c:349 msgid "[-c] [-k] [-p] off len" msgstr "[-c] [-k] [-p] offset dÅ‚ugość" #: .././io/mmap.c:135 #, c-format msgid "" "\n" " maps a range within the current file into memory\n" "\n" " Example:\n" " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" "\n" " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" " With no arguments, mmap shows the current mappings. The current mapping\n" " can be set by using the single argument form (mapping number or address).\n" " If two arguments are specified (a range), a new mapping is created and the\n" " following options are available:\n" " -r -- map with PROT_READ protection\n" " -w -- map with PROT_WRITE protection\n" " -x -- map with PROT_EXEC protection\n" " If no protection mode is specified, all are used by default.\n" "\n" msgstr "" "\n" " odwzorowanie przedziaÅ‚u z bieżącego pliku w pamiÄ™ci\n" "\n" "PrzykÅ‚ad:\n" " 'mmap -rw 0 1m' - odwzorowuje 1MB od poczÄ…tku bieżącego pliku\n" "\n" " mmap odwzorowuje w pamiÄ™ci przedziaÅ‚ z pliku do dalszego wykorzystania " "przez\n" " inne polecenia xfs_io.\n" " Bez argumentów mmap pokazuje aktualne odwzorowania. Bieżące odwzorowanie\n" " można ustawić przy użyciu formy jednoargumentowej (mmap numer lub adres).\n" " JeÅ›li podano dwa argumenty (przedziaÅ‚), tworzone jest nowe odwzorowanie\n" " i dostÄ™pne sÄ… nastÄ™pujÄ…ce opcje:\n" " -r - odwzorowanie z ochronÄ… PROT_READ\n" " -w - odwzorowanie z ochronÄ… PROT_WRITE\n" " -x - odwzorowanie z ochronÄ… PROT_EXEC\n" " JeÅ›li nie podano trybu ochrony, domyÅ›lnie używane sÄ… wszystkie.\n" "\n" #: .././io/mmap.c:584 #, c-format msgid "" "\n" " resizes the current memory mapping\n" "\n" " Examples:\n" " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" "\n" " Resizes the mappping, growing or shrinking from the current size.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -f -- use the MREMAP_FIXED flag\n" " -m -- use the MREMAP_MAYMOVE flag\n" "\n" msgstr "" #: .././io/mmap.c:650 msgid "[N] | [-rwx] [off len]" msgstr "[N] | [-rwx] [offset dÅ‚ugość]" #: .././io/mmap.c:702 #, fuzzy msgid "[-m|-f] newsize" msgstr "[-D | -R] [rozmiar_fragmentu]" #: .././libxfs/rdwr.c:1036 #, c-format msgid "%s: pwrite64 failed: %s\n" msgstr "%s: pwrite64 nie powiodÅ‚o siÄ™: %s\n" #: .././libxfs/rdwr.c:1042 #, c-format msgid "%s: error - pwrite64 only %d of %d bytes\n" msgstr "%s: błąd - wykonano pwrite64 tylko %d z %d bajtów\n" #: .././logprint/log_print_all.c:258 #, c-format msgid "\t\tmagic:%c%c mode:0x%x ver:%d format:%d onlink:%d\n" msgstr "\t\tmagic:%c%c mode:0x%x ver:%d format:%d onlin:%d\n" #: .././logprint/log_print_all.c:262 #, c-format msgid "\t\tuid:%d gid:%d nlink:%d projid:%u\n" msgstr "\t\tuid:%d gid:%d nlink:%d projid:%u\n" #: .././logprint/log_print_all.c:388 #, c-format msgid "\tEFD: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "\tEFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_print_all.c:420 #, c-format msgid "\tEFI: #regs:%d num_extents:%d id:0x%llx\n" msgstr "\tEFI: #regs:%d num_extents:%d id:0x%llx\n" #: .././logprint/log_print_trans.c:27 #, c-format msgid "TRANS: tid:0x%x type:%s #items:%d trans:0x%x q:0x%lx\n" msgstr "TRANS: tid:0x%x typ:%s #elem:%d trans:0x%x q:0x%lx\n" #: .././logprint/log_misc.c:236 #, c-format msgid " type: %s tid: %x num_items: %d\n" msgstr " typ: %s tid: %x num_items: %d\n" #: .././logprint/log_misc.c:493 #, c-format msgid "EFD: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "EFD: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_misc.c:548 #, c-format msgid "EFI: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "EFI: #regs: %d num_extents: %d id: 0x%llx\n" #: .././logprint/log_misc.c:890 #, c-format msgid "%s: lseek64 to %lld failed: %s\n" msgstr "%s: lseek64 na %lld nie powiodÅ‚o siÄ™: %s\n" #: .././mkfs/xfs_mkfs.c:230 #, c-format msgid "data su/sw must not be used in conjunction with data sunit/swidth\n" msgstr "su/sw danych nie można użyć w połączeniu z sunit/swidth danych\n" #: .././mkfs/xfs_mkfs.c:246 #, c-format msgid "data sunit/swidth must not be used in conjunction with data su/sw\n" msgstr "sunit/swidth danych nie można użyć w połączeniu z su/sw danych\n" #: .././mkfs/xfs_mkfs.c:281 #, c-format msgid "log su should not be used in conjunction with log sunit\n" msgstr "su logu nie powinno być używane w połączeniu z sunit logu\n" #: .././mkfs/xfs_mkfs.c:290 #, c-format msgid "log sunit should not be used in conjunction with log su\n" msgstr "sunit logu nie powinno być używane w połączeniu z su logu\n" #: .././mkfs/xfs_mkfs.c:820 #, c-format msgid "existing superblock read failed: %s\n" msgstr "odczyt istniejÄ…cego superbloku nie powiódÅ‚ siÄ™: %s\n" #: .././mkfs/xfs_mkfs.c:826 #, fuzzy, c-format msgid "warning: could not read existing superblock, skip zeroing\n" msgstr "nie udaÅ‚o siÄ™ odczytać superbloku\n" #: .././mkfs/xfs_mkfs.c:1137 #, c-format msgid "%s: Specify data sunit in 512-byte blocks, no unit suffix\n" msgstr "%s: sunit danych należy podać w 512-bajtowych blokach, bez jednostki\n" #: .././mkfs/xfs_mkfs.c:1153 #, c-format msgid "%s: Specify data swidth in 512-byte blocks, no unit suffix\n" msgstr "" "%s: swidth danych należy podać w 512-bajtowych blokach, bez jednostki\n" #: .././mkfs/xfs_mkfs.c:1180 #, c-format msgid "%s: Specify data sw as multiple of su, no unit suffix\n" msgstr "%s: sw danych należy podać jako wielokrotność su, bez jednostki\n" #: .././mkfs/xfs_mkfs.c:1417 #, c-format msgid "Specify log sunit in 512-byte blocks, no size suffix\n" msgstr "sunit należy podać w 512-bajtowych blokach, bez jednostki\n" #: .././mkfs/xfs_mkfs.c:1726 #, c-format msgid "cannot specify both %s and -d name=%s\n" msgstr "nie można podać jednoczeÅ›nie %s i -d name=%s\n" #: .././mkfs/xfs_mkfs.c:1880 #, c-format msgid "warning: finobt not supported without CRC support, disabled.\n" msgstr "uwaga: finobt nie jest obsÅ‚ugiwane bez obsÅ‚ugi CRC, wyłączono.\n" #: .././mkfs/xfs_mkfs.c:1887 #, fuzzy, c-format msgid "warning: sparse inodes not supported without CRC support, disabled.\n" msgstr "uwaga: finobt nie jest obsÅ‚ugiwane bez obsÅ‚ugi CRC, wyłączono.\n" #: .././mkfs/xfs_mkfs.c:1908 #, c-format msgid "both -d agcount= and agsize= specified, use one or the other\n" msgstr "" "podano jednoczeÅ›nie -d agcount= i agsize=, można użyć tylko jednej z tych " "opcji\n" #: .././mkfs/xfs_mkfs.c:1914 #, c-format msgid "if -d file then -d name and -d size are required\n" msgstr "jeÅ›li podano -d file, to -d name i -d size sÄ… wymagane\n" #: .././mkfs/xfs_mkfs.c:1951 #, c-format msgid "if -l file then -l name and -l size are required\n" msgstr "jeÅ›li podano -l file to -l name i -l size sÄ… wymagane\n" #: .././mkfs/xfs_mkfs.c:1973 #, c-format msgid "if -r file then -r name and -r size are required\n" msgstr "jeÅ›li podano -r file, to -r name i -r size sÄ… wymagane\n" #: .././mkfs/xfs_mkfs.c:2008 #, c-format msgid "rt extent size %s too large, maximum %d\n" msgstr "rozmiar ekstentu rt %s zbyt duży, maksimum to %d\n" #: .././mkfs/xfs_mkfs.c:2014 #, c-format msgid "rt extent size %s too small, minimum %d\n" msgstr "rozmiar ekstentu rt %s zbyt maÅ‚y, minimum to %d\n" #: .././mkfs/xfs_mkfs.c:2567 #, fuzzy, c-format msgid "" "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" msgstr "" "metadane=%-22s isize=%-6d agcount=%lld, agsize=%lld bloków\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u\n" "dane =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u bloków\n" "nazwy =wersja %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, wersja=%d\n" " =%-22s sectsz=%-5u sunit=%d bloków, lazy-count=%d\n" "realtime=%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" #: .././mkfs/xfs_mkfs.c:3181 #, c-format msgid "blocksize not available yet.\n" msgstr "rozmiar bloku jeszcze nie dostÄ™pny.\n" #: .././mkfs/xfs_mkfs.c:3207 #, fuzzy, c-format msgid "" "Usage: %s\n" "/* blocksize */\t\t[-b log=n|size=num]\n" "/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx]\n" "/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num|noalign),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* force overwrite */\t[-f]\n" "/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n" "\t\t\t projid32bit=0|1,sparse=0|1]\n" "/* no discard */\t[-K]\n" "/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* label */\t\t[-L label (maximum 12 characters)]\n" "/* naming */\t\t[-n log=n|size=num,version=2|ci,ftype=0|1]\n" "/* no-op info only */\t[-N]\n" "/* prototype file */\t[-p fname]\n" "/* quiet */\t\t[-q]\n" "/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* sectorsize */\t[-s log=n|size=num]\n" "/* version */\t\t[-V]\n" "\t\t\tdevicename\n" " is required unless -d name=xxx is given.\n" " is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " is xxx (512 byte blocks).\n" msgstr "" "SkÅ‚adnia: %s\n" "/* rozmiar bloku */ [-b log=n|size=liczba]\n" "/* metadane */ [-m crc=0|1,finobt=0|1]\n" "/* podwolumen danych */ [-d agcount=n,agsize=n,file,name=xxx,size=liczba,\n" " (sunit=wartość,swidth=wartość|su=ile,sw=ile|" "noalign),\n" " sectlog=n|sectsize=ile]\n" "/* wym. nadpisania */ [-f]\n" "/* rozmiar i-wÄ™zÅ‚a */ [-i log=n|perblock=n|size=ile,maxpct=n,attr=0|1|2,\n" " projid32bit=0|1]\n" "/* bez porzucenia */ [-K]\n" "/* podwolumen logu */ [-l agnum=n,internal,size=ile,logdev=xxx,version=n\n" " sunit=wartość|su=ile,sectlog=n|sectsize=ile,\n" " lazy-count=0|1]\n" "/* etykieta */ [-L etykieta (maksymalnie 12 znaków)]\n" "/* nazwy */ [-n log=n|size=ile,wersja=2|ci,ftype=0|1]\n" "/* tylko info no-op */ [-N]\n" "/* plik prototypu */ [-p nazwa_pliku]\n" "/* cisza */ [-q]\n" "/* podwolumen rt */ [-r extsize=ile,size=ile,rtdev=xxx]\n" "/* rozmiar sektora */ [-s log=n|size=ile]\n" "/* wersja */ [-V]\n" " nazwa_urzÄ…dzenia\n" " jest wymagana, chyba że podano -d name=xxx.\n" " to xxx (bajtów), xxxs (sektorów), xxxb (bloków systemu plików),\n" " xxxk (xxx KiB), xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB),\n" " xxxp (xxx PiB).\n" " to xxx (512-bajtowych bloków).\n" #: .././quota/edit.c:689 msgid "[-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" msgstr "[-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|nazwa" #: .././quota/edit.c:697 .././quota/report.c:33 .././quota/report.c:647 msgid "[-gpu] [-f file]" msgstr "[-gpu] [-f plik]" #: .././quota/edit.c:704 .././quota/edit.c:712 msgid "[-bir] [-gpu] value -d|id|name" msgstr "[-bir] [-gpu] wartość -d|id|nazwa" #: .././quota/edit.c:705 msgid "get/set quota enforcement timeouts" msgstr "pobranie/ustawienie czasu wymuszenia quot" #: .././quota/free.c:371 msgid "[-bir] [-hn] [-f file]" msgstr "[-bir] [hn] [-f plik]" #: .././quota/init.c:48 #, c-format msgid "Usage: %s [-V] [-x] [-p prog] [-c cmd]... [-d project]... [path]\n" msgstr "" "SkÅ‚adnia: %s [-V] [-x] [-p program] [-c polecenie]... [-d projekt]... " "[Å›cieżka]\n" #: .././quota/path.c:39 #, c-format msgid "%sFilesystem Pathname\n" msgstr "%sSystem plików Åšcieżka\n" #: .././quota/quot.c:419 msgid "[-bir] [-gpu] [-acv] [-f file]" msgstr "[-bir] [-gpu] [-acv] [-f plik]" #: .././quota/quota.c:464 msgid "[-bir] [-gpu] [-hnNv] [-f file] [id|name]..." msgstr "[-bir] [-gpu] [-hnNv] [-f plik] [id|nazwa]..." #: .././quota/report.c:48 msgid "[-bir] [-gpu] [-ahntLNU] [-f file]" msgstr "[-bir] [-gpu] [-ahntLNU] [-f plik]" #: .././quota/report.c:51 #, c-format msgid "" "\n" " report used space and inodes, and quota limits, for a filesystem\n" " Example:\n" " 'report -igh'\n" " (reports inode usage for all groups, in an easy-to-read format)\n" " This command is the equivalent of the traditional repquota command, which\n" " prints a summary of the disk usage and quotas for the current filesystem,\n" " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -L -- lower ID bound to report on\n" " -U -- upper ID bound to report on\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" " -u -- report user usage and quota information\n" " -b -- report blocks-used information only\n" " -i -- report inodes-used information only\n" " -r -- report realtime-blocks-used information only\n" "\n" msgstr "" "\n" " informacje o wykorzystanym miejscu i i-wÄ™zÅ‚ach oraz limitach quota dla " "systemu\n" " plików\n" "\n" " PrzykÅ‚ad:\n" " 'report -igh'\n" " (raport o wykorzystaniu i-wÄ™złów dla wszystkich grup w czytelnym formacie)\n" "\n" " To polecenie jest odpowiednikiem tradycyjnego polecenia repquota, " "wypisujÄ…cego\n" " podsumowanie wykorzystania dysku i limitów dla bieżącego systemu plików " "lub\n" " wszystkich systemów plików.\n" " -a - informacje o wszystkich zamontowanych systemach plików z limitami\n" " -h - informacje w formacie czytelnym dla czÅ‚owieka\n" " -n - pominiÄ™cie tÅ‚umaczenia identyfikatorów na nazwy, wypisywanie ID\n" " -N - pominiÄ™cie poczÄ…tkowego nagłówka\n" " -t - zwiÄ™zÅ‚y format, ukrycie wierszy zerowych\n" " -L - dolna granica ID dla wypisywanych informacji\n" " -U - górna granica ID dla wypisywanych informacji\n" " -g - informacje o wykorzystanym miejscu i limitach dla grup\n" " -p - informacje o wykorzystanym miejscu i limitach dla projektów\n" " -u - informacje o wykorzystanym miejscu i limitach dla użytkowników\n" " -b - tylko informacje o wykorzystanych blokach\n" " -i - tylko informacje o wykorzystanych i-wÄ™zÅ‚ach\n" " -r - tylko informacje o wykorzystanych blokach realtime\n" "\n" #: .././repair/phase5.c:1463 #, c-format msgid "lost %d blocks in ag %u\n" msgstr "utracono %d bloków w ag %u\n" #: .././repair/phase5.c:1466 #, c-format msgid "thought we were going to lose %d blocks in ag %u, actually lost %d\n" msgstr "przewidywano utracenie %d bloków w ag %u, a utracono %d\n" #: .././repair/phase5.c:1685 #, c-format msgid "lost %d blocks in agno %d, sorry.\n" msgstr "niestety utracono %d bloków w agno %d.\n" #: .././repair/versions.c:228 #, c-format msgid "" "WARNING: you have a V1 inode filesystem. It %s be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:84 #, c-format msgid "%s: stat64 of %s failed\n" msgstr "%s: stat64 na %s nie powiodÅ‚o siÄ™\n" #: .././rtcp/xfs_rtcp.c:138 #, c-format msgid "%s: failed stat64 on %s: %s\n" msgstr "%s: nie udaÅ‚o siÄ™ wykonać stat64 na %s: %s\n" #~ msgid "%s: Cannot yet copy V5 fs without '-d'\n" #~ msgstr "%s: Nie można jeszcze kopiować systemu plików V5 bez '-d'\n" #~ msgid "sb versionnum missing nlink bit %x\n" #~ msgstr "sb versionnum - brak bitu nlink %x\n" #~ msgid "%s: cannot read %s\n" #~ msgstr "%s: nie można odczytać %s\n" #~ msgid "could not open mtab file: %s\n" #~ msgstr "nie udaÅ‚o siÄ™ otworzyć pliku mtab: %s\n" #~ msgid "FSGETXATTRA failed on target\n" #~ msgstr "FSGETXATTRA nie powiodÅ‚o siÄ™ na docelowym urzÄ…dzeniu\n" #~ msgid "wrote %lld/%lld bytes at offset %lld\n" #~ msgstr "zapisano %lld/%lld bajtów od offsetu %lld\n" #~ msgid "sent %lld/%lld bytes from offset %lld\n" #~ msgstr "przesÅ‚ano %lld/%lld bajtów od offsetu %lld\n" #~ msgid "%s: cannot reserve space: %s\n" #~ msgstr "%s: nie można zarezerwować przestrzeni: %s\n" #~ msgid "bad shared version number in superblock %d\n" #~ msgstr "błędny numer wersji dzielonej w superbloku %d\n" #~ msgid "" #~ "can't read block %u (fsbno %) for directory inode %\n" #~ msgstr "" #~ "nie można odczytać bloku %u (fsbno %) dla i-wÄ™zÅ‚a katalogu " #~ "%\n" #~ msgid "" #~ "can't read block %u (fsbno %) for attrbute fork of inode " #~ "%\n" #~ msgstr "" #~ "nie można odczytać bloku %u (fsbno %) dla gałęzi atrybutów i-" #~ "wÄ™zÅ‚a %\n" #~ msgid "" #~ "bad dir/attr magic number in inode %, file bno = %u, fsbno = " #~ "%\n" #~ msgstr "" #~ "błędna liczba magiczna katalogu/atrybutu w i-węźle %, bno pliku = " #~ "%u, fsbno = %\n" #~ msgid "bad directory btree for directory inode %\n" #~ msgstr "błędne b-drzewo katalogu dla i-wÄ™zÅ‚a katalogu %\n" #~ msgid "directory/attribute block used/count inconsistency - %d/%hu\n" #~ msgstr "niespójność wartoÅ›ci used/count bloku katalogu/atrybutu - %d/%hu\n" #~ msgid "bad directory block in dir ino %\n" #~ msgstr "błędny blok katalogu w i-węźle katalogu %\n" #~ msgid "" #~ "correcting bad hashval in non-leaf dir/attr block\n" #~ "\tin (level %d) in inode %.\n" #~ msgstr "" #~ "poprawiono błędne hashval w bloku katalogu/atrybutu nie bÄ™dÄ…cego liÅ›ciem\n" #~ "\tw i-węźle (poziomu %d) %.\n" #~ msgid "" #~ "would correct bad hashval in non-leaf dir/attr block\n" #~ "\tin (level %d) in inode %.\n" #~ msgstr "" #~ "błędne hashval zostaÅ‚oby poprawione w bloku katalogu/atrybutu nie " #~ "bÄ™dÄ…cego liÅ›ciem\n" #~ "\tw i-węźle (poziomu %d) %.\n" #~ msgid "can't read block %u (%) for directory inode %\n" #~ msgstr "" #~ "nie można odczytać bloku %u (%) dla i-wÄ™zÅ‚a katalogu %\n" #~ msgid "" #~ "bad magic number %x in block %u (%) for directory inode " #~ "%\n" #~ msgstr "" #~ "błędna liczba magiczna %x w bloku %u (%) dla i-wÄ™zÅ‚a katalogu " #~ "%\n" #~ msgid "" #~ "bad back pointer in block %u (%) for directory inode %\n" #~ msgstr "" #~ "błędny wskaźnik wstecz w bloku %u (%) dla i-wÄ™zÅ‚a katalogu " #~ "%\n" #~ msgid "" #~ "entry count %d too large in block %u (%) for directory inode " #~ "%\n" #~ msgstr "" #~ "liczba wpisów %d zbyt duża w bloku %u (%) dla i-wÄ™zÅ‚a katalogu " #~ "%\n" #~ msgid "bad level %d in block %u (%) for directory inode %\n" #~ msgstr "" #~ "błędny poziom %d w bloku %u (%) dla i-wÄ™zÅ‚a katalogu %\n" #~ msgid "" #~ "correcting bad hashval in interior dir/attr block\n" #~ "\tin (level %d) in inode %.\n" #~ msgstr "" #~ "poprawiono błędne hashval w wewnÄ™trznym bloku katalogu/atrybutu\n" #~ "\tw i-węźle (poziomu %d) %.\n" #~ msgid "" #~ "would correct bad hashval in interior dir/attr block\n" #~ "\tin (level %d) in inode %.\n" #~ msgstr "" #~ "błędne hashval zostaÅ‚oby poprawione w wewnÄ™trznym bloku katalogu/" #~ "atrybutu\n" #~ "\tw i-węźle (poziomu %d) %.\n" #~ msgid "component of symlink in inode % too long\n" #~ msgstr "skÅ‚adnik dowiÄ…zania symbolicznego w i-węźle % zbyt dÅ‚ugi\n" #~ msgid "version 2 inode % claims > %u links, " #~ msgstr "i-wÄ™zeÅ‚ % w wersji 2 odwoÅ‚uje siÄ™ do > %u dowiÄ…zaÅ„, " #~ msgid "updating superblock version number\n" #~ msgstr "uaktualniono numer wersji superbloku\n" #~ msgid "would update superblock version number\n" #~ msgstr "numer wersji superbloku zostaÅ‚by uaktualniony\n" #~ msgid "WARNING: version 2 inode % claims > %u links, " #~ msgstr "UWAGA: i-wÄ™zeÅ‚ % w wersji 2 odwoÅ‚uje siÄ™ do > %u dowiÄ…zaÅ„, " #~ msgid "" #~ "converting back to version 1,\n" #~ "this may destroy %d links\n" #~ msgstr "" #~ "przeksztaÅ‚canie z powrotem do wersji 1,\n" #~ "może to zniszczyć %d dowiÄ…zaÅ„\n" #~ msgid "" #~ "would convert back to version 1,\n" #~ "\tthis might destroy %d links\n" #~ msgstr "" #~ "zostaÅ‚by przeksztaÅ‚cony z powrotem do wersji 1,\n" #~ "\tco mogÅ‚oby zniszczyć %d dowiÄ…zaÅ„\n" #~ msgid "found version 2 inode %, " #~ msgstr "znaleziono i-wÄ™zeÅ‚ % w wersji 2, " #~ msgid "converting back to version 1\n" #~ msgstr "przeksztaÅ‚cono z powrotem do wersji 1\n" #~ msgid "would convert back to version 1\n" #~ msgstr "zostaÅ‚by przeksztaÅ‚cony z powrotem do wersji 1\n" #~ msgid "release_dir2_cursor_int got unexpected non-null bp, dabno = %u\n" #~ msgstr "" #~ "release_dir2_cursor_int otrzymaÅ‚ nieoczekiwany niezerowy bp, dabno = %u\n" #~ msgid "zero length entry in shortform dir %, resetting to %d\n" #~ msgstr "" #~ "wpis zerowej dÅ‚ugoÅ›ci w krótkim katalogu %, przestawiono na %d\n" #~ msgid "zero length entry in shortform dir %, would set to %d\n" #~ msgstr "" #~ "wpis zerowej dÅ‚ugoÅ›ci w krótkim katalogu %, zostaÅ‚by przestawiony " #~ "na %d\n" #~ msgid "" #~ "size of last entry overflows space left in in shortform dir %, " #~ msgstr "" #~ "rozmiar ostatniego wpisu przekracza miejsce pozostaÅ‚e w krótkim katalogu " #~ "%, " #~ msgid "resetting to %d\n" #~ msgstr "przestawiono na %d\n" #~ msgid "would reset to %d\n" #~ msgstr "zostaÅ‚by przestawiony na %d\n" #~ msgid "" #~ "size of entry #%d overflows space left in in shortform dir %\n" #~ msgstr "" #~ "rozmiar wpisu #%d przekracza miejsce pozostaÅ‚e w krótkim katalogu " #~ "%\n" #~ msgid "junking entry #%d\n" #~ msgstr "wyrzucono wpis #%d\n" #~ msgid "junking %d entries\n" #~ msgstr "wyrzucono %d wpisów\n" #~ msgid "would junk entry #%d\n" #~ msgstr "wpis #%d zostaÅ‚by wyrzucony\n" #~ msgid "would junk %d entries\n" #~ msgstr "%d wpisów zostaÅ‚oby wyrzuconych\n" #~ msgid "" #~ "nlinks %u will overflow v1 ino, ino % will be converted to " #~ "version 2\n" #~ msgstr "" #~ "nlinks %u przepeÅ‚ni i-wÄ™zeÅ‚ v1, i-wÄ™zeÅ‚ % bÄ™dzie skonwertowany do " #~ "wersji 2\n" #~ msgid "calloc failed in verify_set_primary_sb\n" #~ msgstr "calloc nie powiodÅ‚o siÄ™ w verify_set_primary_sb\n" #~ msgid "badly aligned finobt inode rec (starting inode = %)\n" #~ msgstr "" #~ "błędnie wyrównany rekord i-wÄ™zÅ‚a finobt (poczÄ…tkowy i-wÄ™zeÅ‚ = %)\n" #~ msgid "" #~ "bad starting inode # (% (0x%x 0x%x)) in finobt rec, skipping rec\n" #~ msgstr "" #~ "błędny numer poczÄ…tkowego i-wÄ™zÅ‚a (% (0x%x 0x%x)) w rekordzie " #~ "finobt, pominiÄ™to rekord\n" #~ msgid "" #~ "bad ending inode # (% (0x%x 0x%zx)) in finobt rec, skipping rec\n" #~ msgstr "" #~ "błędny numer koÅ„cowego i-wÄ™zÅ‚a (% (0x%x 0x%zx)) w rekordzie " #~ "finobt, pominiÄ™to rekord\n" #~ msgid "This filesystem is marked shared.\n" #~ msgstr "Ten system plików jest oznaczony jako współdzielony.\n" #~ msgid "" #~ "WARNING: you have disallowed version 2 inodes but this filesystem\n" #~ "\thas version 2 inodes. The filesystem will be downgraded and\n" #~ "\tall version 2 inodes will be converted to version 1 inodes.\n" #~ "\tThis may cause some hard links to files to be destroyed\n" #~ msgstr "" #~ "UWAGA: zabroniono używania i-wÄ™złów w wersji 2, ale ten system plików\n" #~ "\tzawiera i-wÄ™zÅ‚y w wersji 2. System plików zostanie zdegradowany,\n" #~ "\ta wszystkie i-wÄ™zÅ‚y w wersji 2 zostanÄ… przekonwertowane do wersji 1.\n" #~ "\tMoże to spowodować zniszczenie niektórych twardych dowiÄ…zaÅ„ do\n" #~ "\tplików.\n" #~ msgid "" #~ "WARNING: you have disallowed version 2 inodes but this filesystem\n" #~ "\thas version 2 inodes. The filesystem would be downgraded and\n" #~ "\tall version 2 inodes would be converted to version 1 inodes.\n" #~ "\tThis might cause some hard links to files to be destroyed\n" #~ msgstr "" #~ "UWAGA: zabroniono używania i-wÄ™złów w wersji 2, ale ten system plików\n" #~ "\tzawiera i-wÄ™zÅ‚y w wersji 2. System plików zostaÅ‚by zdegradowany,\n" #~ "\ta wszystkie i-wÄ™zÅ‚y w wersji 2 zostaÅ‚yby przekonwertowane do\n" #~ "\twersji 1. MogÅ‚oby to spowodować zniszczenie niektórych twardych\n" #~ "\tdowiÄ…zaÅ„ do plików.\n" xfsprogs-4.9.0+nmu1ubuntu2/po/xfsprogs.pot0000644000000000000000000113720113063067172015515 0ustar # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-01-08 07:15+1100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: .././copy/xfs_copy.c:115 #, c-format msgid "Check logfile \"%s\" for more details\n" msgstr "" #: .././copy/xfs_copy.c:121 #, c-format msgid "%s: could not write to logfile \"%s\".\n" msgstr "" #: .././copy/xfs_copy.c:124 #, c-format msgid "Aborting XFS copy -- logfile error -- reason: %s\n" msgstr "" #: .././copy/xfs_copy.c:139 .././copy/xfs_copy.c:292 .././copy/xfs_copy.c:605 #: .././copy/xfs_copy.c:612 msgid "Aborting XFS copy - reason" msgstr "" #: .././copy/xfs_copy.c:159 msgid "THE FOLLOWING COPIES FAILED TO COMPLETE\n" msgstr "" #: .././copy/xfs_copy.c:163 msgid "write error" msgstr "" #: .././copy/xfs_copy.c:165 msgid "lseek error" msgstr "" #: .././copy/xfs_copy.c:166 #, c-format msgid " at offset %lld\n" msgstr "" #: .././copy/xfs_copy.c:170 #, c-format msgid "All copies completed.\n" msgstr "" #: .././copy/xfs_copy.c:173 #, c-format msgid "See \"%s\" for more details.\n" msgstr "" #: .././copy/xfs_copy.c:261 #, c-format msgid "%s: write error on target %d \"%s\" at offset %lld\n" msgstr "" #: .././copy/xfs_copy.c:266 #, c-format msgid "%s: lseek error on target %d \"%s\" at offset %lld\n" msgstr "" #: .././copy/xfs_copy.c:272 #, c-format msgid "Aborting target %d - reason" msgstr "" #: .././copy/xfs_copy.c:276 msgid "Aborting XFS copy - no more targets.\n" msgstr "" #: .././copy/xfs_copy.c:287 #, c-format msgid "%s: thread %d died unexpectedly, target \"%s\" incomplete\n" msgstr "" #: .././copy/xfs_copy.c:289 #, c-format msgid "%s: offset was probably %lld\n" msgstr "" #: .././copy/xfs_copy.c:300 #, c-format msgid "%s: Unknown child died (should never happen!)\n" msgstr "" #: .././copy/xfs_copy.c:310 #, c-format msgid "Usage: %s [-bdV] [-L logfile] source target [target ...]\n" msgstr "" #: .././copy/xfs_copy.c:393 #, c-format msgid "%s: lseek failure at offset %lld\n" msgstr "" #: .././copy/xfs_copy.c:408 #, c-format msgid "assert error: buf->length = %d, buf->size = %d\n" msgstr "" #: .././copy/xfs_copy.c:414 #, c-format msgid "%s: read failure at offset %lld\n" msgstr "" #: .././copy/xfs_copy.c:444 msgid "ag header buffer invalid!\n" msgstr "" #: .././copy/xfs_copy.c:585 .././db/init.c:96 .././estimate/xfs_estimate.c:144 #: .././fsr/xfs_fsr.c:295 .././growfs/xfs_growfs.c:190 .././io/init.c:199 #: .././logprint/logprint.c:206 .././mkfs/xfs_mkfs.c:1925 #: .././quota/init.c:181 .././repair/xfs_repair.c:322 .././rtcp/xfs_rtcp.c:55 #, c-format msgid "%s version %s\n" msgstr "" #: .././copy/xfs_copy.c:603 #, c-format msgid "%s: couldn't open log file \"%s\"\n" msgstr "" #: .././copy/xfs_copy.c:610 #, c-format msgid "%s: couldn't set up logfile stream\n" msgstr "" #: .././copy/xfs_copy.c:622 msgid "Couldn't allocate target array\n" msgstr "" #: .././copy/xfs_copy.c:641 #, c-format msgid "%s: couldn't open source \"%s\"\n" msgstr "" #: .././copy/xfs_copy.c:647 #, c-format msgid "%s: couldn't stat source \"%s\"\n" msgstr "" #: .././copy/xfs_copy.c:657 #, c-format msgid "%s: Cannot set direct I/O flag on \"%s\".\n" msgstr "" #: .././copy/xfs_copy.c:662 #, c-format msgid "%s: xfsctl on file \"%s\" failed.\n" msgstr "" #: .././copy/xfs_copy.c:685 #, c-format msgid "%s: Warning -- a filesystem is mounted on the source device.\n" msgstr "" #: .././copy/xfs_copy.c:688 msgid "\t\tGenerated copies may be corrupt unless the source is\n" msgstr "" #: .././copy/xfs_copy.c:690 msgid "\t\tunmounted or mounted read-only. Copy proceeding...\n" msgstr "" #: .././copy/xfs_copy.c:707 #, c-format msgid "" "%s: couldn't initialize XFS library\n" "%s: Aborting.\n" msgstr "" #: .././copy/xfs_copy.c:731 #, c-format msgid "" "%s: %s filesystem failed to initialize\n" "%s: Aborting.\n" msgstr "" #: .././copy/xfs_copy.c:735 #, c-format msgid "" "%s %s filesystem failed to initialize\n" "%s: Aborting.\n" msgstr "" #: .././copy/xfs_copy.c:739 #, c-format msgid "" "%s: %s has an external log.\n" "%s: Aborting.\n" msgstr "" #: .././copy/xfs_copy.c:743 #, c-format msgid "" "%s: %s has a real-time section.\n" "%s: Aborting.\n" msgstr "" #: .././copy/xfs_copy.c:762 msgid "" "Error: source filesystem log is dirty. Mount the filesystem to replay the\n" "log, unmount and retry xfs_copy.\n" msgstr "" #: .././copy/xfs_copy.c:767 msgid "" "Error: could not determine the log head or tail of the source filesystem.\n" "Mount the filesystem to replay the log or run xfs_repair.\n" msgstr "" #: .././copy/xfs_copy.c:783 msgid "" "Error: filesystem block size is smaller than the disk sectorsize.\n" "Aborting XFS copy now.\n" msgstr "" #: .././copy/xfs_copy.c:800 #, c-format msgid "Creating file %s\n" msgstr "" #: .././copy/xfs_copy.c:818 #, c-format msgid "" "%s: a filesystem is mounted on target device \"%s\".\n" "%s cannot copy to mounted filesystems. Aborting\n" msgstr "" #: .././copy/xfs_copy.c:829 #, c-format msgid "%s: couldn't open target \"%s\"\n" msgstr "" #: .././copy/xfs_copy.c:839 #, c-format msgid "%s: cannot grow data section.\n" msgstr "" #: .././copy/xfs_copy.c:847 #, c-format msgid "%s: xfsctl on \"%s\" failed.\n" msgstr "" #: .././copy/xfs_copy.c:866 #, c-format msgid "%s: failed to write last block\n" msgstr "" #: .././copy/xfs_copy.c:868 #, c-format msgid "\tIs target \"%s\" too small?\n" msgstr "" #: .././copy/xfs_copy.c:878 msgid "Couldn't initialize global thread mask\n" msgstr "" #: .././copy/xfs_copy.c:885 msgid "Error initializing wbuf 0\n" msgstr "" #: .././copy/xfs_copy.c:893 msgid "Error initializing btree buf 1\n" msgstr "" #: .././copy/xfs_copy.c:898 msgid "Error creating first semaphore.\n" msgstr "" #: .././copy/xfs_copy.c:913 msgid "Couldn't malloc space for thread args\n" msgstr "" #: .././copy/xfs_copy.c:925 #, c-format msgid "Error creating thread mutex %d\n" msgstr "" #: .././copy/xfs_copy.c:942 #, c-format msgid "Error creating thread for target %d\n" msgstr "" #: .././copy/xfs_copy.c:996 #, c-format msgid "Error: current level %d >= btree levels %d\n" msgstr "" #: .././copy/xfs_copy.c:1015 #, c-format msgid "Bad btree magic 0x%x\n" msgstr "" #: .././copy/xfs_copy.c:1042 msgid "WARNING: source filesystem inconsistent.\n" msgstr "" #: .././copy/xfs_copy.c:1044 msgid " A leaf btree rec isn't a leaf. Aborting now.\n" msgstr "" #: .././db/addr.c:35 msgid "[field-expression]" msgstr "" #: .././db/addr.c:36 msgid "set current address" msgstr "" #: .././db/addr.c:42 msgid "" "\n" " 'addr' uses the given field to set the filesystem address and type\n" "\n" " Examples:\n" "\n" " sb\n" " a rootino - set the type to inode and set position to the root inode\n" " a u.bmx[0].startblock (for inode with blockmap)\n" "\n" msgstr "" #: .././db/addr.c:72 .././db/attrset.c:86 .././db/attrset.c:189 #: .././db/crc.c:76 .././db/print.c:74 .././db/type.c:208 .././db/write.c:110 msgid "no current type\n" msgstr "" #: .././db/addr.c:82 #, c-format msgid "no fields for type %s\n" msgstr "" #: .././db/addr.c:94 msgid "array not allowed for addr command\n" msgstr "" #: .././db/addr.c:103 #, c-format msgid "no next type for field %s\n" msgstr "" #: .././db/addr.c:110 #, c-format msgid "no addr function for field %s (type %s)\n" msgstr "" #: .././db/agf.c:35 .././db/agfl.c:36 .././db/agi.c:35 .././db/sb.c:44 msgid "[agno]" msgstr "" #: .././db/agf.c:36 msgid "set address to agf header" msgstr "" #: .././db/agf.c:100 msgid "" "\n" " set allocation group free block list\n" "\n" " Example:\n" "\n" " agf 2 - move location to AGF in 2nd filesystem allocation group\n" "\n" " Located in the second sector of each allocation group, the AGF\n" " contains the root of two different freespace btrees:\n" " The 'cnt' btree keeps track freespace indexed on section size.\n" " The 'bno' btree tracks sections of freespace indexed on block number.\n" msgstr "" #: .././db/agf.c:125 .././db/agfl.c:106 .././db/agi.c:94 .././db/sb.c:167 #, c-format msgid "bad allocation group number %s\n" msgstr "" #: .././db/agfl.c:37 msgid "set address to agfl block" msgstr "" #: .././db/agfl.c:79 msgid "" "\n" " set allocation group freelist\n" "\n" " Example:\n" "\n" " agfl 5\n" " Located in the fourth sector of each allocation group,\n" " the agfl freelist for internal btree space allocation is maintained\n" " for each allocation group. This acts as a reserved pool of space\n" " separate from the general filesystem freespace (not used for user data).\n" "\n" msgstr "" #: .././db/agi.c:36 msgid "set address to agi header" msgstr "" #: .././db/agi.c:69 msgid "" "\n" " set allocation group inode btree\n" "\n" " Example:\n" "\n" " agi 3 (set location to 3rd allocation group inode btree and type to 'agi')\n" "\n" " Located in the 3rd 512 byte block of each allocation group,\n" " the agi inode btree tracks all used/free inodes in the allocation group.\n" " Inodes are allocated in 16k 'chunks', each btree entry tracks a 'chunk'.\n" "\n" msgstr "" #: .././db/attr.c:556 msgid "Unknown attribute buffer type!\n" msgstr "" #: .././db/attr.c:568 msgid "Writing unknown attribute buffer type!\n" msgstr "" #: .././db/attrset.c:38 msgid "[-r|-s|-p|-u] [-n] [-R|-C] [-v n] name" msgstr "" #: .././db/attrset.c:39 msgid "set the named attribute on the current inode" msgstr "" #: .././db/attrset.c:42 msgid "[-r|-s|-p|-u] [-n] name" msgstr "" #: .././db/attrset.c:43 msgid "remove the named attribute from the current inode" msgstr "" #: .././db/attrset.c:49 msgid "" "\n" " The 'attr_set' and 'attr_remove' commands provide interfaces for debugging\n" " the extended attribute allocation and removal code.\n" " Both commands require an attribute name to be specified, and the attr_set\n" " command allows an optional value length (-v) to be provided as well.\n" " There are 4 namespace flags:\n" " -r -- 'root'\n" " -u -- 'user'\t\t(default)\n" " -s -- 'secure'\n" "\n" " For attr_set, these options further define the type of set operation:\n" " -C -- 'create' - create attribute, fail if it already exists\n" " -R -- 'replace' - replace attribute, fail if it does not exist\n" " The backward compatibility mode 'noattr2' can be emulated (-n) also.\n" "\n" msgstr "" #: .././db/attrset.c:90 .././db/attrset.c:193 msgid "current type is not inode\n" msgstr "" #: .././db/attrset.c:125 #, c-format msgid "bad attr_set valuelen %s\n" msgstr "" #: .././db/attrset.c:131 msgid "bad option for attr_set command\n" msgstr "" #: .././db/attrset.c:137 msgid "too few options for attr_set (no name given)\n" msgstr "" #: .././db/attrset.c:146 #, c-format msgid "cannot allocate buffer (%d)\n" msgstr "" #: .././db/attrset.c:155 .././db/attrset.c:230 #, c-format msgid "failed to iget inode %llu\n" msgstr "" #: .././db/attrset.c:162 #, c-format msgid "failed to set attr %s on inode %llu\n" msgstr "" #: .././db/attrset.c:217 msgid "bad option for attr_remove command\n" msgstr "" #: .././db/attrset.c:223 msgid "too few options for attr_remove (no name given)\n" msgstr "" #: .././db/attrset.c:236 #, c-format msgid "failed to remove attr %s from inode %llu\n" msgstr "" #: .././db/block.c:43 .././db/block.c:49 msgid "filoff" msgstr "" #: .././db/block.c:44 msgid "set address to file offset (attr fork)" msgstr "" #: .././db/block.c:46 msgid "[d]" msgstr "" #: .././db/block.c:47 msgid "set address to daddr value" msgstr "" #: .././db/block.c:50 msgid "set address to file offset (data fork)" msgstr "" #: .././db/block.c:52 msgid "[fsb]" msgstr "" #: .././db/block.c:53 msgid "set address to fsblock value" msgstr "" #: .././db/block.c:59 msgid "" "\n" " Example:\n" "\n" " 'ablock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's attribute fork. The filesystem block size is specified in\n" " the superblock.\n" "\n" msgstr "" #: .././db/block.c:82 .././db/block.c:177 #, c-format msgid "bad block number %s\n" msgstr "" #: .././db/block.c:90 msgid "no attribute data for file\n" msgstr "" #: .././db/block.c:96 msgid "file attr block is unmapped\n" msgstr "" #: .././db/block.c:119 msgid "" "\n" " Example:\n" "\n" " 'daddr 102' - sets position to the 102nd absolute disk block\n" " (512 byte block).\n" msgstr "" #: .././db/block.c:135 #, c-format msgid "current daddr is %lld\n" msgstr "" #: .././db/block.c:141 #, c-format msgid "bad daddr %s\n" msgstr "" #: .././db/block.c:153 msgid "" "\n" " Example:\n" "\n" " 'dblock 23' - sets the file position to the 23rd filesystem block in\n" " the inode's data fork. The filesystem block size is specified in the\n" " superblock.\n" "\n" msgstr "" #: .././db/block.c:185 msgid "no type for file data\n" msgstr "" #: .././db/block.c:192 msgid "file data block is unmapped\n" msgstr "" #: .././db/block.c:210 msgid "" "\n" " Example:\n" "\n" " 'fsblock 1023' - sets the file position to the 1023rd filesystem block.\n" " The filesystem block size is specified in the superblock and set during\n" " mkfs time. Offset is absolute (not AG relative).\n" "\n" msgstr "" #: .././db/block.c:229 #, c-format msgid "current fsblock is %lld\n" msgstr "" #: .././db/block.c:235 .././db/block.c:241 #, c-format msgid "bad fsblock %s\n" msgstr "" #: .././db/bmap.c:39 msgid "[-ad] [block [len]]" msgstr "" #: .././db/bmap.c:40 msgid "show block map for current file" msgstr "" #: .././db/bmap.c:152 .././db/inode.c:424 msgid "no current inode\n" msgstr "" #: .././db/bmap.c:165 msgid "bad option for bmap command\n" msgstr "" #: .././db/bmap.c:182 #, c-format msgid "bad block number for bmap %s\n" msgstr "" #: .././db/bmap.c:190 #, c-format msgid "bad len for bmap %s\n" msgstr "" #: .././db/bmap.c:213 #, c-format msgid "%s offset %lld startblock %llu (%u/%u) count %llu flag %u\n" msgstr "" #: .././db/bmap.c:215 .././db/check.c:2224 .././db/check.c:2236 #: .././db/check.c:2263 .././repair/dinode.c:52 msgid "data" msgstr "" #: .././db/bmap.c:215 .././db/check.c:2224 .././db/check.c:2236 #: .././db/check.c:2263 .././repair/dinode.c:53 msgid "attr" msgstr "" #: .././db/check.c:378 msgid "free block usage information" msgstr "" #: .././db/check.c:381 msgid "[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..." msgstr "" #: .././db/check.c:382 msgid "get block usage and check consistency" msgstr "" #: .././db/check.c:385 msgid "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ..." msgstr "" #: .././db/check.c:386 msgid "trash randomly selected block(s)" msgstr "" #: .././db/check.c:389 msgid "[-n] [-c blockcount]" msgstr "" #: .././db/check.c:390 msgid "print usage for current block(s)" msgstr "" #: .././db/check.c:393 msgid "[-s] [-i ino] ..." msgstr "" #: .././db/check.c:394 msgid "print inode-name pairs" msgstr "" #: .././db/check.c:414 #, c-format msgid "-i %lld bad inode number\n" msgstr "" #: .././db/check.c:426 #, c-format msgid "inode %lld add link, now %u\n" msgstr "" #: .././db/check.c:453 #, c-format msgid "inode %lld parent %lld\n" msgstr "" #: .././db/check.c:766 msgid "block usage information not allocated\n" msgstr "" #: .././db/check.c:804 msgid "already have block usage information\n" msgstr "" #: .././db/check.c:821 .././db/check.c:922 msgid "WARNING: this may be a newer XFS filesystem.\n" msgstr "" #: .././db/check.c:857 #, c-format msgid "sb_icount %lld, counted %lld\n" msgstr "" #: .././db/check.c:863 #, c-format msgid "sb_ifree %lld, counted %lld\n" msgstr "" #: .././db/check.c:869 #, c-format msgid "sb_fdblocks %lld, counted %lld\n" msgstr "" #: .././db/check.c:875 #, c-format msgid "sb_fdblocks %lld, aggregate AGF count %lld\n" msgstr "" #: .././db/check.c:881 #, c-format msgid "sb_frextents %lld, counted %lld\n" msgstr "" #: .././db/check.c:888 #, c-format msgid "sb_features2 (0x%x) not same as sb_bad_features2 (0x%x)\n" msgstr "" #: .././db/check.c:897 #, c-format msgid "sb versionnum missing attr bit %x\n" msgstr "" #: .././db/check.c:904 #, c-format msgid "sb versionnum missing quota bit %x\n" msgstr "" #: .././db/check.c:911 #, c-format msgid "sb versionnum extra align bit %x\n" msgstr "" #: .././db/check.c:950 msgid "zeroed" msgstr "" #: .././db/check.c:950 msgid "set" msgstr "" #: .././db/check.c:950 msgid "flipped" msgstr "" #: .././db/check.c:950 msgid "randomized" msgstr "" #: .././db/check.c:958 #, c-format msgid "zero-length block %u/%u buffer to trash??\n" msgstr "" #: .././db/check.c:977 #, c-format msgid "can't read block %u/%u for trashing\n" msgstr "" #: .././db/check.c:1006 #, c-format msgid "blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n" msgstr "" #: .././db/check.c:1085 #, c-format msgid "bad blocktrash count %s\n" msgstr "" #: .././db/check.c:1097 #, c-format msgid "bad blocktrash offset %s\n" msgstr "" #: .././db/check.c:1114 #, c-format msgid "bad blocktrash type %s\n" msgstr "" #: .././db/check.c:1123 #, c-format msgid "bad blocktrash min %s\n" msgstr "" #: .././db/check.c:1131 #, c-format msgid "bad blocktrash max %s\n" msgstr "" #: .././db/check.c:1139 msgid "bad option for blocktrash command\n" msgstr "" #: .././db/check.c:1144 .././db/check.c:1235 msgid "must run blockget first\n" msgstr "" #: .././db/check.c:1148 msgid "nothing on stack\n" msgstr "" #: .././db/check.c:1152 msgid "bad min/max for blocktrash command\n" msgstr "" #: .././db/check.c:1170 #, c-format msgid "blocktrash: seed %u\n" msgstr "" #: .././db/check.c:1186 msgid "blocktrash: no matching blocks\n" msgstr "" #: .././db/check.c:1250 #, c-format msgid "bad blockuse count %s\n" msgstr "" #: .././db/check.c:1256 .././db/check.c:1980 msgid "must run blockget -n first\n" msgstr "" #: .././db/check.c:1262 msgid "bad option for blockuse command\n" msgstr "" #: .././db/check.c:1269 #, c-format msgid "block %llu (%u/%u) type %s" msgstr "" #: .././db/check.c:1273 #, c-format msgid " inode %lld" msgstr "" #: .././db/check.c:1317 #, c-format msgid "block %u/%u expected type %s got %s\n" msgstr "" #: .././db/check.c:1350 #, c-format msgid "blocks %u/%u..%u claimed by inode %lld\n" msgstr "" #: .././db/check.c:1358 #, c-format msgid "block %u/%u claimed by inode %lld, previous inum %lld\n" msgstr "" #: .././db/check.c:1387 #, c-format msgid "link count mismatch for inode %lld (name %s), nlink %d, counted %d\n" msgstr "" #: .././db/check.c:1395 #, c-format msgid "disconnected inode %lld, nlink %d\n" msgstr "" #: .././db/check.c:1399 #, c-format msgid "allocated inode %lld has 0 link count\n" msgstr "" #: .././db/check.c:1409 #, c-format msgid "inode %lld name %s\n" msgstr "" #: .././db/check.c:1443 .././db/check.c:1458 #, c-format msgid "block %u/%u out of range\n" msgstr "" #: .././db/check.c:1446 .././db/check.c:1461 #, c-format msgid "blocks %u/%u..%u out of range\n" msgstr "" #: .././db/check.c:1484 #, c-format msgid "rtblock %llu expected type %s got %s\n" msgstr "" #: .././db/check.c:1504 #, c-format msgid "rtblocks %llu..%llu claimed by inode %lld\n" msgstr "" #: .././db/check.c:1513 #, c-format msgid "rtblock %llu claimed by inode %lld, previous inum %lld\n" msgstr "" #: .././db/check.c:1531 #, c-format msgid "root inode %lld is missing\n" msgstr "" #: .././db/check.c:1536 #, c-format msgid "root inode %lld is not a directory\n" msgstr "" #: .././db/check.c:1552 #, c-format msgid "rtblock %llu out of range\n" msgstr "" #: .././db/check.c:1596 #, c-format msgid "blocks %u/%u..%u claimed by block %u/%u\n" msgstr "" #: .././db/check.c:1610 #, c-format msgid "setting block %u/%u to %s\n" msgstr "" #: .././db/check.c:1633 #, c-format msgid "setting rtblock %llu to %s\n" msgstr "" #: .././db/check.c:1654 .././repair/rt.c:151 #, c-format msgid "rt summary mismatch, size %d block %llu, file: %d, computed: %d\n" msgstr "" #: .././db/check.c:1679 #, c-format msgid "block %u/%u type %s not expected\n" msgstr "" #: .././db/check.c:1700 #, c-format msgid "rtblock %llu type %s not expected\n" msgstr "" #: .././db/check.c:1737 #, c-format msgid "dir ino %lld missing leaf entry for %x/%x\n" msgstr "" #: .././db/check.c:1856 #, c-format msgid "bad superblock magic number %x, giving up\n" msgstr "" #: .././db/check.c:1910 msgid "bad option for blockget command\n" msgstr "" #: .././db/check.c:1997 #, c-format msgid "bad option -%c for ncheck command\n" msgstr "" #: .././db/check.c:2071 #, c-format msgid "block 0 for directory inode %lld is missing\n" msgstr "" #: .././db/check.c:2091 #, c-format msgid "can't read block 0 for directory inode %lld\n" msgstr "" #: .././db/check.c:2137 #, c-format msgid "inode %lld extent [%lld,%lld,%lld,%d]\n" msgstr "" #: .././db/check.c:2140 #, c-format msgid "bmap rec out of order, inode %lld entry %d\n" msgstr "" #: .././db/check.c:2146 #, c-format msgid "inode %lld bad rt block number %lld, offset %lld\n" msgstr "" #: .././db/check.c:2156 .././db/check.c:2162 #, c-format msgid "inode %lld bad block number %lld [%d,%d], offset %lld\n" msgstr "" #: .././db/check.c:2180 .././db/check.c:2194 #, c-format msgid "inode %lld block %lld at offset %lld\n" msgstr "" #: .././db/check.c:2221 #, c-format msgid "level for ino %lld %s fork bmap root too large (%u)\n" msgstr "" #: .././db/check.c:2233 #, c-format msgid "numrecs for ino %lld %s fork bmap root too large (%u)\n" msgstr "" #: .././db/check.c:2260 #, c-format msgid "extent count for ino %lld %s fork too low (%d) for file format\n" msgstr "" #: .././db/check.c:2312 .././db/check.c:3338 #, c-format msgid "bad directory data magic # %#x for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:2330 #, c-format msgid "bad block directory tail for dir ino %lld\n" msgstr "" #: .././db/check.c:2375 #, c-format msgid "dir %lld block %d bad free entry at %d\n" msgstr "" #: .././db/check.c:2399 #, c-format msgid "dir %lld block %d zero length entry at %d\n" msgstr "" #: .././db/check.c:2408 #, c-format msgid "dir %lld block %d bad entry at %d\n" msgstr "" #: .././db/check.c:2426 #, c-format msgid "dir %lld block %d entry %*.*s %lld\n" msgstr "" #: .././db/check.c:2433 #, c-format msgid "dir %lld block %d entry %*.*s bad inode number %lld\n" msgstr "" #: .././db/check.c:2443 #, c-format msgid "multiple .. entries in dir %lld (%lld, %lld)\n" msgstr "" #: .././db/check.c:2460 #, c-format msgid "dir %lld entry . inode number mismatch (%lld)\n" msgstr "" #: .././db/check.c:2474 #, c-format msgid "dir %lld block %d bad count %u\n" msgstr "" #: .././db/check.c:2485 .././db/check.c:3352 #, c-format msgid "dir %lld block %d extra leaf entry %x %x\n" msgstr "" #: .././db/check.c:2497 #, c-format msgid "dir %lld block %d bad bestfree data\n" msgstr "" #: .././db/check.c:2505 #, c-format msgid "dir %lld block %d bad block tail count %d (stale %d)\n" msgstr "" #: .././db/check.c:2515 #, c-format msgid "dir %lld block %d bad stale tail count %d\n" msgstr "" #: .././db/check.c:2521 #, c-format msgid "dir %lld block %d consecutive free entries\n" msgstr "" #: .././db/check.c:2527 #, c-format msgid "dir %lld block %d entry/unused tag mismatch\n" msgstr "" #: .././db/check.c:2576 #, c-format msgid "no . entry for directory %lld\n" msgstr "" #: .././db/check.c:2581 #, c-format msgid "no .. entry for directory %lld\n" msgstr "" #: .././db/check.c:2585 #, c-format msgid ". and .. same for non-root directory %lld\n" msgstr "" #: .././db/check.c:2590 #, c-format msgid "root directory %lld has .. %lld\n" msgstr "" #: .././db/check.c:2623 #, c-format msgid "bad size (%lld) or format (%d) for directory inode %lld\n" msgstr "" #: .././db/check.c:2651 #, c-format msgid "bad number of extents %d for inode %lld\n" msgstr "" #: .././db/check.c:2723 #, c-format msgid "bad magic number %#x for inode %lld\n" msgstr "" #: .././db/check.c:2730 #, c-format msgid "bad version number %#x for inode %lld\n" msgstr "" #: .././db/check.c:2738 #, c-format msgid "bad nblocks %lld for free inode %lld\n" msgstr "" #: .././db/check.c:2745 #, c-format msgid "bad nlink %d for free inode %lld\n" msgstr "" #: .././db/check.c:2751 #, c-format msgid "bad mode %#o for free inode %lld\n" msgstr "" #: .././db/check.c:2760 #, c-format msgid "bad next unlinked %#x for inode %lld\n" msgstr "" #: .././db/check.c:2771 #, c-format msgid "bad format %d for inode %lld type %#o\n" msgstr "" #: .././db/check.c:2779 #, c-format msgid "bad fork offset %d for inode %lld\n" msgstr "" #: .././db/check.c:2786 #, c-format msgid "bad attribute format %d for inode %lld\n" msgstr "" #: .././db/check.c:2792 #, c-format msgid "" "inode %lld mode %#o fmt %s afmt %s nex %d anex %d nblk %lld sz %lld%s%s%s%s%s" "%s%s\n" msgstr "" #: .././db/check.c:2911 #, c-format msgid "bad nblocks %lld for inode %lld, counted %lld\n" msgstr "" #: .././db/check.c:2918 #, c-format msgid "bad nextents %d for inode %lld, counted %d\n" msgstr "" #: .././db/check.c:2924 #, c-format msgid "bad anextents %d for inode %lld, counted %d\n" msgstr "" #: .././db/check.c:2976 #, c-format msgid "local inode %lld data is too large (size %lld)\n" msgstr "" #: .././db/check.c:2985 #, c-format msgid "local inode %lld attr is too large (size %d)\n" msgstr "" #: .././db/check.c:3034 #, c-format msgid "dir inode %lld block %u=%llu\n" msgstr "" #: .././db/check.c:3046 #, c-format msgid "can't read block %u for directory inode %lld\n" msgstr "" #: .././db/check.c:3060 #, c-format msgid "multiple .. entries in dir %lld\n" msgstr "" #: .././db/check.c:3082 #, c-format msgid "missing free index for data block %d in dir ino %lld\n" msgstr "" #: .././db/check.c:3110 .././db/check.c:3188 #, c-format msgid "bad free block firstdb %d for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:3121 .././db/check.c:3201 #, c-format msgid "bad free block nvalid/nused %d/%d for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:3135 .././db/check.c:3215 #, c-format msgid "bad free block ent %d is %d should be %d for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:3149 .././db/check.c:3229 #, c-format msgid "bad free block nused %d should be %d for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:3174 #, c-format msgid "bad free block magic # %#x for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:3283 #, c-format msgid "bad leaf block forw/back pointers %d/%d for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:3292 #, c-format msgid "single leaf block for dir ino %lld block %d should be at block %d\n" msgstr "" #: .././db/check.c:3304 #, c-format msgid "bestfree %d for dir ino %lld block %d doesn't match table value %d\n" msgstr "" #: .././db/check.c:3329 #, c-format msgid "bad node block level %d for dir ino %lld block %d\n" msgstr "" #: .././db/check.c:3361 #, c-format msgid "dir3 %lld block %d stale mismatch %d/%d\n" msgstr "" #: .././db/check.c:3368 #, c-format msgid "dir %lld block %d stale mismatch %d/%d\n" msgstr "" #: .././db/check.c:3424 #, c-format msgid "can't read block %lld for %s quota inode (fsblock %lld)\n" msgstr "" #: .././db/check.c:3434 #, c-format msgid "%s dqblk %lld entry %d id %u bc %lld ic %lld rc %lld\n" msgstr "" #: .././db/check.c:3442 #, c-format msgid "bad magic number %#x for %s dqblk %lld entry %d id %u\n" msgstr "" #: .././db/check.c:3451 #, c-format msgid "bad version number %#x for %s dqblk %lld entry %d id %u\n" msgstr "" #: .././db/check.c:3461 #, c-format msgid "bad flags %#x for %s dqblk %lld entry %d id %u\n" msgstr "" #: .././db/check.c:3470 #, c-format msgid "bad id %u for %s dqblk %lld entry %d id %u\n" msgstr "" #: .././db/check.c:3516 #, c-format msgid "block %lld for rtbitmap inode is missing\n" msgstr "" #: .././db/check.c:3527 #, c-format msgid "can't read block %lld for rtbitmap inode\n" msgstr "" #: .././db/check.c:3583 #, c-format msgid "block %lld for rtsummary inode is missing\n" msgstr "" #: .././db/check.c:3594 #, c-format msgid "can't read block %lld for rtsummary inode\n" msgstr "" #: .././db/check.c:3627 #, c-format msgid "dir %lld entry . %lld\n" msgstr "" #: .././db/check.c:3635 #, c-format msgid "dir %llu bad size in entry at %d\n" msgstr "" #: .././db/check.c:3647 #, c-format msgid "dir %lld entry %*.*s bad inode number %lld\n" msgstr "" #: .././db/check.c:3659 #, c-format msgid "dir %lld entry %*.*s offset %d %lld\n" msgstr "" #: .././db/check.c:3664 #, c-format msgid "dir %lld entry %*.*s bad offset %d\n" msgstr "" #: .././db/check.c:3677 #, c-format msgid "dir %llu size is %lld, should be %u\n" msgstr "" #: .././db/check.c:3685 #, c-format msgid "dir %llu offsets too high\n" msgstr "" #: .././db/check.c:3696 #, c-format msgid "dir %lld entry .. bad inode number %lld\n" msgstr "" #: .././db/check.c:3701 #, c-format msgid "dir %lld entry .. %lld\n" msgstr "" #: .././db/check.c:3704 #, c-format msgid "dir %lld i8count mismatch is %d should be %d\n" msgstr "" #: .././db/check.c:3786 #, c-format msgid "%s quota id %u, have/exp" msgstr "" #: .././db/check.c:3789 #, c-format msgid " bc %lld/%lld" msgstr "" #: .././db/check.c:3793 #, c-format msgid " ic %lld/%lld" msgstr "" #: .././db/check.c:3797 #, c-format msgid " rc %lld/%lld" msgstr "" #: .././db/check.c:3853 #, c-format msgid "can't read superblock for ag %u\n" msgstr "" #: .././db/check.c:3862 #, c-format msgid "bad sb magic # %#x in ag %u\n" msgstr "" #: .././db/check.c:3868 #, c-format msgid "bad sb version # %#x in ag %u\n" msgstr "" #: .././db/check.c:3878 .././db/sb.c:217 msgid "mkfs not completed successfully\n" msgstr "" #: .././db/check.c:3890 .././db/frag.c:370 #, c-format msgid "can't read agf block for ag %u\n" msgstr "" #: .././db/check.c:3896 #, c-format msgid "bad agf magic # %#x in ag %u\n" msgstr "" #: .././db/check.c:3902 #, c-format msgid "bad agf version # %#x in ag %u\n" msgstr "" #: .././db/check.c:3918 .././db/frag.c:379 #, c-format msgid "can't read agi block for ag %u\n" msgstr "" #: .././db/check.c:3924 #, c-format msgid "bad agi magic # %#x in ag %u\n" msgstr "" #: .././db/check.c:3930 #, c-format msgid "bad agi version # %#x in ag %u\n" msgstr "" #: .././db/check.c:3973 .././repair/scan.c:2252 #, c-format msgid "agf_freeblks %u, counted %u in ag %u\n" msgstr "" #: .././db/check.c:3980 .././repair/scan.c:2257 #, c-format msgid "agf_longest %u, counted %u in ag %u\n" msgstr "" #: .././db/check.c:3988 #, c-format msgid "agf_btreeblks %u, counted %u in ag %u\n" msgstr "" #: .././db/check.c:3996 .././repair/scan.c:2306 #, c-format msgid "agi_count %u, counted %u in ag %u\n" msgstr "" #: .././db/check.c:4003 .././repair/scan.c:2311 #, c-format msgid "agi_freecount %u, counted %u in ag %u\n" msgstr "" #: .././db/check.c:4012 #, c-format msgid "agi unlinked bucket %d is %u in ag %u (inode=%lld)\n" msgstr "" #: .././db/check.c:4050 #, c-format msgid "can't read agfl block for ag %u\n" msgstr "" #: .././db/check.c:4060 .././db/freesp.c:255 .././repair/scan.c:2142 #, c-format msgid "agf %d freelist blocks bad, skipping freelist scan\n" msgstr "" #: .././db/check.c:4082 #, c-format msgid "freeblk count %u != flcount %u in ag %u\n" msgstr "" #: .././db/check.c:4111 .././db/check.c:4139 .././db/frag.c:402 #: .././db/frag.c:425 .././db/freesp.c:289 #, c-format msgid "can't read btree block %u/%u\n" msgstr "" #: .././db/check.c:4173 #, c-format msgid "bad magic # %#x in inode %lld bmbt block %u/%u\n" msgstr "" #: .././db/check.c:4180 #, c-format msgid "expected level %d got %d in inode %lld bmbt block %u/%u\n" msgstr "" #: .././db/check.c:4192 .././db/check.c:4209 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in inode %lld bmap block %lld\n" msgstr "" #: .././db/check.c:4238 #, c-format msgid "bad magic # %#x in btbno block %u/%u\n" msgstr "" #: .././db/check.c:4247 #, c-format msgid "expected level %d got %d in btbno block %u/%u\n" msgstr "" #: .././db/check.c:4256 .././db/check.c:4284 .././db/check.c:4330 #: .././db/check.c:4361 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in btbno block %u/%u\n" msgstr "" #: .././db/check.c:4271 .././repair/scan.c:666 #, c-format msgid "out-of-order bno btree record %d (%u %u) block %u/%u\n" msgstr "" #: .././db/check.c:4312 #, c-format msgid "bad magic # %#x in btcnt block %u/%u\n" msgstr "" #: .././db/check.c:4321 #, c-format msgid "expected level %d got %d in btcnt block %u/%u\n" msgstr "" #: .././db/check.c:4349 .././repair/scan.c:678 #, c-format msgid "out-of-order cnt btree record %d (%u %u) block %u/%u\n" msgstr "" #: .././db/check.c:4407 #, c-format msgid "bad magic # %#x in inobt block %u/%u\n" msgstr "" #: .././db/check.c:4414 #, c-format msgid "expected level %d got %d in inobt block %u/%u\n" msgstr "" #: .././db/check.c:4423 .././db/check.c:4509 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in inobt block %u/%u\n" msgstr "" #: .././db/check.c:4466 .././db/frag.c:494 #, c-format msgid "can't read inode block %u/%u\n" msgstr "" #: .././db/check.c:4497 #, c-format msgid "ir_freecount/free mismatch, inode chunk %u/%u, freecount %d nfree %d\n" msgstr "" #: .././db/check.c:4550 #, c-format msgid "bad magic # %#x in finobt block %u/%u\n" msgstr "" #: .././db/check.c:4557 #, c-format msgid "expected level %d got %d in finobt block %u/%u\n" msgstr "" #: .././db/check.c:4566 .././db/check.c:4609 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in finobt block %u/%u\n" msgstr "" #: .././db/check.c:4636 #, c-format msgid "bad magic # %#x in rmapbt block %u/%u\n" msgstr "" #: .././db/check.c:4643 #, c-format msgid "expected level %d got %d in rmapbt block %u/%u\n" msgstr "" #: .././db/check.c:4656 .././db/check.c:4680 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in rmapbt block %u/%u\n" msgstr "" #: .././db/check.c:4668 #, c-format msgid "out-of-order rmap btree record %d (%u %u) block %u/%u\n" msgstr "" #: .././db/check.c:4708 #, c-format msgid "bad magic # %#x in refcntbt block %u/%u\n" msgstr "" #: .././db/check.c:4715 #, c-format msgid "expected level %d got %d in refcntbt block %u/%u\n" msgstr "" #: .././db/check.c:4724 .././db/check.c:4765 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in refcntbt block %u/%u\n" msgstr "" #: .././db/check.c:4736 .././repair/scan.c:1350 #, c-format msgid "leftover CoW extent (%u/%u) len %u\n" msgstr "" #: .././db/check.c:4752 #, c-format msgid "out-of-order refcnt btree record %d (%u %u) block %u/%u\n" msgstr "" #: .././db/check.c:4808 #, c-format msgid "setting inode to %lld for block %u/%u\n" msgstr "" #: .././db/check.c:4840 #, c-format msgid "setting inode to %lld for rtblock %llu\n" msgstr "" #: .././db/check.c:4856 #, c-format msgid "inode %lld nlink %u %s dir\n" msgstr "" #: .././db/command.c:85 .././db/help.c:56 .././libxcmd/help.c:50 #, c-format msgid "command %s not found\n" msgstr "" #: .././db/command.c:89 #, c-format msgid "bad argument count %d to %s, expected " msgstr "" #: .././db/command.c:91 #, c-format msgid "at least %d" msgstr "" #: .././db/command.c:95 #, c-format msgid "between %d and %d" msgstr "" #: .././db/command.c:96 msgid " arguments\n" msgstr "" #: .././db/convert.c:171 #, c-format msgid "bad argument count %d to convert, expected 3,5,7,9 arguments\n" msgstr "" #: .././db/convert.c:176 .././db/convert.c:183 #, c-format msgid "unknown conversion type %s\n" msgstr "" #: .././db/convert.c:187 msgid "result type same as argument\n" msgstr "" #: .././db/convert.c:191 #, c-format msgid "conflicting conversion type %s\n" msgstr "" #: .././db/convert.c:269 #, c-format msgid "%s is not a number\n" msgstr "" #: .././db/crc.c:37 msgid "manipulate crc values for V5 filesystem structures" msgstr "" #: .././db/crc.c:50 msgid "" "\n" " 'crc' validates, invalidates, or recalculates the crc value for\n" " the current on-disk metadata structures in Version 5 filesystems.\n" "\n" " Usage: \"crc [-i|-r|-v]\"\n" "\n" msgstr "" #: .././db/crc.c:81 #, c-format msgid "current type (%s) is not a structure\n" msgstr "" #: .././db/crc.c:98 msgid "bad option for crc command\n" msgstr "" #: .././db/crc.c:105 msgid "crc command accepts only one option\n" msgstr "" #: .././db/crc.c:111 #, c-format msgid "%s not in expert mode, writing disabled\n" msgstr "" #: .././db/crc.c:128 #, c-format msgid "No CRC field found for type %s\n" msgstr "" #: .././db/crc.c:135 .././db/write.c:693 msgid "parsing error\n" msgstr "" #: .././db/crc.c:171 msgid "Invalidating CRC:\n" msgstr "" #: .././db/crc.c:173 msgid "Recalculating CRC:\n" msgstr "" #: .././db/crc.c:181 msgid "Verifying CRC:\n" msgstr "" #: .././db/debug.c:27 msgid "[flagbits]" msgstr "" #: .././db/debug.c:28 msgid "set debug option bits" msgstr "" #: .././db/debug.c:42 #, c-format msgid "bad value for debug %s\n" msgstr "" #: .././db/dir2.c:1023 msgid "Unknown directory buffer type!\n" msgstr "" #: .././db/dir2.c:1035 msgid "Writing unknown directory buffer type!\n" msgstr "" #: .././db/dquot.c:37 msgid "[-g|-p|-u] id" msgstr "" #: .././db/dquot.c:38 msgid "" "set current address to a group, project or user quota block for given ID" msgstr "" #: .././db/dquot.c:129 msgid "bad option for dquot command\n" msgstr "" #: .././db/dquot.c:133 msgid "project" msgstr "" #: .././db/dquot.c:133 msgid "group" msgstr "" #: .././db/dquot.c:133 msgid "user" msgstr "" #: .././db/dquot.c:135 #, c-format msgid "dquot command requires one %s id argument\n" msgstr "" #: .././db/dquot.c:145 #, c-format msgid "no %s quota inode present\n" msgstr "" #: .././db/dquot.c:150 #, c-format msgid "bad %s id for dquot %s\n" msgstr "" #: .././db/dquot.c:162 #, c-format msgid "no %s quota data for id %d\n" msgstr "" #: .././db/echo.c:27 msgid "[args]..." msgstr "" #: .././db/echo.c:28 msgid "echo arguments" msgstr "" #: .././db/faddr.c:40 .././db/faddr.c:63 msgid "no current allocation group, cannot set new addr\n" msgstr "" #: .././db/faddr.c:45 .././db/faddr.c:117 .././db/faddr.c:148 #: .././db/faddr.c:180 .././db/faddr.c:202 .././db/faddr.c:232 #: .././db/faddr.c:262 .././db/faddr.c:316 .././db/faddr.c:335 msgid "null block number, cannot set new addr\n" msgstr "" #: .././db/faddr.c:68 .././db/faddr.c:353 .././db/faddr.c:370 #: .././db/faddr.c:387 msgid "null inode number, cannot set new addr\n" msgstr "" #: .././db/faddr.c:88 msgid "null attribute block number, cannot set new addr\n" msgstr "" #: .././db/faddr.c:94 msgid "attribute block is unmapped\n" msgstr "" #: .././db/faddr.c:123 .././db/faddr.c:155 .././db/faddr.c:208 #: .././db/faddr.c:239 msgid "file block is unmapped\n" msgstr "" #: .././db/faddr.c:285 msgid "null directory block number, cannot set new addr\n" msgstr "" #: .././db/faddr.c:292 msgid "directory block is unmapped\n" msgstr "" #: .././db/flist.c:149 #, c-format msgid "field %s not found\n" msgstr "" #: .././db/flist.c:159 #, c-format msgid "no elements in %s\n" msgstr "" #: .././db/flist.c:165 #, c-format msgid "indices %d-%d for field %s out of range %d-%d\n" msgstr "" #: .././db/flist.c:173 #, c-format msgid "index %d for field %s out of range %d-%d\n" msgstr "" #: .././db/flist.c:187 #, c-format msgid "field %s is not an array\n" msgstr "" #: .././db/flist.c:200 #, c-format msgid "field %s has no subfields\n" msgstr "" #: .././db/flist.c:220 #, c-format msgid "fl@%p:\n" msgstr "" #: .././db/flist.c:221 #, c-format msgid "\tname=%s, fld=%p, child=%p, sibling=%p\n" msgstr "" #: .././db/flist.c:223 #, c-format msgid "\tlow=%d, high=%d, flags=%d (%s%s), offset=%d\n" msgstr "" #: .././db/flist.c:225 msgid "oklow " msgstr "" #: .././db/flist.c:226 msgid "okhigh" msgstr "" #: .././db/flist.c:227 #, c-format msgid "\tfld->name=%s, fld->ftyp=%d (%s)\n" msgstr "" #: .././db/flist.c:230 #, c-format msgid "\tfld->flags=%d (%s%s%s%s%s)\n" msgstr "" #: .././db/flist.c:322 #, c-format msgid "bad syntax in field name %s\n" msgstr "" #: .././db/flist.c:378 #, c-format msgid "missing closing quote %s\n" msgstr "" #: .././db/flist.c:395 #, c-format msgid "bad character in field %s\n" msgstr "" #: .././db/fprint.c:99 msgid "null" msgstr "" #: .././db/frag.c:173 #, c-format msgid "actual %llu, ideal %llu, fragmentation factor %.2f%%\n" msgstr "" #: .././db/frag.c:175 msgid "Note, this number is largely meaningless.\n" msgstr "" #: .././db/frag.c:177 #, c-format msgid "Files on this filesystem average %.2f extents per file\n" msgstr "" #: .././db/frag.c:218 msgid "bad option for frag command\n" msgstr "" #: .././db/frag.c:354 #, c-format msgid "inode %lld actual %lld ideal %lld\n" msgstr "" #: .././db/frag.c:448 .././db/frag.c:458 #, c-format msgid "invalid numrecs (%u) in %s block\n" msgstr "" #: .././db/freesp.c:110 #, c-format msgid "total free extents %lld\n" msgstr "" #: .././db/freesp.c:111 #, c-format msgid "total free blocks %lld\n" msgstr "" #: .././db/freesp.c:112 #, c-format msgid "average free extent size %g\n" msgstr "" #: .././db/freesp.c:203 msgid "" "freesp arguments: [-bcds] [-a agno] [-e binsize] [-h h1]... [-m binmult]\n" msgstr "" #: .././db/freesp.c:427 msgid "from" msgstr "" #: .././db/freesp.c:427 msgid "to" msgstr "" #: .././db/freesp.c:427 .././repair/progress.c:26 msgid "extents" msgstr "" #: .././db/freesp.c:427 .././repair/progress.c:18 msgid "blocks" msgstr "" #: .././db/freesp.c:427 msgid "pct" msgstr "" #: .././db/fsmap.c:39 #, c-format msgid "" "%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n" msgstr "" #: .././db/fsmap.c:86 #, c-format msgid "Error %d while reading AGF.\n" msgstr "" #: .././db/fsmap.c:93 msgid "Not enough memory.\n" msgstr "" #: .././db/fsmap.c:103 #, c-format msgid "Error %d while querying fsmap btree.\n" msgstr "" #: .././db/fsmap.c:127 msgid "Filesystem does not support reverse mapping btree.\n" msgstr "" #: .././db/fsmap.c:134 msgid "Bad option for fsmap command.\n" msgstr "" #: .././db/fsmap.c:142 #, c-format msgid "Bad fsmap start_fsb %s.\n" msgstr "" #: .././db/fsmap.c:150 #, c-format msgid "Bad fsmap end_fsb %s.\n" msgstr "" #: .././db/fsmap.c:162 msgid "[start_fsb] [end_fsb]" msgstr "" #: .././db/fsmap.c:163 msgid "display reverse mapping(s)" msgstr "" #: .././db/hash.c:30 msgid "string" msgstr "" #: .././db/hash.c:31 msgid "calculate hash value" msgstr "" #: .././db/hash.c:37 msgid "" "\n" " 'hash' prints out the calculated hash value for a string using the\n" "directory/attribute code hash function.\n" "\n" " Usage: \"hash \"\n" "\n" msgstr "" #: .././db/help.c:30 .././db/io.c:49 .././libxcmd/help.c:93 msgid "[command]" msgstr "" #: .././db/help.c:31 .././libxcmd/help.c:94 msgid "help for one or all commands" msgstr "" #: .././db/help.c:40 .././libxcmd/help.c:34 #, c-format msgid "" "\n" "Use 'help commandname' for extended help.\n" msgstr "" #: .././db/help.c:89 #, c-format msgid "(or %s) " msgstr "" #: .././db/init.c:49 #, c-format msgid "Usage: %s [-ifFrxV] [-p prog] [-l logdev] [-c cmd]... device\n" msgstr "" #: .././db/init.c:116 msgid "" "\n" "fatal error -- couldn't initialize XFS library\n" msgstr "" #: .././db/init.c:131 #, c-format msgid "%s: %s is invalid (cannot read first 512 bytes)\n" msgstr "" #: .././db/init.c:143 #, c-format msgid "" "%s: %s is not a valid XFS filesystem (unexpected SB magic number 0x%08x)\n" msgstr "" #: .././db/init.c:146 #, c-format msgid "Use -F to force a read attempt.\n" msgstr "" #: .././db/init.c:155 #, c-format msgid "%s: device %s unusable (not an XFS filesystem?)\n" msgstr "" #: .././db/init.c:170 #, c-format msgid "%s: cannot init perag data (%d). Continuing anyway.\n" msgstr "" #: .././db/inode.c:419 #, c-format msgid "bad value for inode number %s\n" msgstr "" #: .././db/inode.c:426 #, c-format msgid "current inode number is %lld\n" msgstr "" #: .././db/inode.c:660 #, c-format msgid "bad inode number %lld\n" msgstr "" #: .././db/inode.c:707 #, c-format msgid "Metadata CRC error detected for ino %lld\n" msgstr "" #: .././db/input.c:43 msgid "source-file" msgstr "" #: .././db/input.c:44 msgid "get commands from source-file" msgstr "" #: .././db/input.c:320 #, c-format msgid "can't open %s\n" msgstr "" #: .././db/io.c:47 msgid "pop location from the stack" msgstr "" #: .././db/io.c:50 msgid "push location to the stack" msgstr "" #: .././db/io.c:53 msgid "view the location stack" msgstr "" #: .././db/io.c:56 msgid "move forward to next entry in the position ring" msgstr "" #: .././db/io.c:59 msgid "move to the previous location in the position ring" msgstr "" #: .././db/io.c:62 msgid "show position ring or move to a specific entry" msgstr "" #: .././db/io.c:92 #, c-format msgid "can't set block offset to %d\n" msgstr "" #: .././db/io.c:105 msgid "can't pop anything from I/O stack\n" msgstr "" #: .././db/io.c:139 msgid "" "\n" " Changes the address and data type to the first entry on the stack.\n" "\n" msgstr "" #: .././db/io.c:153 #, c-format msgid "\tbyte offset %lld, length %d\n" msgstr "" #: .././db/io.c:154 #, c-format msgid "\tbuffer block %lld (fsbno %lld), %d bb%s\n" msgstr "" #: .././db/io.c:158 .././db/io.c:544 #, c-format msgid "\tblock map" msgstr "" #: .././db/io.c:164 #, c-format msgid "\tinode %lld, dir inode %lld, type %s\n" msgstr "" #: .././db/io.c:165 .././growfs/xfs_growfs.c:88 .././logprint/log_misc.c:107 #: .././mkfs/xfs_mkfs.c:2366 #, c-format msgid "none" msgstr "" #: .././db/io.c:175 msgid "no entries in location ring.\n" msgstr "" #: .././db/io.c:179 msgid " type bblock bblen fsbno inode\n" msgstr "" #: .././db/io.c:233 #, c-format msgid "no such command %s\n" msgstr "" #: .././db/io.c:237 #, c-format msgid "no push form allowed for %s\n" msgstr "" #: .././db/io.c:261 msgid "" "\n" " Allows you to push the current address and data type on the stack for\n" " later return. 'push' also accepts an additional command to execute after\n" " storing the current address (ex: 'push a rootino' from the superblock).\n" "\n" msgstr "" #: .././db/io.c:277 .././db/io.c:317 msgid "ring is empty\n" msgstr "" #: .././db/io.c:281 msgid "no further entries\n" msgstr "" #: .././db/io.c:300 msgid "" "\n" " The 'forward' ('f') command moves to the next location in the position\n" " ring, updating the current position and data type. If the current " "location\n" " is the top entry in the ring, then the 'forward' command will have\n" " no effect.\n" "\n" msgstr "" #: .././db/io.c:321 msgid "no previous entries\n" msgstr "" #: .././db/io.c:340 msgid "" "\n" " The 'back' ('b') command moves to the previous location in the position\n" " ring, updating the current position and data type. If the current " "location\n" " is the last entry in the ring, then the 'back' command will have no " "effect.\n" "\n" msgstr "" #: .././db/io.c:363 #, c-format msgid "invalid entry: %d\n" msgstr "" #: .././db/io.c:382 #, c-format msgid "" "\n" " The position ring automatically keeps track of each disk location and\n" " structure type for each change of position you make during your xfs_db\n" " session. The last %d most recent entries are kept in the ring.\n" "\n" " To display the current list of ring entries type 'ring' by itself on\n" " the command line. The entry highlighted by an asterisk ('*') is the\n" " current entry.\n" "\n" " To move to another entry in the ring type 'ring ' where is\n" " your desired entry from the ring position list.\n" "\n" " You may also use the 'forward' ('f') or 'back' ('b') commands to move\n" " to the previous or next entry in the ring, respectively.\n" "\n" " Note: Unlike the 'stack', 'push' and 'pop' commands, the ring tracks your\n" " location implicitly. Use the 'push' and 'pop' commands if you wish to\n" " store a specific location explicitly for later return.\n" "\n" msgstr "" #: .././db/io.c:435 .././db/io.c:451 #, c-format msgid "write error: %s\n" msgstr "" #: .././db/io.c:441 .././db/io.c:457 #, c-format msgid "read error: %s\n" msgstr "" #: .././db/io.c:480 msgid "nothing to write\n" msgstr "" #: .././db/io.c:529 msgid "set_cur no stack element to set\n" msgstr "" #: .././db/io.c:543 #, c-format msgid "xfs_db got a bbmap for %lld\n" msgstr "" #: .././db/io.c:619 msgid "" "\n" " The stack is used to explicitly store your location and data type\n" " for later return. The 'push' operation stores the current address\n" " and type on the stack, the 'pop' operation returns you to the\n" " position and datatype of the top entry on the stack.\n" "\n" " The 'stack' allows explicit location saves, see 'ring' for implicit\n" " position tracking.\n" "\n" msgstr "" #: .././db/logformat.c:89 msgid "The log is dirty. Please mount to replay the log.\n" msgstr "" #: .././db/logformat.c:121 msgid "" "\n" " The 'logformat' command reformats (clears) the log to the specified log\n" " cycle and log stripe unit. If the log cycle is not specified, the log is\n" " reformatted to the current cycle. If the log stripe unit is not specified,\n" " the stripe unit from the filesystem superblock is used.\n" "\n" msgstr "" #: .././db/logformat.c:137 msgid "[-c cycle] [-s sunit]" msgstr "" #: .././db/logformat.c:138 msgid "reformat the log" msgstr "" #: .././db/malloc.c:27 #, c-format msgid "%s: out of memory\n" msgstr "" #: .././db/metadump.c:60 msgid "[-a] [-e] [-g] [-m max_extent] [-w] [-o] filename" msgstr "" #: .././db/metadump.c:61 msgid "dump metadata to a file" msgstr "" #: .././db/metadump.c:92 #, c-format msgid "" "\n" " The 'metadump' command dumps the known metadata to a compact file suitable\n" " for compressing and sending to an XFS maintainer for corruption analysis \n" " or xfs_repair failures.\n" "\n" " Options:\n" " -a -- Copy full metadata blocks without zeroing unused space\n" " -e -- Ignore read errors and keep going\n" " -g -- Display dump progress\n" " -m -- Specify max extent size in blocks to copy (default = %d blocks)\n" " -o -- Don't obfuscate names and extended attributes\n" " -w -- Show warnings of bad metadata information\n" "\n" msgstr "" #: .././db/metadump.c:2728 msgid "" "Filesystem log is dirty; image will contain unobfuscated metadata in log." msgstr "" #: .././db/metadump.c:2734 msgid "Could not discern log; image will contain unobfuscated metadata in log." msgstr "" #: .././db/output.c:30 msgid "[stop|start ]" msgstr "" #: .././db/output.c:31 msgid "start or stop logging to a file" msgstr "" #: .././db/output.c:68 #, c-format msgid "logging to %s\n" msgstr "" #: .././db/output.c:70 .././db/output.c:77 msgid "no log file\n" msgstr "" #: .././db/output.c:80 #, c-format msgid "already logging to %s\n" msgstr "" #: .././db/output.c:84 #, c-format msgid "can't open %s for writing\n" msgstr "" #: .././db/output.c:90 msgid "bad log command, ignored\n" msgstr "" #: .././db/print.c:41 msgid "[value]..." msgstr "" #: .././db/print.c:42 msgid "print field values" msgstr "" #: .././db/print.c:79 #, c-format msgid "no print function for type %s\n" msgstr "" #: .././db/print.c:156 msgid "(empty)\n" msgstr "" #: .././db/print.c:218 msgid "(empty)" msgstr "" #: .././db/print.c:278 msgid "no arguments allowed\n" msgstr "" #: .././db/quit.c:27 msgid "exit xfs_db" msgstr "" #: .././db/sb.c:45 msgid "set current address to sb header" msgstr "" #: .././db/sb.c:47 msgid "[uuid]" msgstr "" #: .././db/sb.c:48 msgid "write/print FS uuid" msgstr "" #: .././db/sb.c:50 msgid "[label]" msgstr "" #: .././db/sb.c:51 msgid "write/print FS label" msgstr "" #: .././db/sb.c:53 msgid "[feature | [vnum fnum]]" msgstr "" #: .././db/sb.c:54 msgid "set feature bit(s) in the sb version field" msgstr "" #: .././db/sb.c:140 msgid "" "\n" " set allocation group superblock\n" "\n" " Example:\n" "\n" " 'sb 7' - set location to 7th allocation group superblock, set type to 'sb'\n" "\n" " Located in the first sector of each allocation group, the superblock\n" " contains the base information for the filesystem.\n" " The superblock in allocation group 0 is the primary. The copies in the\n" " remaining allocation groups only serve as backup for filesystem recovery.\n" " The icount/ifree/fdblocks/frextents are only updated in superblock 0.\n" "\n" msgstr "" #: .././db/sb.c:199 #, c-format msgid "can't read superblock for AG %u\n" msgstr "" #: .././db/sb.c:207 #, c-format msgid "bad sb magic # %#x in AG %u\n" msgstr "" #: .././db/sb.c:212 #, c-format msgid "bad sb version # %#x in AG %u\n" msgstr "" #: .././db/sb.c:236 msgid "aborting - external log specified for FS with an internal log\n" msgstr "" #: .././db/sb.c:242 msgid "aborting - no external log specified for FS with an external log\n" msgstr "" #: .././db/sb.c:252 msgid "ERROR: cannot find log head/tail, run xfs_repair\n" msgstr "" #: .././db/sb.c:256 #, c-format msgid "" "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running %s. If you are unable to mount the filesystem, then use\n" "the xfs_repair -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n" msgstr "" #: .././db/sb.c:284 msgid "Clearing log and setting UUID\n" msgstr "" #: .././db/sb.c:293 msgid "ERROR: cannot clear the log\n" msgstr "" #: .././db/sb.c:305 msgid "" "\n" " write/print FS uuid\n" "\n" " Example:\n" "\n" " 'uuid' - print UUID\n" " 'uuid 01234567-0123-0123-0123-0123456789ab' - write UUID\n" " 'uuid generate' - generate and write\n" " 'uuid rewrite' - copy UUID from SB 0\n" "\n" "The print function checks the UUID in each SB and will warn if the UUIDs\n" "differ between AGs (the log is not checked). The write commands will\n" "set the uuid in all AGs to either a specified value, a newly generated\n" "value or the value found in the first superblock (SB 0) respectively.\n" "As a side effect of writing the UUID, the log is cleared (which is fine\n" "on a CLEANLY unmounted FS).\n" "\n" msgstr "" #: .././db/sb.c:383 .././db/sb.c:546 msgid "invalid parameters\n" msgstr "" #: .././db/sb.c:390 .././db/sb.c:553 .././db/sb.c:720 #, c-format msgid "%s: not in expert mode, writing disabled\n" msgstr "" #: .././db/sb.c:402 msgid "failed to read UUID from AG 0\n" msgstr "" #: .././db/sb.c:407 #, c-format msgid "old UUID = %s\n" msgstr "" #: .././db/sb.c:421 msgid "invalid UUID\n" msgstr "" #: .././db/sb.c:430 .././db/sb.c:558 .././db/sb.c:806 msgid "writing all SBs\n" msgstr "" #: .././db/sb.c:433 #, c-format msgid "failed to set UUID in AG %d\n" msgstr "" #: .././db/sb.c:438 #, c-format msgid "new UUID = %s\n" msgstr "" #: .././db/sb.c:446 #, c-format msgid "failed to read UUID from AG %d\n" msgstr "" #: .././db/sb.c:452 #, c-format msgid "warning: UUID in AG %d differs to the primary SB\n" msgstr "" #: .././db/sb.c:463 msgid "warning - external log specified for FS with an internal log\n" msgstr "" #: .././db/sb.c:466 msgid "warning - no external log specified for FS with an external log\n" msgstr "" #: .././db/sb.c:471 #, c-format msgid "UUID = %s\n" msgstr "" #: .././db/sb.c:482 msgid "" "\n" " write/print FS label\n" "\n" " Example:\n" "\n" " 'label' - print label\n" " 'label 123456789012' - write label\n" " 'label --' - write an empty label\n" "\n" "The print function checks the label in each SB and will warn if the labels\n" "differ between AGs. The write commands will set the label in all AGs to the\n" "specified value. The maximum length of a label is 12 characters - use of a\n" "longer label will result in truncation and a warning will be issued.\n" "\n" msgstr "" #: .././db/sb.c:519 #, c-format msgid "%s: truncating label length from %d to %d\n" msgstr "" #: .././db/sb.c:561 #, c-format msgid "failed to set label in AG %d\n" msgstr "" #: .././db/sb.c:564 #, c-format msgid "new label = \"%s\"\n" msgstr "" #: .././db/sb.c:571 #, c-format msgid "failed to read label in AG %d\n" msgstr "" #: .././db/sb.c:577 #, c-format msgid "warning: AG %d label differs\n" msgstr "" #: .././db/sb.c:579 #, c-format msgid "label = \"%s\"\n" msgstr "" #: .././db/sb.c:589 msgid "" "\n" " set/print feature bits in sb version\n" "\n" " Example:\n" "\n" " 'version' - print current feature bits\n" " 'version extflg' - enable unwritten extents\n" " 'version attr1' - enable v1 inline extended attributes\n" " 'version attr2' - enable v2 inline extended attributes\n" " 'version log2' - enable v2 log format\n" "\n" "The version function prints currently enabled features for a filesystem\n" "according to the version field of its primary superblock.\n" "It can also be used to enable selected features, such as support for\n" "unwritten extents. The updated version is written into all AGs.\n" "\n" msgstr "" #: .././db/sb.c:617 msgid "Superblock has mismatched features2 fields, skipping modification\n" msgstr "" #: .././db/sb.c:740 msgid "unwritten extents flag is already enabled\n" msgstr "" #: .././db/sb.c:747 msgid "unwritten extents always enabled for v5 superblocks.\n" msgstr "" #: .././db/sb.c:764 msgid "version 2 log format is already in use\n" msgstr "" #: .././db/sb.c:771 msgid "Version 2 logs always enabled for v5 superblocks.\n" msgstr "" #: .././db/sb.c:776 #, c-format msgid "%s: Cannot change %s on v5 superblocks.\n" msgstr "" #: .././db/sb.c:800 #, c-format msgid "%s: invalid version change command \"%s\"\n" msgstr "" #: .././db/sb.c:809 #, c-format msgid "failed to set versionnum in AG %d\n" msgstr "" #: .././db/sb.c:827 #, c-format msgid "versionnum [0x%x+0x%x] = %s\n" msgstr "" #: .././db/type.c:49 msgid "[newtype]" msgstr "" #: .././db/type.c:50 msgid "set/show current data type" msgstr "" #: .././db/type.c:210 #, c-format msgid "current type is \"%s\"\n" msgstr "" #: .././db/type.c:212 msgid "" "\n" " supported types are:\n" " " msgstr "" #: .././db/type.c:229 #, c-format msgid "no such type %s\n" msgstr "" #: .././db/type.c:232 msgid "no current object\n" msgstr "" #: .././db/write.c:41 msgid "[-c] [field or value]..." msgstr "" #: .././db/write.c:42 msgid "write value to disk" msgstr "" #: .././db/write.c:58 msgid "" "\n" " The 'write' command takes on different personalities depending on the\n" " type of object being worked with.\n" "\n" " Write has 3 modes:\n" " 'struct mode' - is active anytime you're looking at a filesystem object\n" " which contains individual fields (ex: an inode).\n" " 'data mode' - is active anytime you set a disk address directly or set\n" " the type to 'data'.\n" " 'string mode' - only used for writing symlink blocks.\n" "\n" " Examples:\n" " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n" " 'write fname \"hello\\000\"' - write superblock fname.\n" " (note: in struct mode strings are not null terminated)\n" " 'write fname #6669736800' - write superblock fname with " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - write superblock uuid.\n" " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n" " 'write lshift 3' - shift the block 3 bytes to the left\n" " 'write sequence 1 5' - write a cycle of number [1-5] through\n" " the entire block.\n" " String mode: 'write \"This_is_a_filename\" - write null terminated " "string.\n" "\n" " In data mode type 'write' by itself for a list of specific commands.\n" "\n" " Specifying the -c option will allow writes of invalid (corrupt) data with\n" " an invalid CRC. Specifying the -d option will allow writes of invalid " "data,\n" " but still recalculate the CRC so we are forced to check and detect the\n" " invalid data appropriately.\n" "\n" msgstr "" #: .././db/write.c:104 #, c-format msgid "%s started in read only mode, writing disabled\n" msgstr "" #: .././db/write.c:116 #, c-format msgid "no handler function for type %s, write unsupported.\n" msgstr "" #: .././db/write.c:130 msgid "bad option for write command\n" msgstr "" #: .././db/write.c:136 msgid "Cannot specify both -c and -d options\n" msgstr "" #: .././db/write.c:141 msgid "Cannot recalculate CRCs on this type of object\n" msgstr "" #: .././db/write.c:166 msgid "Allowing write of corrupted data and bad CRC\n" msgstr "" #: .././db/write.c:169 msgid "Allowing write of corrupted data with good CRC\n" msgstr "" #: .././db/write.c:225 .././db/write.c:254 .././db/write.c:284 #: .././db/write.c:317 .././db/write.c:353 .././db/write.c:402 #: .././db/write.c:431 #, c-format msgid "length (%d) too large for data block size (%d)" msgstr "" #: .././db/write.c:673 msgid "usage: write fieldname value\n" msgstr "" #: .././db/write.c:679 #, c-format msgid "unable to parse '%s'.\n" msgstr "" #: .././db/write.c:728 #, c-format msgid "unable to convert value '%s'.\n" msgstr "" #: .././db/write.c:752 msgid "usage (in string mode): write \"string...\"\n" msgstr "" #: .././db/write.c:794 msgid "write: invalid subcommand\n" msgstr "" #: .././db/write.c:799 #, c-format msgid "write %s: invalid number of arguments\n" msgstr "" #: .././db/write.c:823 msgid "usage: write (in data mode)\n" msgstr "" #: .././estimate/xfs_estimate.c:78 #, c-format msgid "" "Usage: %s [opts] directory [directory ...]\n" "\t-b blocksize (fundamental filesystem blocksize)\n" "\t-i logsize (internal log size)\n" "\t-e logsize (external log size)\n" "\t-v prints more verbose messages\n" "\t-V prints version and exits\n" "\t-h prints this usage message\n" "\n" "Note:\tblocksize may have 'k' appended to indicate x1024\n" "\tlogsize may also have 'm' appended to indicate (1024 x 1024)\n" msgstr "" #: .././estimate/xfs_estimate.c:109 #, c-format msgid "blocksize %llu too small\n" msgstr "" #: .././estimate/xfs_estimate.c:114 #, c-format msgid "blocksize %llu too large\n" msgstr "" #: .././estimate/xfs_estimate.c:121 #, c-format msgid "already have external log noted, can't have both\n" msgstr "" #: .././estimate/xfs_estimate.c:130 #, c-format msgid "already have internal log noted, can't have both\n" msgstr "" #: .././estimate/xfs_estimate.c:160 #, c-format msgid "" "directory bsize blocks megabytes " "logsize\n" msgstr "" #: .././estimate/xfs_estimate.c:174 #, c-format msgid "dirsize=%llu\n" msgstr "" #: .././estimate/xfs_estimate.c:175 #, c-format msgid "fullblocks=%llu\n" msgstr "" #: .././estimate/xfs_estimate.c:176 #, c-format msgid "isize=%llu\n" msgstr "" #: .././estimate/xfs_estimate.c:178 #, c-format msgid "%llu regular files\n" msgstr "" #: .././estimate/xfs_estimate.c:179 #, c-format msgid "%llu symbolic links\n" msgstr "" #: .././estimate/xfs_estimate.c:180 #, c-format msgid "%llu directories\n" msgstr "" #: .././estimate/xfs_estimate.c:181 #, c-format msgid "%llu special files\n" msgstr "" #: .././estimate/xfs_estimate.c:194 #, c-format msgid "%s will take about %.1f megabytes\n" msgstr "" #: .././estimate/xfs_estimate.c:201 #, c-format msgid "%-39s %5llu %8llu %10.1fMB %10llu\n" msgstr "" #: .././estimate/xfs_estimate.c:207 #, c-format msgid "\twith the external log using %llu blocks " msgstr "" #: .././estimate/xfs_estimate.c:209 #, c-format msgid "or about %.1f megabytes\n" msgstr "" #: .././fsr/xfs_fsr.c:268 #, c-format msgid "%s: Stats not yet supported for XFS\n" msgstr "" #: .././fsr/xfs_fsr.c:332 #, c-format msgid "%s: could not stat: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:351 #, c-format msgid "%s: char special not supported: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:357 #, c-format msgid "%s: cannot defragment: %s: Not XFS\n" msgstr "" #: .././fsr/xfs_fsr.c:367 #, c-format msgid "%s: not fsys dev, dir, or reg file, ignoring\n" msgstr "" #: .././fsr/xfs_fsr.c:382 #, c-format msgid "" "Usage: %s [-d] [-v] [-g] [-t time] [-p passes] [-f leftf] [-m mtab]\n" " %s [-d] [-v] [-g] xfsdev | dir | file ...\n" " %s -V\n" "\n" "Options:\n" " -g Print to syslog (default if stdout not a tty).\n" " -t time How long to run in seconds.\n" " -p passes Number of passes before terminating global re-org.\n" " -f leftoff Use this instead of %s.\n" " -m mtab Use something other than /etc/mtab.\n" " -d Debug, print even more.\n" " -v Verbose, more -v's more verbose.\n" " -V Print version number and exit.\n" msgstr "" #: .././fsr/xfs_fsr.c:412 .././fsr/xfs_fsr.c:450 #, c-format msgid "out of memory: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:441 #, c-format msgid "Skipping %s: not mounted rw\n" msgstr "" #: .././fsr/xfs_fsr.c:455 #, c-format msgid "out of memory on realloc: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:466 .././fsr/xfs_fsr.c:470 #, c-format msgid "strdup(%s) failed\n" msgstr "" #: .././fsr/xfs_fsr.c:481 #, c-format msgid "no rw xfs file systems in mtab: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:485 #, c-format msgid "Found %d mounted, writable, XFS filesystems\n" msgstr "" #: .././fsr/xfs_fsr.c:515 #, c-format msgid "%s: open failed\n" msgstr "" #: .././fsr/xfs_fsr.c:530 #, c-format msgid "Can't use %s: mode=0%o own=%d nlink=%d\n" msgstr "" #: .././fsr/xfs_fsr.c:550 #, c-format msgid "could not read %s, starting with %s\n" msgstr "" #: .././fsr/xfs_fsr.c:589 #, c-format msgid "START: pass=%d ino=%llu %s %s\n" msgstr "" #: .././fsr/xfs_fsr.c:606 #, c-format msgid "Completed all %d passes\n" msgstr "" #: .././fsr/xfs_fsr.c:616 msgid "couldn't fork sub process:" msgstr "" #: .././fsr/xfs_fsr.c:651 #, c-format msgid "%s startpass %d, endpass %d, time %d seconds\n" msgstr "" #: .././fsr/xfs_fsr.c:658 #, c-format msgid "open(%s) failed: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:664 #, c-format msgid "write(%s) failed: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:688 #, c-format msgid "%s start inode=%llu\n" msgstr "" #: .././fsr/xfs_fsr.c:693 #, c-format msgid "unable to get handle: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:699 #, c-format msgid "unable to open: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:706 #, c-format msgid "Skipping %s: could not get XFS geometry\n" msgstr "" #: .././fsr/xfs_fsr.c:741 #, c-format msgid "could not open: inode %llu\n" msgstr "" #: .././fsr/xfs_fsr.c:771 #, c-format msgid "%s: xfs_bulkstat: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:798 #, c-format msgid "%s: Directory defragmentation not supported\n" msgstr "" #: .././fsr/xfs_fsr.c:817 #, c-format msgid "unable to construct sys handle for %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:828 #, c-format msgid "unable to open sys handle for %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:834 #, c-format msgid "unable to get bstat on %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:841 #, c-format msgid "unable to open handle %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:848 #, c-format msgid "Unable to get geom on fs for: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:899 #, c-format msgid "sync failed: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:905 #, c-format msgid "%s: zero size, ignoring\n" msgstr "" #: .././fsr/xfs_fsr.c:924 #, c-format msgid "locking check failed: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:931 #, c-format msgid "mandatory lock: %s: ignoring\n" msgstr "" #: .././fsr/xfs_fsr.c:944 #, c-format msgid "unable to get fs stat on %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:951 #, c-format msgid "insufficient freespace for: %s: size=%lld: ignoring\n" msgstr "" #: .././fsr/xfs_fsr.c:958 #, c-format msgid "failed to get inode attrs: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:963 #, c-format msgid "%s: immutable/append, ignoring\n" msgstr "" #: .././fsr/xfs_fsr.c:968 #, c-format msgid "%s: marked as don't defrag, ignoring\n" msgstr "" #: .././fsr/xfs_fsr.c:974 #, c-format msgid "cannot get realtime geometry for: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:979 #, c-format msgid "low on realtime free space: %s: ignoring file\n" msgstr "" #: .././fsr/xfs_fsr.c:986 #, c-format msgid "cannot open: %s: Permission denied\n" msgstr "" #: .././fsr/xfs_fsr.c:1045 .././fsr/xfs_fsr.c:1095 .././fsr/xfs_fsr.c:1175 msgid "could not set ATTR\n" msgstr "" #: .././fsr/xfs_fsr.c:1054 #, c-format msgid "unable to stat temp file: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1072 #, c-format msgid "unable to get bstat on temp file: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1077 #, c-format msgid "orig forkoff %d, temp forkoff %d\n" msgstr "" #: .././fsr/xfs_fsr.c:1130 msgid "big ATTR set failed\n" msgstr "" #: .././fsr/xfs_fsr.c:1151 #, c-format msgid "forkoff diff %d too large!\n" msgstr "" #: .././fsr/xfs_fsr.c:1168 #, c-format msgid "data fork growth unimplemented\n" msgstr "" #: .././fsr/xfs_fsr.c:1183 msgid "set temp attr\n" msgstr "" #: .././fsr/xfs_fsr.c:1186 msgid "failed to match fork offset\n" msgstr "" #: .././fsr/xfs_fsr.c:1233 #, c-format msgid "%s already fully defragmented.\n" msgstr "" #: .././fsr/xfs_fsr.c:1239 #, c-format msgid "%s extents=%d can_save=%d tmp=%s\n" msgstr "" #: .././fsr/xfs_fsr.c:1245 #, c-format msgid "could not open tmp file: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1253 #, c-format msgid "failed to set ATTR fork on tmp: %s:\n" msgstr "" #: .././fsr/xfs_fsr.c:1260 #, c-format msgid "could not set inode attrs on tmp: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1267 #, c-format msgid "could not get DirectIO info on tmp: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1282 #, c-format msgid "DEBUG: fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n" msgstr "" #: .././fsr/xfs_fsr.c:1289 #, c-format msgid "could not allocate buf: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1299 #, c-format msgid "could not open fragfile: %s : %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1314 #, c-format msgid "could not trunc tmp %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1318 .././fsr/xfs_fsr.c:1338 .././fsr/xfs_fsr.c:1366 #, c-format msgid "could not lseek in tmpfile: %s : %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1333 #, c-format msgid "could not pre-allocate tmp space: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1346 msgid "Couldn't rewind on temporary file\n" msgstr "" #: .././fsr/xfs_fsr.c:1353 #, c-format msgid "Temporary file has %d extents (%d in original)\n" msgstr "" #: .././fsr/xfs_fsr.c:1356 #, c-format msgid "No improvement will be made (skipping): %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1371 #, c-format msgid "could not lseek in file: %s : %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1407 #, c-format msgid "bad read of %d bytes from %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1411 .././fsr/xfs_fsr.c:1443 #, c-format msgid "bad write of %d bytes to %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1428 #, c-format msgid "bad write2 of %d bytes to %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1433 #, c-format msgid "bad copy to %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1451 #, c-format msgid "could not truncate tmpfile: %s : %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1456 #, c-format msgid "could not fsync tmpfile: %s : %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1471 #, c-format msgid "failed to fchown tmpfile %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1481 #, c-format msgid "%s: file type not supported\n" msgstr "" #: .././fsr/xfs_fsr.c:1485 #, c-format msgid "%s: file modified defrag aborted\n" msgstr "" #: .././fsr/xfs_fsr.c:1490 #, c-format msgid "%s: file busy\n" msgstr "" #: .././fsr/xfs_fsr.c:1492 #, c-format msgid "XFS_IOC_SWAPEXT failed: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1500 #, c-format msgid "extents before:%d after:%d %s %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1534 #, c-format msgid "tmp file name too long: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1584 #, c-format msgid "realloc failed: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1597 #, c-format msgid "malloc failed: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1627 #, c-format msgid "failed reading extents: inode %llu" msgstr "" #: .././fsr/xfs_fsr.c:1677 msgid "failed reading extents" msgstr "" #: .././fsr/xfs_fsr.c:1765 .././fsr/xfs_fsr.c:1779 #, c-format msgid "tmpdir already exists: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1768 #, c-format msgid "could not create tmpdir: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1781 #, c-format msgid "cannot create tmpdir: %s: %s\n" msgstr "" #: .././fsr/xfs_fsr.c:1819 .././fsr/xfs_fsr.c:1827 #, c-format msgid "could not remove tmpdir: %s: %s\n" msgstr "" #: .././growfs/xfs_growfs.c:26 #, c-format msgid "" "Usage: %s [options] mountpoint\n" "\n" "Options:\n" "\t-d grow data/metadata section\n" "\t-l grow log section\n" "\t-r grow realtime section\n" "\t-n don't change anything, just show geometry\n" "\t-i convert log from external to internal format\n" "\t-t alternate location for mount table (/etc/mtab)\n" "\t-x convert log from internal to external format\n" "\t-D size grow data/metadata section to size blks\n" "\t-L size grow/shrink log section to size blks\n" "\t-R size grow realtime section to size blks\n" "\t-e size set realtime extent size to size blks\n" "\t-m imaxpct set inode max percent to imaxpct\n" "\t-V print version information\n" msgstr "" #: .././growfs/xfs_growfs.c:66 #, c-format msgid "" "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u rmapbt=%u\n" " =%-22s reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" msgstr "" #: .././growfs/xfs_growfs.c:85 .././growfs/xfs_growfs.c:466 #: .././growfs/xfs_growfs.c:467 msgid "internal" msgstr "" #: .././growfs/xfs_growfs.c:85 .././growfs/xfs_growfs.c:88 #: .././growfs/xfs_growfs.c:466 .././growfs/xfs_growfs.c:467 msgid "external" msgstr "" #: .././growfs/xfs_growfs.c:207 #, c-format msgid "%s: %s is not a mounted XFS filesystem\n" msgstr "" #: .././growfs/xfs_growfs.c:224 #, c-format msgid "%s: specified file [\"%s\"] is not on an XFS filesystem\n" msgstr "" #: .././growfs/xfs_growfs.c:241 #, c-format msgid "%s: cannot determine geometry of filesystem mounted at %s: %s\n" msgstr "" #: .././growfs/xfs_growfs.c:285 #, c-format msgid "%s: failed to access data device for %s\n" msgstr "" #: .././growfs/xfs_growfs.c:290 #, c-format msgid "%s: failed to access external log for %s\n" msgstr "" #: .././growfs/xfs_growfs.c:296 #, c-format msgid "%s: failed to access realtime device for %s\n" msgstr "" #: .././growfs/xfs_growfs.c:336 #, c-format msgid "data size %lld too large, maximum is %lld\n" msgstr "" #: .././growfs/xfs_growfs.c:343 #, c-format msgid "data size %lld too small, old size is %lld\n" msgstr "" #: .././growfs/xfs_growfs.c:351 #, c-format msgid "data size unchanged, skipping\n" msgstr "" #: .././growfs/xfs_growfs.c:354 #, c-format msgid "inode max pct unchanged, skipping\n" msgstr "" #: .././growfs/xfs_growfs.c:361 .././growfs/xfs_growfs.c:400 #: .././growfs/xfs_growfs.c:435 #, c-format msgid "%s: growfs operation in progress already\n" msgstr "" #: .././growfs/xfs_growfs.c:365 #, c-format msgid "%s: XFS_IOC_FSGROWFSDATA xfsctl failed: %s\n" msgstr "" #: .././growfs/xfs_growfs.c:381 #, c-format msgid "realtime size %lld too large, maximum is %lld\n" msgstr "" #: .././growfs/xfs_growfs.c:387 #, c-format msgid "realtime size %lld too small, old size is %lld\n" msgstr "" #: .././growfs/xfs_growfs.c:393 #, c-format msgid "realtime size unchanged, skipping\n" msgstr "" #: .././growfs/xfs_growfs.c:404 #, c-format msgid "%s: realtime growth not implemented\n" msgstr "" #: .././growfs/xfs_growfs.c:408 #, c-format msgid "%s: XFS_IOC_FSGROWFSRT xfsctl failed: %s\n" msgstr "" #: .././growfs/xfs_growfs.c:429 #, c-format msgid "log size unchanged, skipping\n" msgstr "" #: .././growfs/xfs_growfs.c:439 #, c-format msgid "%s: log growth not supported yet\n" msgstr "" #: .././growfs/xfs_growfs.c:443 #, c-format msgid "%s: XFS_IOC_FSGROWFSLOG xfsctl failed: %s\n" msgstr "" #: .././growfs/xfs_growfs.c:451 #, c-format msgid "%s: XFS_IOC_FSGEOMETRY xfsctl failed: %s\n" msgstr "" #: .././growfs/xfs_growfs.c:456 #, c-format msgid "data blocks changed from %lld to %lld\n" msgstr "" #: .././growfs/xfs_growfs.c:459 #, c-format msgid "inode max percent changed from %d to %d\n" msgstr "" #: .././growfs/xfs_growfs.c:462 #, c-format msgid "log blocks changed from %d to %d\n" msgstr "" #: .././growfs/xfs_growfs.c:465 #, c-format msgid "log changed from %s to %s\n" msgstr "" #: .././growfs/xfs_growfs.c:469 #, c-format msgid "realtime blocks changed from %lld to %lld\n" msgstr "" #: .././growfs/xfs_growfs.c:472 #, c-format msgid "realtime extent size changed from %d to %d\n" msgstr "" #: .././io/attr.c:60 #, c-format msgid "" "\n" " displays the set of extended inode flags associated with the current file\n" "\n" " Each individual flag is displayed as a single character, in this order:\n" " r -- file data is stored in the realtime section\n" " p -- file has preallocated extents (cannot be changed using chattr)\n" " i -- immutable, file cannot be modified\n" " a -- append-only, file can only be appended to\n" " s -- all updates are synchronous\n" " A -- the access time is not updated for this inode\n" " d -- do not include this file in a dump of the filesystem\n" " t -- child created in this directory has realtime bit set by default\n" " P -- child created in this directory has parents project ID by default\n" " n -- symbolic links cannot be created in this directory\n" " e -- for non-realtime files, observe the inode extent size value\n" " E -- children created in this directory inherit the extent size value\n" " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" " x -- Use direct access (DAX) for data in this file\n" " C -- for files with shared blocks, observe the inode CoW extent size value\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, but only list attributes on directories\n" " -a -- show all flags which can be set alongside those which are set\n" " -v -- verbose mode; show long names of flags, not single characters\n" "\n" msgstr "" #: .././io/attr.c:93 #, c-format msgid "" "\n" " modifies the set of extended inode flags associated with the current file\n" "\n" " Examples:\n" " 'chattr +a' - sets the append-only flag\n" " 'chattr -a' - clears the append-only flag\n" "\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, only modifying attributes on directories\n" " +/-r -- set/clear the realtime flag\n" " +/-i -- set/clear the immutable flag\n" " +/-a -- set/clear the append-only flag\n" " +/-s -- set/clear the sync flag\n" " +/-A -- set/clear the no-atime flag\n" " +/-d -- set/clear the no-dump flag\n" " +/-t -- set/clear the realtime inheritance flag\n" " +/-P -- set/clear the project ID inheritance flag\n" " +/-n -- set/clear the no-symbolic-links flag\n" " +/-e -- set/clear the extent-size flag\n" " +/-E -- set/clear the extent-size inheritance flag\n" " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " +/-x -- set/clear the direct access (DAX) flag\n" " +/-C -- set/clear the CoW extent-size flag\n" " Note1: user must have certain capabilities to modify immutable/append-" "only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" " Note3: the realtime flag can only be set if the filesystem has a realtime\n" " section, and the (regular) file must be empty when the flag is set.\n" "\n" msgstr "" #: .././io/attr.c:176 .././io/attr.c:252 .././io/cowextsize.c:109 #: .././io/cowextsize.c:132 .././io/open.c:426 .././io/open.c:498 #: .././io/open.c:622 .././io/open.c:644 .././libxfs/init.c:127 #: .././mkfs/proto.c:302 .././quota/project.c:118 .././quota/project.c:163 #: .././quota/project.c:210 #, c-format msgid "%s: cannot open %s: %s\n" msgstr "" #: .././io/attr.c:179 .././io/attr.c:226 .././io/attr.c:255 .././io/attr.c:326 #: .././quota/project.c:122 .././quota/project.c:168 .././quota/project.c:215 #, c-format msgid "%s: cannot get flags on %s: %s\n" msgstr "" #: .././io/attr.c:261 .././io/attr.c:332 #, c-format msgid "%s: cannot set flags on %s: %s\n" msgstr "" #: .././io/attr.c:296 .././io/attr.c:310 #, c-format msgid "%s: unknown flag\n" msgstr "" #: .././io/attr.c:316 #, c-format msgid "%s: bad chattr command, not +/-X\n" msgstr "" #: .././io/attr.c:343 msgid "[-R|-D] [+/-" msgstr "" #: .././io/attr.c:348 msgid "change extended inode flags on the currently open file" msgstr "" #: .././io/attr.c:353 msgid "[-R|-D|-a|-v]" msgstr "" #: .././io/attr.c:358 msgid "list extended inode flags set on the currently open file" msgstr "" #: .././io/bmap.c:30 #, c-format msgid "" "\n" " prints the block mapping for an XFS file's data or attribute forks\n" " Example:\n" " 'bmap -vp' - tabular format verbose map, including unwritten extents\n" "\n" " bmap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -c -- prints the copy-on-write fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" " -e -- print delayed allocation extents.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are " "unwritten.)\n" " -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" " Note: the bmap for non-regular files can be obtained provided the file\n" " was opened appropriately (in particular, must be opened read-only).\n" "\n" msgstr "" #: .././io/bmap.c:133 #, c-format msgid "%s: can't get geometry [\"%s\"]: %s\n" msgstr "" #: .././io/bmap.c:141 #, c-format msgid "%s: cannot read attrs on \"%s\": %s\n" msgstr "" #: .././io/bmap.c:159 .././io/fiemap.c:258 #, c-format msgid "%s: malloc of %d bytes failed.\n" msgstr "" #: .././io/bmap.c:207 #, c-format msgid "%s: xfsctl(XFS_IOC_GETBMAPX) iflags=0x%x [\"%s\"]: %s\n" msgstr "" #: .././io/bmap.c:238 #, c-format msgid "%s: cannot realloc %d bytes\n" msgstr "" #: .././io/bmap.c:247 #, c-format msgid "%s: no extents\n" msgstr "" #: .././io/bmap.c:261 .././io/bmap.c:396 .././io/fiemap.c:104 #: .././io/fiemap.c:339 .././io/fiemap.c:343 #, c-format msgid "hole" msgstr "" #: .././io/bmap.c:263 .././io/bmap.c:404 #, c-format msgid "delalloc" msgstr "" #: .././io/bmap.c:272 #, c-format msgid " %lld blocks\n" msgstr "" #: .././io/bmap.c:352 .././io/fiemap.c:93 msgid "EXT" msgstr "" #: .././io/bmap.c:353 .././io/fiemap.c:94 msgid "FILE-OFFSET" msgstr "" #: .././io/bmap.c:354 msgid "RT-BLOCK-RANGE" msgstr "" #: .././io/bmap.c:354 .././io/fiemap.c:95 msgid "BLOCK-RANGE" msgstr "" #: .././io/bmap.c:355 msgid "AG" msgstr "" #: .././io/bmap.c:356 msgid "AG-OFFSET" msgstr "" #: .././io/bmap.c:357 .././io/fiemap.c:96 msgid "TOTAL" msgstr "" #: .././io/bmap.c:358 msgid " FLAGS" msgstr "" #: .././io/bmap.c:438 #, c-format msgid " FLAG Values:\n" msgstr "" #: .././io/bmap.c:439 #, c-format msgid " %*.*o Shared extent\n" msgstr "" #: .././io/bmap.c:441 #, c-format msgid " %*.*o Unwritten preallocated extent\n" msgstr "" #: .././io/bmap.c:443 #, c-format msgid " %*.*o Doesn't begin on stripe unit\n" msgstr "" #: .././io/bmap.c:445 #, c-format msgid " %*.*o Doesn't end on stripe unit\n" msgstr "" #: .././io/bmap.c:447 #, c-format msgid " %*.*o Doesn't begin on stripe width\n" msgstr "" #: .././io/bmap.c:449 #, c-format msgid " %*.*o Doesn't end on stripe width\n" msgstr "" #: .././io/bmap.c:465 msgid "[-adlpv] [-n nx]" msgstr "" #: .././io/bmap.c:466 msgid "print block mapping for an XFS file" msgstr "" #: .././io/copy_file_range.c:32 #, c-format msgid "" "\n" " Copies a range of bytes from a file into the open file, overwriting any " "data\n" " already there.\n" "\n" " Example:\n" " 'copy_range -s 100 -d 200 -l 300 some_file' - copies 300 bytes from " "some_file\n" " at offset 100 into the open\n" "\t\t\t\t\t file at offset 200\n" " 'copy_range some_file' - copies all bytes from some_file into the open " "file\n" " at position 0\n" msgstr "" #: .././io/copy_file_range.c:97 #, c-format msgid "invalid source offset -- %s\n" msgstr "" #: .././io/copy_file_range.c:104 #, c-format msgid "invalid destination offset -- %s\n" msgstr "" #: .././io/copy_file_range.c:111 #, c-format msgid "invalid length -- %s\n" msgstr "" #: .././io/copy_file_range.c:143 msgid "[-s src_off] [-d dst_off] [-l len] src_file" msgstr "" #: .././io/copy_file_range.c:144 msgid "Copy a range of data between two files" msgstr "" #: .././io/cowextsize.c:40 #, c-format msgid "" "\n" " report or modify preferred CoW extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying cowextsize on directories\n" "\n" msgstr "" #: .././io/cowextsize.c:81 .././io/open.c:595 #, c-format msgid "invalid target file type - file %s\n" msgstr "" #: .././io/cowextsize.c:169 #, c-format msgid "non-numeric cowextsize argument -- %s\n" msgstr "" #: .././io/cowextsize.c:193 msgid "[-D | -R] [cowextsize]" msgstr "" #: .././io/cowextsize.c:198 msgid "get/set preferred CoW extent size (in bytes) for the open file" msgstr "" #: .././io/fadvise.c:30 #, c-format msgid "" "\n" " advise the page cache about expected I/O patterns on the current file\n" "\n" " Modifies kernel page cache behaviour when operating on the current file.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_FADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_FADV_DONTNEED) [*]\n" " -n -- data will be accessed once (POSIX_FADV_NOREUSE) [*]\n" " -r -- expect random page references (POSIX_FADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_FADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_FADV_WILLNEED) [*]\n" " Notes: these interfaces are not supported in Linux kernels before 2.6.\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED and NOREUSE are equivalent, and force the maximum readahead.\n" "\n" msgstr "" #: .././io/fadvise.c:91 .././io/madvise.c:86 .././io/mincore.c:47 #: .././io/mmap.c:213 .././io/mmap.c:320 .././io/mmap.c:406 .././io/mmap.c:565 #: .././io/mmap.c:647 .././io/prealloc.c:73 .././io/pwrite.c:346 #: .././io/sendfile.c:124 .././io/sync_file_range.c:74 #, c-format msgid "non-numeric offset argument -- %s\n" msgstr "" #: .././io/fadvise.c:98 .././io/madvise.c:93 .././io/mincore.c:53 #: .././io/mmap.c:219 .././io/mmap.c:327 .././io/mmap.c:413 .././io/mmap.c:572 #: .././io/pread.c:454 .././io/pread.c:462 .././io/prealloc.c:78 #: .././io/pwrite.c:352 .././io/sendfile.c:131 .././io/sync_file_range.c:81 #, c-format msgid "non-numeric length argument -- %s\n" msgstr "" #: .././io/fadvise.c:121 msgid "[-dnrsw] [off len]" msgstr "" #: .././io/fadvise.c:122 msgid "advisory commands for sections of a file" msgstr "" #: .././io/fiemap.c:31 #, c-format msgid "" "\n" " prints the block mapping for a file's data or attribute forks\n" " Example:\n" " 'fiemap -v' - tabular format verbose map\n" "\n" " fiemap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -v -- Verbose information\n" "\n" msgstr "" #: .././io/fiemap.c:97 msgid "FLAGS" msgstr "" #: .././io/fiemap.c:146 .././io/fiemap.c:160 .././io/fiemap.c:345 #, c-format msgid " %llu blocks\n" msgstr "" #: .././io/fiemap.c:365 msgid "[-alv] [-n nx]" msgstr "" #: .././io/fiemap.c:366 msgid "print block mapping for a file" msgstr "" #: .././io/file.c:38 #, c-format msgid "%c%03d%c %-14s (%s,%s,%s,%s%s%s%s%s)\n" msgstr "" #: .././io/file.c:40 msgid "foreign" msgstr "" #: .././io/file.c:40 msgid "xfs" msgstr "" #: .././io/file.c:41 .././io/open.c:98 msgid "sync" msgstr "" #: .././io/file.c:41 .././io/open.c:98 msgid "non-sync" msgstr "" #: .././io/file.c:42 .././io/open.c:99 msgid "direct" msgstr "" #: .././io/file.c:42 .././io/open.c:99 msgid "non-direct" msgstr "" #: .././io/file.c:43 .././io/open.c:100 msgid "read-only" msgstr "" #: .././io/file.c:43 .././io/open.c:100 msgid "read-write" msgstr "" #: .././io/file.c:44 .././io/open.c:101 msgid ",real-time" msgstr "" #: .././io/file.c:45 .././io/open.c:102 msgid ",append-only" msgstr "" #: .././io/file.c:46 .././io/open.c:103 msgid ",non-block" msgstr "" #: .././io/file.c:47 .././io/open.c:104 msgid ",tmpfile" msgstr "" #: .././io/file.c:81 .././io/sendfile.c:101 .././quota/path.c:126 #, c-format msgid "value %d is out of range (0-%d)\n" msgstr "" #: .././io/file.c:94 .././quota/path.c:140 msgid "[N]" msgstr "" #: .././io/file.c:99 msgid "set the current file" msgstr "" #: .././io/file.c:108 msgid "list current open files and memory mappings" msgstr "" #: .././io/freeze.c:36 #, c-format msgid "%s: cannot freeze filesystem at %s: %s\n" msgstr "" #: .././io/freeze.c:53 #, c-format msgid "%s: cannot unfreeze filesystem mounted at %s: %s\n" msgstr "" #: .././io/freeze.c:69 msgid "freeze filesystem of current file" msgstr "" #: .././io/freeze.c:76 msgid "unfreeze filesystem of current file" msgstr "" #: .././io/fsync.c:59 msgid "calls fsync(2) to flush all in-core file state to disk" msgstr "" #: .././io/fsync.c:66 msgid "calls fdatasync(2) to flush the files in-core data to disk" msgstr "" #: .././io/getrusage.c:117 msgid "report process resource usage" msgstr "" #: .././io/imap.c:54 #, c-format msgid "ino %10llu count %2d mask %016llx\n" msgstr "" #: .././io/imap.c:74 msgid "[nentries]" msgstr "" #: .././io/imap.c:76 msgid "inode map for filesystem of current file" msgstr "" #: .././io/init.c:37 #, c-format msgid "Usage: %s [-adfinrRstVx] [-m mode] [-p prog] [-c cmd]... file\n" msgstr "" #: .././io/init.c:111 .././io/mmap.c:171 .././io/mmap.c:178 .././io/mmap.c:181 #: .././io/open.c:294 #, c-format msgid "no files are open, try 'help open'\n" msgstr "" #: .././io/init.c:115 .././io/mmap.c:170 .././io/mmap.c:177 #, c-format msgid "no mapped regions, try 'help mmap'\n" msgstr "" #: .././io/init.c:121 #, c-format msgid "foreign file active, %s command is for XFS filesystems only\n" msgstr "" #: .././io/init.c:169 .././io/open.c:316 #, c-format msgid "non-numeric mode -- %s\n" msgstr "" #: .././io/inject.c:120 #, c-format msgid "" "\n" " inject errors into the filesystem of the currently open file\n" "\n" " Example:\n" " 'inject readagf' - cause errors on allocation group freespace reads\n" "\n" " Causes the kernel to generate and react to errors within XFS, provided\n" " the XFS kernel code has been built with debugging features enabled.\n" " With no arguments, displays the list of error injection tags.\n" "\n" msgstr "" #: .././io/inject.c:146 #, c-format msgid "no such tag -- %s\n" msgstr "" #: .././io/inject.c:167 msgid "[tag ...]" msgstr "" #: .././io/inject.c:168 msgid "inject errors into a filesystem" msgstr "" #: .././io/link.c:34 #, c-format msgid "" "\n" "link the open file descriptor to the supplied filename\n" "\n" "\n" msgstr "" #: .././io/link.c:63 msgid "filename" msgstr "" #: .././io/link.c:65 msgid "link the open file descriptor to the supplied filename" msgstr "" #: .././io/madvise.c:31 #, c-format msgid "" "\n" " advise the page cache about access patterns expected for a mapping\n" "\n" " Modifies page cache behavior when operating on the current mapping.\n" " The range arguments are required by some advise commands ([*] below).\n" " With no arguments, the POSIX_MADV_NORMAL advice is implied.\n" " -d -- don't need these pages (POSIX_MADV_DONTNEED) [*]\n" " -r -- expect random page references (POSIX_MADV_RANDOM)\n" " -s -- expect sequential page references (POSIX_MADV_SEQUENTIAL)\n" " -w -- will need these pages (POSIX_MADV_WILLNEED) [*]\n" " Notes:\n" " NORMAL sets the default readahead setting on the file.\n" " RANDOM sets the readahead setting on the file to zero.\n" " SEQUENTIAL sets double the default readahead setting on the file.\n" " WILLNEED forces the maximum readahead.\n" "\n" msgstr "" #: .././io/madvise.c:97 .././io/mincore.c:57 #, c-format msgid "length argument too large -- %lld\n" msgstr "" #: .././io/madvise.c:126 msgid "[-drsw] [off len]" msgstr "" #: .././io/madvise.c:127 msgid "give advice about use of memory" msgstr "" #: .././io/mincore.c:91 .././io/mincore.c:101 #, c-format msgid "0x%lx %lu pages (%llu : %lu)\n" msgstr "" #: .././io/mincore.c:121 msgid "[off len]" msgstr "" #: .././io/mincore.c:122 msgid "find mapping pages that are memory resident" msgstr "" #: .././io/mmap.c:78 #, c-format msgid "offset (%lld) is before start of mapping (%lld)\n" msgstr "" #: .././io/mmap.c:84 #, c-format msgid "offset (%lld) is beyond end of mapping (%lld)\n" msgstr "" #: .././io/mmap.c:89 #, c-format msgid "range (%lld:%lld) is beyond mapping (%lld:%ld)\n" msgstr "" #: .././io/mmap.c:95 #, c-format msgid "offset address (%p) is not page aligned\n" msgstr "" #: .././io/mmap.c:135 #, c-format msgid "" "\n" " maps a range within the current file into memory\n" "\n" " Example:\n" " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" "\n" " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" " With no arguments, mmap shows the current mappings. The current mapping\n" " can be set by using the single argument form (mapping number or address).\n" " If two arguments are specified (a range), a new mapping is created and the\n" " following options are available:\n" " -r -- map with PROT_READ protection\n" " -w -- map with PROT_WRITE protection\n" " -x -- map with PROT_EXEC protection\n" " -s -- first do mmap(size)/munmap(size), try to reserve some free " "space\n" " If no protection mode is specified, all are used by default.\n" "\n" msgstr "" #: .././io/mmap.c:273 #, c-format msgid "" "\n" " flushes a range of bytes in the current memory mapping\n" "\n" " Writes all modified copies of pages over the specified range (or entire\n" " mapping if no range specified) to their backing storage locations. Also,\n" " optionally invalidates so that subsequent references to the pages will be\n" " obtained from their backing storage locations (instead of cached copies).\n" " -a -- perform asynchronous writes (MS_ASYNC)\n" " -i -- invalidate mapped pages (MS_INVALIDATE)\n" " -s -- perform synchronous writes (MS_SYNC)\n" "\n" msgstr "" #: .././io/mmap.c:349 #, c-format msgid "" "\n" " reads a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n" "\n" " Accesses a range of the current memory mapping, optionally dumping it to\n" " the standard output stream (with -v option) for subsequent inspection.\n" " -f -- verbose mode, dump bytes with offsets relative to start of file.\n" " -r -- reverse order; start accessing from the end of range, moving " "backward\n" " -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n" " The accesses are performed sequentially from the start offset by default.\n" " Notes:\n" " References to whole pages following the end of the backing file results\n" " in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n" " on various filesystem conditions, including quota exceeded errors, and\n" " for physical device errors (such as unreadable disk blocks). No attempt\n" " has been made to catch signals at this stage...\n" "\n" msgstr "" #: .././io/mmap.c:513 #, c-format msgid "" "\n" " dirties a range of bytes in the current memory mapping\n" "\n" " Example:\n" " 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n" "\n" " Stores a byte into memory for a range within a mapping.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -S -- use an alternate seed character\n" " -r -- reverse order; start storing from the end of range, moving backward\n" " The stores are performed sequentially from the start offset by default.\n" "\n" msgstr "" #: .././io/mmap.c:549 .././io/pread.c:439 .././io/pwrite.c:305 #: .././io/pwrite.c:332 #, c-format msgid "non-numeric seed -- %s\n" msgstr "" #: .././io/mmap.c:601 #, c-format msgid "" "\n" " resizes the current memory mapping\n" "\n" " Examples:\n" " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" "\n" " Resizes the mappping, growing or shrinking from the current size.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -f -- use MREMAP_FIXED flag to mremap on new_address\n" " -m -- use the MREMAP_MAYMOVE flag\n" "\n" msgstr "" #: .././io/mmap.c:678 msgid "[N] | [-rwx] [-s size] [off len]" msgstr "" #: .././io/mmap.c:680 msgid "mmap a range in the current file, show mappings" msgstr "" #: .././io/mmap.c:689 msgid "[-r] [off len]" msgstr "" #: .././io/mmap.c:691 msgid "reads data from a region in the current memory mapping" msgstr "" #: .././io/mmap.c:700 msgid "[-ais] [off len]" msgstr "" #: .././io/mmap.c:701 msgid "flush a region in the current memory mapping" msgstr "" #: .././io/mmap.c:710 msgid "unmaps the current memory mapping" msgstr "" #: .././io/mmap.c:718 msgid "[-r] [-S seed] [off len]" msgstr "" #: .././io/mmap.c:720 msgid "writes data into a region in the current memory mapping" msgstr "" #: .././io/mmap.c:730 msgid "[-m|-f ] newsize" msgstr "" #: .././io/mmap.c:732 msgid "alters the size of the current memory mapping" msgstr "" #: .././io/open.c:69 msgid "socket" msgstr "" #: .././io/open.c:71 .././repair/da_util.c:105 msgid "directory" msgstr "" #: .././io/open.c:73 msgid "char device" msgstr "" #: .././io/open.c:75 msgid "block device" msgstr "" #: .././io/open.c:77 msgid "regular file" msgstr "" #: .././io/open.c:79 msgid "symbolic link" msgstr "" #: .././io/open.c:81 msgid "fifo" msgstr "" #: .././io/open.c:96 .././io/open.c:709 #, c-format msgid "fd.path = \"%s\"\n" msgstr "" #: .././io/open.c:97 #, c-format msgid "fd.flags = %s,%s,%s%s%s%s%s\n" msgstr "" #: .././io/open.c:108 #, c-format msgid "stat.ino = %lld\n" msgstr "" #: .././io/open.c:109 #, c-format msgid "stat.type = %s\n" msgstr "" #: .././io/open.c:110 #, c-format msgid "stat.size = %lld\n" msgstr "" #: .././io/open.c:111 #, c-format msgid "stat.blocks = %lld\n" msgstr "" #: .././io/open.c:113 #, c-format msgid "stat.atime = %s" msgstr "" #: .././io/open.c:114 #, c-format msgid "stat.mtime = %s" msgstr "" #: .././io/open.c:115 #, c-format msgid "stat.ctime = %s" msgstr "" #: .././io/open.c:124 #, c-format msgid "fsxattr.xflags = 0x%x " msgstr "" #: .././io/open.c:126 #, c-format msgid "fsxattr.projid = %u\n" msgstr "" #: .././io/open.c:127 #, c-format msgid "fsxattr.extsize = %u\n" msgstr "" #: .././io/open.c:128 #, c-format msgid "fsxattr.cowextsize = %u\n" msgstr "" #: .././io/open.c:129 #, c-format msgid "fsxattr.nextents = %u\n" msgstr "" #: .././io/open.c:130 #, c-format msgid "fsxattr.naextents = %u\n" msgstr "" #: .././io/open.c:135 #, c-format msgid "dioattr.mem = 0x%x\n" msgstr "" #: .././io/open.c:136 #, c-format msgid "dioattr.miniosz = %u\n" msgstr "" #: .././io/open.c:137 #, c-format msgid "dioattr.maxiosz = %u\n" msgstr "" #: .././io/open.c:256 #, c-format msgid "" "\n" " opens a new file in the requested mode\n" "\n" " Example:\n" " 'open -cd /tmp/data' - creates/opens data file read-write for direct IO\n" "\n" " Opens a file for subsequent use by all of the other xfs_io commands.\n" " With no arguments, open uses the stat command to show the current file.\n" " -a -- open with the O_APPEND flag (append-only mode)\n" " -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n" " -f -- open with O_CREAT (create the file if it doesn't exist)\n" " -m -- permissions to use in case a new file is created (default 0600)\n" " -n -- open with O_NONBLOCK\n" " -r -- open with O_RDONLY, the default is O_RDWR\n" " -s -- open with O_SYNC\n" " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n" " -R -- mark the file as a realtime XFS file immediately after opening it\n" " -T -- open with O_TMPFILE (create a file not visible in the namespace)\n" " Note1: usually read/write direct IO requests must be blocksize aligned;\n" " some kernels, however, allow sectorsize alignment for direct IO.\n" " Note2: the bmap for non-regular files can be obtained provided the file\n" " was opened correctly (in particular, must be opened read-only).\n" "\n" msgstr "" #: .././io/open.c:348 #, c-format msgid "-T and -r options are incompatible\n" msgstr "" #: .././io/open.c:403 #, c-format msgid "" "\n" " displays the project identifier associated with the current path\n" "\n" " Options:\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, but only list projects on directories\n" "\n" msgstr "" #: .././io/open.c:469 #, c-format msgid "projid = %u\n" msgstr "" #: .././io/open.c:477 #, c-format msgid "" "\n" " modifies the project identifier associated with the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying projects on directories\n" "\n" msgstr "" #: .././io/open.c:536 #, c-format msgid "invalid project ID -- %s\n" msgstr "" #: .././io/open.c:552 #, c-format msgid "" "\n" " report or modify preferred extent size (in bytes) for the current path\n" "\n" " -R -- recursively descend (useful when current path is a directory)\n" " -D -- recursively descend, only modifying extsize on directories\n" "\n" msgstr "" #: .././io/open.c:681 #, c-format msgid "non-numeric extsize argument -- %s\n" msgstr "" #: .././io/open.c:713 #, c-format msgid "statfs.f_bsize = %lld\n" msgstr "" #: .././io/open.c:714 #, c-format msgid "statfs.f_blocks = %lld\n" msgstr "" #: .././io/open.c:716 #, c-format msgid "statfs.f_frsize = %lld\n" msgstr "" #: .././io/open.c:718 #, c-format msgid "statfs.f_bavail = %lld\n" msgstr "" #: .././io/open.c:720 #, c-format msgid "statfs.f_files = %lld\n" msgstr "" #: .././io/open.c:721 #, c-format msgid "statfs.f_ffree = %lld\n" msgstr "" #: .././io/open.c:728 #, c-format msgid "geom.bsize = %u\n" msgstr "" #: .././io/open.c:729 #, c-format msgid "geom.agcount = %u\n" msgstr "" #: .././io/open.c:730 #, c-format msgid "geom.agblocks = %u\n" msgstr "" #: .././io/open.c:731 #, c-format msgid "geom.datablocks = %llu\n" msgstr "" #: .././io/open.c:733 #, c-format msgid "geom.rtblocks = %llu\n" msgstr "" #: .././io/open.c:735 #, c-format msgid "geom.rtextents = %llu\n" msgstr "" #: .././io/open.c:737 #, c-format msgid "geom.rtextsize = %u\n" msgstr "" #: .././io/open.c:738 #, c-format msgid "geom.sunit = %u\n" msgstr "" #: .././io/open.c:739 #, c-format msgid "geom.swidth = %u\n" msgstr "" #: .././io/open.c:744 #, c-format msgid "counts.freedata = %llu\n" msgstr "" #: .././io/open.c:746 #, c-format msgid "counts.freertx = %llu\n" msgstr "" #: .././io/open.c:748 #, c-format msgid "counts.freeino = %llu\n" msgstr "" #: .././io/open.c:750 #, c-format msgid "counts.allocino = %llu\n" msgstr "" #: .././io/open.c:760 #, c-format msgid "" "\n" "Query physical information about an inode\n" " Default:\t-- Return 1 if any inode number greater than 32 bits exists in\n" "\t\t the filesystem, or 0 if none exist\n" " num\t\t-- Return inode number [num] if in use, or 0 if not in use\n" " -n num\t-- Return the next used inode after [num]\n" " -v\t\t-- Verbose mode - display returned inode number's size in bits\n" "\n" msgstr "" #: .././io/open.c:843 #, c-format msgid "%s is not a numeric inode value\n" msgstr "" #: .././io/open.c:922 msgid "[-acdrstxT] [-m mode] [path]" msgstr "" #: .././io/open.c:923 msgid "open the file specified by path" msgstr "" #: .././io/open.c:931 msgid "[-v]" msgstr "" #: .././io/open.c:932 msgid "statistics on the currently open file" msgstr "" #: .././io/open.c:940 msgid "close the current open file" msgstr "" #: .././io/open.c:946 msgid "statistics on the filesystem of the currently open file" msgstr "" #: .././io/open.c:950 msgid "[-D | -R] projid" msgstr "" #: .././io/open.c:955 msgid "change project identifier on the currently open file" msgstr "" #: .././io/open.c:960 msgid "[-D | -R]" msgstr "" #: .././io/open.c:965 msgid "list project identifier set on the currently open file" msgstr "" #: .././io/open.c:970 msgid "[-D | -R] [extsize]" msgstr "" #: .././io/open.c:975 msgid "get/set preferred extent size (in bytes) for the open file" msgstr "" #: .././io/open.c:980 msgid "[-nv] [num]" msgstr "" #: .././io/open.c:985 msgid "Query inode number usage in the filesystem" msgstr "" #: .././io/parent.c:48 #, c-format msgid "%s%s" msgstr "" #: .././io/parent.c:53 #, c-format msgid "inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n" msgstr "" #: .././io/parent.c:57 #, c-format msgid "path \"%s\" does not stat for inode: %llu; err = %s\n" msgstr "" #: .././io/parent.c:66 #, c-format msgid "path \"%s\" found\n" msgstr "" #: .././io/parent.c:72 #, c-format msgid "inode-path for inode: %llu is incorrect - wrong inode#\n" msgstr "" #: .././io/parent.c:76 .././io/parent.c:106 #, c-format msgid "ino mismatch for path \"%s\" %llu vs %llu\n" msgstr "" #: .././io/parent.c:84 #, c-format msgid "inode number match: %llu\n" msgstr "" #: .././io/parent.c:94 #, c-format msgid "parent path \"%s\" does not stat: %s\n" msgstr "" #: .././io/parent.c:102 #, c-format msgid "inode-path for inode: %llu is incorrect - wrong parent inode#\n" msgstr "" #: .././io/parent.c:115 #, c-format msgid "parent ino match for %llu\n" msgstr "" #: .././io/parent.c:137 #, c-format msgid "parentpaths failed for ino %llu: %s\n" msgstr "" #: .././io/parent.c:148 #, c-format msgid "inode-path for inode: %llu is missing\n" msgstr "" #: .././io/parent.c:172 #, c-format msgid "can't stat mount point \"%s\": %s\n" msgstr "" #: .././io/parent.c:193 #, c-format msgid "failed to get bulkstat information for inode %llu\n" msgstr "" #: .././io/parent.c:199 #, c-format msgid "failed to get valid bulkstat information for inode %llu\n" msgstr "" #: .././io/parent.c:211 #, c-format msgid "checking inode %llu\n" msgstr "" #: .././io/parent.c:226 #, c-format msgid "syssgi bulkstat failed: %s\n" msgstr "" #: .././io/parent.c:248 #, c-format msgid "unable to open \"%s\" for jdm: %s\n" msgstr "" #: .././io/parent.c:258 #, c-format msgid "unable to allocate buffers: %s\n" msgstr "" #: .././io/parent.c:268 #, c-format msgid "num errors: %d\n" msgstr "" #: .././io/parent.c:270 #, c-format msgid "succeeded checking %llu inodes\n" msgstr "" #: .././io/parent.c:283 #, c-format msgid "p_ino = %llu\n" msgstr "" #: .././io/parent.c:284 #, c-format msgid "p_gen = %u\n" msgstr "" #: .././io/parent.c:285 #, c-format msgid "p_reclen = %u\n" msgstr "" #: .././io/parent.c:287 #, c-format msgid "p_name = \"%s%s\"\n" msgstr "" #: .././io/parent.c:289 #, c-format msgid "p_name = \"%s\"\n" msgstr "" #: .././io/parent.c:311 #, c-format msgid "%s: failed path_to_fshandle \"%s\": %s\n" msgstr "" #: .././io/parent.c:319 #, c-format msgid "%s: path_to_handle failed for \"%s\"\n" msgstr "" #: .././io/parent.c:326 #, c-format msgid "%s: unable to allocate parent buffer: %s\n" msgstr "" #: .././io/parent.c:347 #, c-format msgid "%s: %s call failed for \"%s\": %s\n" msgstr "" #: .././io/parent.c:356 #, c-format msgid "%s: inode-path is missing\n" msgstr "" #: .././io/parent.c:388 #, c-format msgid "file argument, \"%s\", is not in a mounted XFS filesystem\n" msgstr "" #: .././io/parent.c:428 #, c-format msgid "" "\n" " list the current file's parents and their filenames\n" "\n" " -c -- check the current file's file system for parent consistency\n" " -p -- list the current file's parents and their full paths\n" " -v -- verbose mode\n" "\n" msgstr "" #: .././io/parent.c:444 msgid "[-cpv]" msgstr "" #: .././io/parent.c:446 msgid "print or check parent inodes" msgstr "" #: .././io/pread.c:32 #, c-format msgid "" "\n" " reads a range of bytes in a specified block size from the given offset\n" "\n" " Example:\n" " 'pread -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n" "\n" " Reads a segment of the currently open file, optionally dumping it to the\n" " standard output stream (with -v option) for subsequent inspection.\n" " The reads are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different pattern is requested.\n" " -B -- read backwards through the range from offset (backwards N bytes)\n" " -F -- read forwards through the range of bytes from offset (default)\n" " -v -- be verbose, dump out buffers (used when reading forwards)\n" " -R -- read at random offsets in the range of bytes\n" " -Z N -- zeed the random number generator (used when reading randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" " -V N -- use vectored IO with N iovecs of blocksize each (preadv)\n" "\n" " When in \"random\" mode, the number of read operations will equal the\n" " number required to do a complete forward/backward scan of the range.\n" " Note that the offset within the range is chosen at random each time\n" " (an offset may be read more than once when operating in this mode).\n" "\n" msgstr "" #: .././io/pread.c:400 .././io/pwrite.c:271 #, c-format msgid "non-numeric bsize -- %s\n" msgstr "" #: .././io/pread.c:430 .././io/pwrite.c:318 #, c-format msgid "non-numeric vector count == %s\n" msgstr "" #: .././io/pread.c:507 msgid "[-b bs] [-v] [-i N] [-FBR [-Z N]] off len" msgstr "" #: .././io/pread.c:508 msgid "reads a number of bytes at a specified offset" msgstr "" #: .././io/prealloc.c:175 #, c-format msgid "" "\n" " modifies space associated with part of a file via fallocate\n" " Example:\n" " 'falloc 0 1m' - fills all holes within the first megabyte\n" "\n" " falloc uses the fallocate system call to alter space allocations in the\n" " open file. The following operations are supported:\n" " All the file offsets are in units of bytes.\n" " -c -- collapses the given range.\n" " -i -- inserts a hole into the given range of the file.\n" " -k -- do not change file size.\n" " -p -- unmap the given range from the file.\n" " -u -- unshare shared extents in the given range.\n" "\n" msgstr "" #: .././io/prealloc.c:347 .././io/prealloc.c:355 .././io/prealloc.c:363 #: .././io/prealloc.c:371 .././io/prealloc.c:381 .././io/prealloc.c:408 #: .././io/prealloc.c:418 .././io/prealloc.c:428 .././io/prealloc.c:448 msgid "off len" msgstr "" #: .././io/prealloc.c:348 msgid "allocates zeroed space for part of a file" msgstr "" #: .././io/prealloc.c:356 msgid "frees space associated with part of a file" msgstr "" #: .././io/prealloc.c:365 msgid "reserves space associated with part of a file" msgstr "" #: .././io/prealloc.c:374 msgid "frees reserved space associated with part of a file" msgstr "" #: .././io/prealloc.c:383 msgid "Converts the given range of a file to allocated zeros" msgstr "" #: .././io/prealloc.c:397 msgid "[-c] [-k] [-p] [-u] off len" msgstr "" #: .././io/prealloc.c:399 msgid "allocates space associated with part of a file via fallocate" msgstr "" #: .././io/prealloc.c:410 msgid "de-allocates space assocated with part of a file via fallocate" msgstr "" #: .././io/prealloc.c:420 msgid "de-allocates space and eliminates the hole by shifting extents" msgstr "" #: .././io/prealloc.c:430 msgid "creates new space for writing within file by shifting extents" msgstr "" #: .././io/prealloc.c:438 msgid "[-k] off len" msgstr "" #: .././io/prealloc.c:440 msgid "zeroes space and eliminates holes by preallocating" msgstr "" #: .././io/prealloc.c:450 msgid "unshares shared blocks within the range" msgstr "" #: .././io/pwrite.c:31 #, c-format msgid "" "\n" " writes a range of bytes (in block size increments) from the given offset\n" "\n" " Example:\n" " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Writes into a segment of the currently open file, using either a buffer\n" " filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n" " The writes are performed in sequential blocks starting at offset, with the\n" " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n" " unless a different write pattern is requested.\n" " -S -- use an alternate seed number for filling the write buffer\n" " -i -- input file, source of data to write (used when writing forward)\n" " -d -- open the input file for direct IO\n" " -s -- skip a number of bytes at the start of the input file\n" " -w -- call fdatasync(2) at the end (included in timing results)\n" " -W -- call fsync(2) at the end (included in timing results)\n" " -B -- write backwards through the range from offset (backwards N bytes)\n" " -F -- write forwards through the range of bytes from offset (default)\n" " -R -- write at random offsets in the specified range of bytes\n" " -Z N -- zeed the random number generator (used when writing randomly)\n" " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n" " -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n" "\n" msgstr "" #: .././io/pwrite.c:298 #, c-format msgid "non-numeric skip -- %s\n" msgstr "" #: .././io/pwrite.c:409 msgid "" "[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] [-FBR [-Z N]] [-V N] off " "len" msgstr "" #: .././io/pwrite.c:411 msgid "writes a number of bytes at a specified offset" msgstr "" #: .././io/readdir.c:193 #, c-format msgid "read %llu bytes from offset %lld\n" msgstr "" #: .././io/readdir.c:194 #, c-format msgid "%s, %d ops, %s (%s/sec and %.4f ops/sec)\n" msgstr "" #: .././io/readdir.c:207 msgid "[-v][-o offset][-l length]" msgstr "" #: .././io/readdir.c:208 msgid "read directory entries" msgstr "" #: .././io/reflink.c:32 #, c-format msgid "" "\n" " Links a range of bytes (in block size increments) from a file into a range\n" " of bytes in the open file. The contents of both file ranges must match.\n" "\n" " Example:\n" " 'dedupe some_file 0 4096 32768' - links 32768 bytes from some_file at\n" " offset 0 to into the open file at\n" " position 4096\n" "\n" " Reflink a range of blocks from a given input file to the open file. Both\n" " files share the same range of physical disk blocks; a write to the shared\n" " range of either file should result in the write landing in a new block and\n" " that range of the file being remapped (i.e. copy-on-write). Both files\n" " must reside on the same filesystem, and the contents of both ranges must\n" " match.\n" msgstr "" #: .././io/reflink.c:87 msgid "Extents did not match." msgstr "" #: .././io/reflink.c:141 .././io/reflink.c:264 #, c-format msgid "non-numeric src offset argument -- %s\n" msgstr "" #: .././io/reflink.c:147 .././io/reflink.c:270 #, c-format msgid "non-numeric dest offset argument -- %s\n" msgstr "" #: .././io/reflink.c:153 .././io/reflink.c:276 #, c-format msgid "non-positive length argument -- %s\n" msgstr "" #: .././io/reflink.c:178 #, c-format msgid "" "\n" " Links a range of bytes (in block size increments) from a file into a range\n" " of bytes in the open file. The two extent ranges need not contain " "identical\n" " data.\n" "\n" " Example:\n" " 'reflink some_file 0 4096 32768' - links 32768 bytes from some_file at\n" " offset 0 to into the open file at\n" " position 4096\n" " 'reflink some_file' - links all bytes from some_file into the open file\n" " at position 0\n" "\n" " Reflink a range of blocks from a given input file to the open file. Both\n" " files share the same range of physical disk blocks; a write to the shared\n" " range of either file should result in the write landing in a new block and\n" " that range of the file being remapped (i.e. copy-on-write). Both files\n" " must reside on the same filesystem.\n" msgstr "" #: .././io/reflink.c:309 .././io/reflink.c:323 msgid "infile src_off dst_off len" msgstr "" #: .././io/reflink.c:311 msgid "reflinks a number of bytes at a specified offset" msgstr "" #: .././io/reflink.c:325 msgid "dedupes a number of bytes at a specified offset" msgstr "" #: .././io/resblks.c:38 #, c-format msgid "non-numeric argument -- %s\n" msgstr "" #: .././io/resblks.c:50 #, c-format msgid "reserved blocks = %llu\n" msgstr "" #: .././io/resblks.c:52 #, c-format msgid "available reserved blocks = %llu\n" msgstr "" #: .././io/resblks.c:65 msgid "[blocks]" msgstr "" #: .././io/resblks.c:67 msgid "get and/or set count of reserved filesystem blocks" msgstr "" #: .././io/seek.c:32 #, c-format msgid "" "\n" " returns the next hole and/or data offset at or after the requested offset\n" "\n" " Example:\n" " 'seek -d 512'\t\t- offset of data at or following offset 512\n" " 'seek -a -r 0'\t- offsets of all data and hole in entire file\n" "\n" " Returns the offset of the next data and/or hole. There is an implied hole\n" " at the end of file. If the specified offset is past end of file, or there\n" " is no data past the specified offset, EOF is returned.\n" " -a\t-- return the next data and hole starting at the specified offset.\n" " -d\t-- return the next data starting at the specified offset.\n" " -h\t-- return the next hole starting at the specified offset.\n" " -r\t-- return all remaining type(s) starting at the specified offset.\n" " -s\t-- also print the starting offset.\n" "\n" msgstr "" #: .././io/seek.c:218 msgid "-a | -d | -h [-r] off" msgstr "" #: .././io/seek.c:219 msgid "locate the next data and/or hole" msgstr "" #: .././io/sendfile.c:31 #, c-format msgid "" "\n" " transfer a range of bytes from the given offset between files\n" "\n" " Example:\n" " 'send -f 2 512 20' - writes 20 bytes at 512 bytes into the open file\n" "\n" " Copies data between one file descriptor and another. Because this copying\n" " is done within the kernel, sendfile does not need to transfer data to and\n" " from user space.\n" " -f -- specifies an input file from which to source data to write\n" " -i -- specifies an input file name from which to source data to write.\n" " An offset and length in the source file can be optionally specified.\n" "\n" msgstr "" #: .././io/sendfile.c:171 msgid "-i infile | -f N [off len]" msgstr "" #: .././io/sendfile.c:173 msgid "Transfer data directly between file descriptors" msgstr "" #: .././io/shutdown.c:58 msgid "[-f]" msgstr "" #: .././io/shutdown.c:60 msgid "shuts down the filesystem where the current file resides" msgstr "" #: .././io/sync.c:57 msgid "calls sync(2) to flush all in-core filesystem state to disk" msgstr "" #: .././io/sync.c:66 msgid "calls syncfs(2) to flush all in-core filesystem state to disk" msgstr "" #: .././io/sync_file_range.c:30 #, c-format msgid "" "\n" " Trigger specific writeback commands on a range of the current file\n" "\n" " With no options, the SYNC_FILE_RANGE_WRITE is implied.\n" " -a -- wait for IO to finish after writing (SYNC_FILE_RANGE_WAIT_AFTER).\n" " -b -- wait for IO to finish before writing (SYNC_FILE_RANGE_WAIT_BEFORE).\n" " -w -- write dirty data in range (SYNC_FILE_RANGE_WRITE).\n" "\n" msgstr "" #: .././io/sync_file_range.c:101 msgid "[-abw] off len" msgstr "" #: .././io/sync_file_range.c:102 msgid "Control writeback on a range of a file" msgstr "" #: .././io/truncate.c:37 #, c-format msgid "non-numeric truncate argument -- %s\n" msgstr "" #: .././io/truncate.c:57 msgid "off" msgstr "" #: .././io/truncate.c:59 msgid "truncates the current file at the given offset" msgstr "" #: .././libxcmd/command.c:85 #, c-format msgid "bad argument count %d to %s, expected at least %d arguments\n" msgstr "" #: .././libxcmd/command.c:89 #, c-format msgid "bad argument count %d to %s, expected %d arguments\n" msgstr "" #: .././libxcmd/command.c:93 #, c-format msgid "bad argument count %d to %s, expected between %d and %d arguments\n" msgstr "" #: .././libxcmd/command.c:155 #, c-format msgid "cannot strdup command '%s': %s\n" msgstr "" #: .././libxcmd/command.c:171 .././libxcmd/command.c:189 #, c-format msgid "command \"%s\" not found\n" msgstr "" #: .././libxcmd/command.c:212 #, c-format msgid "%s %lld/%lld bytes at offset %lld\n" msgstr "" #: .././libxcmd/command.c:214 #, c-format msgid "%s, %d ops; %s (%s/sec and %.4f ops/sec)\n" msgstr "" #: .././libxcmd/paths.c:285 #, c-format msgid "%s: unable to extract mount options for \"%s\"\n" msgstr "" #: .././libxcmd/paths.c:371 #, c-format msgid "%s: getmntinfo() failed: %s\n" msgstr "" #: .././libxcmd/paths.c:440 #, c-format msgid "%s: cannot setup path for mount %s: %s\n" msgstr "" #: .././libxcmd/paths.c:462 #, c-format msgid "%s: cannot find mount point for path `%s': %s\n" msgstr "" #: .././libxcmd/paths.c:490 #, c-format msgid "%s: cannot setup path for project %s: %s\n" msgstr "" #: .././libxcmd/paths.c:531 #, c-format msgid "%s: cannot initialise path table: %s\n" msgstr "" #: .././libxcmd/paths.c:551 #, c-format msgid "%s: cannot setup path for project dir %s: %s\n" msgstr "" #: .././libxcmd/quit.c:43 msgid "exit the program" msgstr "" #: .././libxcmd/topology.c:165 #, c-format msgid "%s: %s appears to contain an existing filesystem (%s).\n" msgstr "" #: .././libxcmd/topology.c:169 #, c-format msgid "%s: %s appears to contain a partition table (%s).\n" msgstr "" #: .././libxcmd/topology.c:173 #, c-format msgid "%s: %s appears to contain something weird according to blkid\n" msgstr "" #: .././libxcmd/topology.c:182 #, c-format msgid "%s: probe of %s failed, cannot detect existing filesystem.\n" msgstr "" #: .././libxcmd/topology.c:204 #, c-format msgid "%s: Warning: trying to probe topology of a file %s!\n" msgstr "" #: .././libxcmd/topology.c:245 #, c-format msgid "warning: device is not properly aligned %s\n" msgstr "" #: .././libxcmd/topology.c:250 #, c-format msgid "Use -f to force usage of a misaligned device\n" msgstr "" #: .././libxcmd/topology.c:264 #, c-format msgid "warning: unable to probe device topology for device %s\n" msgstr "" #: .././libxfs/darwin.c:41 #, c-format msgid "%s: error opening the device special file \"%s\": %s\n" msgstr "" #: .././libxfs/darwin.c:48 #, c-format msgid "%s: can't tell if \"%s\" is writable: %s\n" msgstr "" #: .././libxfs/darwin.c:76 .././libxfs/freebsd.c:116 .././libxfs/irix.c:58 #: .././libxfs/linux.c:170 #, c-format msgid "%s: cannot stat the device file \"%s\": %s\n" msgstr "" #: .././libxfs/darwin.c:86 #, c-format msgid "%s: can't determine device size: %s\n" msgstr "" #: .././libxfs/darwin.c:139 .././libxfs/freebsd.c:196 .././libxfs/irix.c:106 #: .././libxfs/linux.c:260 #, c-format msgid "%s: can't determine memory size\n" msgstr "" #: .././libxfs/freebsd.c:49 .././libxfs/linux.c:76 #, c-format msgid "%s: %s possibly contains a mounted filesystem\n" msgstr "" #: .././libxfs/freebsd.c:60 .././libxfs/linux.c:104 #, c-format msgid "%s: %s contains a mounted filesystem\n" msgstr "" #: .././libxfs/freebsd.c:75 #, c-format msgid "%s: %s contains a possibly writable, mounted filesystem\n" msgstr "" #: .././libxfs/freebsd.c:89 .././libxfs/linux.c:100 #, c-format msgid "%s: %s contains a mounted and writable filesystem\n" msgstr "" #: .././libxfs/freebsd.c:129 #, c-format msgid "%s: Not a device or file: \"%s\"\n" msgstr "" #: .././libxfs/freebsd.c:135 #, c-format msgid "%s: DIOCGMEDIASIZE failed on \"%s\": %s\n" msgstr "" #: .././libxfs/freebsd.c:141 #, c-format msgid "%s: DIOCGSECTORSIZE failed on \"%s\": %s\n" msgstr "" #: .././libxfs/init.c:97 .././libxfs/init.c:196 #, c-format msgid "%s: %s: device %lld is not open\n" msgstr "" #: .././libxfs/init.c:133 #, c-format msgid "%s: cannot stat %s: %s\n" msgstr "" #: .././libxfs/init.c:158 #, c-format msgid "%s: device %lld is already open\n" msgstr "" #: .././libxfs/init.c:171 #, c-format msgid "%s: %s: too many open devices\n" msgstr "" #: .././libxfs/init.c:214 #, c-format msgid "%s: can't find a character device matching %s\n" msgstr "" #: .././libxfs/init.c:220 #, c-format msgid "%s: can't find a block device matching %s\n" msgstr "" #: .././libxfs/init.c:348 #, c-format msgid "%s: can't get size for data subvolume\n" msgstr "" #: .././libxfs/init.c:353 #, c-format msgid "%s: can't get size for log subvolume\n" msgstr "" #: .././libxfs/init.c:358 #, c-format msgid "%s: can't get size for realtime subvolume\n" msgstr "" #: .././libxfs/init.c:453 #, c-format msgid "%s: filesystem has a realtime subvolume\n" msgstr "" #: .././libxfs/init.c:475 #, c-format msgid "%s: realtime init - %llu != %llu\n" msgstr "" #: .././libxfs/init.c:483 #, c-format msgid "%s: realtime size check failed\n" msgstr "" #: .././libxfs/init.c:605 #, c-format msgid "%s: buftarg init failed\n" msgstr "" #: .././libxfs/init.c:626 #, c-format msgid "%s: bad buftarg reinit, ddev\n" msgstr "" #: .././libxfs/init.c:633 #, c-format msgid "%s: bad buftarg reinit, ldev mismatch\n" msgstr "" #: .././libxfs/init.c:640 #, c-format msgid "%s: bad buftarg reinit, logdev\n" msgstr "" #: .././libxfs/init.c:647 #, c-format msgid "%s: bad buftarg reinit, rtdev\n" msgstr "" #: .././libxfs/init.c:741 #, c-format msgid "%s: size check failed\n" msgstr "" #: .././libxfs/init.c:753 #, c-format msgid "%s: V1 inodes unsupported. Please try an older xfsprogs.\n" msgstr "" #: .././libxfs/init.c:762 #, c-format msgid "%s: V1 directories unsupported. Please try an older xfsprogs.\n" msgstr "" #: .././libxfs/init.c:770 #, c-format msgid "%s: Unsupported features detected. Please try a newer xfsprogs.\n" msgstr "" #: .././libxfs/init.c:790 #, c-format msgid "%s: data size check failed\n" msgstr "" #: .././libxfs/init.c:804 #, c-format msgid "%s: log size checks failed\n" msgstr "" #: .././libxfs/init.c:815 #, c-format msgid "%s: realtime device init failed\n" msgstr "" #: .././libxfs/init.c:822 #, c-format msgid "%s: perag init failed\n" msgstr "" #: .././libxfs/kmem.c:15 #, c-format msgid "%s: zone init failed (%s, %d bytes): %s\n" msgstr "" #: .././libxfs/kmem.c:32 #, c-format msgid "%s: zone alloc failed (%s, %d bytes): %s\n" msgstr "" #: .././libxfs/kmem.c:56 #, c-format msgid "%s: malloc failed (%d bytes): %s\n" msgstr "" #: .././libxfs/kmem.c:77 #, c-format msgid "%s: realloc failed (%d bytes): %s\n" msgstr "" #: .././libxfs/linux.c:137 #, c-format msgid "%s: %s - cannot set blocksize %d on block device %s: %s\n" msgstr "" #: .././libxfs/linux.c:205 #, c-format msgid "%s: can't determine device size\n" msgstr "" #: .././libxfs/linux.c:213 #, c-format msgid "%s: warning - cannot get sector size from block device %s: %s\n" msgstr "" #: .././libxfs/rdwr.c:82 #, c-format msgid "%s: %s can't memalign %d bytes: %s\n" msgstr "" #: .././libxfs/rdwr.c:92 #, c-format msgid "%s: %s seek to offset %llu failed: %s\n" msgstr "" #: .././libxfs/rdwr.c:102 #, c-format msgid "%s: %s write failed: %s\n" msgstr "" #: .././libxfs/rdwr.c:106 #, c-format msgid "%s: %s not progressing?\n" msgstr "" #: .././libxfs/rdwr.c:581 #, c-format msgid "%s: %s can't memalign %u bytes: %s\n" msgstr "" #: .././libxfs/rdwr.c:614 #, c-format msgid "%s: %s can't malloc %u bytes: %s\n" msgstr "" #: .././libxfs/rdwr.c:697 #, c-format msgid "%s: %s invalid map %p or nmaps %d\n" msgstr "" #: .././libxfs/rdwr.c:704 #, c-format msgid "%s: %s map blkno 0x%llx doesn't match key 0x%llx\n" msgstr "" #: .././libxfs/rdwr.c:749 #, c-format msgid "Warning: recursive buffer locking at block % detected\n" msgstr "" #: .././libxfs/rdwr.c:921 #, c-format msgid "%s: read failed: %s\n" msgstr "" #: .././libxfs/rdwr.c:927 #, c-format msgid "%s: error - read only %d of %d bytes\n" msgstr "" #: .././libxfs/rdwr.c:1089 #, c-format msgid "%s: pwrite failed: %s\n" msgstr "" #: .././libxfs/rdwr.c:1095 #, c-format msgid "%s: error - pwrite only %d of %d bytes\n" msgstr "" #: .././libxfs/rdwr.c:1130 #, c-format msgid "%s: write verifer failed on %s bno 0x%llx/0x%x\n" msgstr "" #: .././libxfs/trans.c:69 #, c-format msgid "%s: lidp calloc failed (%d bytes): %s\n" msgstr "" #: .././libxfs/trans.c:183 #, c-format msgid "%s: xact calloc failed (%d bytes): %s\n" msgstr "" #: .././libxfs/trans.c:670 #, c-format msgid "%s: warning - imap_to_bp failed (%d)\n" msgstr "" #: .././libxfs/trans.c:678 #, c-format msgid "%s: warning - iflush_int failed (%d)\n" msgstr "" #: .././libxfs/trans.c:738 .././libxfs/trans.c:792 #, c-format msgid "%s: unrecognised log item type\n" msgstr "" #: .././libxfs/util.c:617 #, c-format msgid "%s: cannot duplicate transaction: %s\n" msgstr "" #: .././libxlog/util.c:67 #, c-format msgid "%s: cannot find log head/tail (xlog_find_tail=%d)\n" msgstr "" #: .././libxlog/util.c:75 #, c-format msgid "%s: head block % tail block %\n" msgstr "" #: .././libxlog/util.c:97 #, c-format msgid "" "* ERROR: mismatched uuid in log\n" "* SB : %s\n" "* log: %s\n" msgstr "" #: .././libxlog/util.c:110 #, c-format msgid "" "\n" "LOG REC AT LSN cycle %d block %d (0x%x, 0x%x)\n" msgstr "" #: .././libxlog/util.c:118 #, c-format msgid "* ERROR: bad magic number in log header: 0x%x\n" msgstr "" #: .././libxlog/util.c:127 #, c-format msgid "* ERROR: log format incompatible (log=%d, ours=%d)\n" msgstr "" #: .././libxlog/util.c:137 .././libxlog/util.c:149 msgid "Bad log" msgstr "" #: .././logprint/log_copy.c:46 .././logprint/log_dump.c:45 #, c-format msgid "%s: read error (%lld): %s\n" msgstr "" #: .././logprint/log_copy.c:51 .././logprint/log_dump.c:50 #, c-format msgid "%s: physical end of log at %lld\n" msgstr "" #: .././logprint/log_copy.c:55 #, c-format msgid "%s: short read? (%lld)\n" msgstr "" #: .././logprint/log_copy.c:62 #, c-format msgid "%s: write error (%lld): %s\n" msgstr "" #: .././logprint/log_copy.c:67 #, c-format msgid "%s: short write? (%lld)\n" msgstr "" #: .././logprint/log_dump.c:58 #, c-format msgid "%6lld HEADER Cycle %d tail %d:%06d len %6d ops %d\n" msgstr "" #: .././logprint/log_dump.c:69 #, c-format msgid "[%05lld - %05lld] Cycle 0x%08x New Cycle 0x%08x\n" msgstr "" #: .././logprint/log_misc.c:87 #, c-format msgid "Oper (%d): tid: %x len: %d clientid: %s " msgstr "" #: .././logprint/log_misc.c:92 #, c-format msgid "flags: " msgstr "" #: .././logprint/log_misc.c:186 #, c-format msgid " Not enough data to decode further\n" msgstr "" #: .././logprint/log_misc.c:190 #, c-format msgid " tid: %x num_items: %d\n" msgstr "" #: .././logprint/log_misc.c:235 #, c-format msgid "" "#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d flags: 0x%x\n" msgstr "" #: .././logprint/log_misc.c:241 #, c-format msgid "#regs: %d Not printing rest of data\n" msgstr "" #: .././logprint/log_misc.c:258 #, c-format msgid "SUPER BLOCK Buffer: " msgstr "" #: .././logprint/log_misc.c:260 .././logprint/log_misc.c:348 #: .././logprint/log_misc.c:378 #, c-format msgid "Out of space\n" msgstr "" #: .././logprint/log_misc.c:268 #, c-format msgid "icount: %llu ifree: %llu " msgstr "" #: .././logprint/log_misc.c:273 #, c-format msgid "fdblks: %llu frext: %llu\n" msgstr "" #: .././logprint/log_misc.c:284 #, c-format msgid "AGI Buffer: XAGI " msgstr "" #: .././logprint/log_misc.c:295 #, c-format msgid "out of space\n" msgstr "" #: .././logprint/log_misc.c:298 #, c-format msgid "ver: %d " msgstr "" #: .././logprint/log_misc.c:300 #, c-format msgid "seq#: %d len: %d cnt: %d root: %d\n" msgstr "" #: .././logprint/log_misc.c:305 #, c-format msgid "level: %d free#: 0x%x newino: 0x%x\n" msgstr "" #: .././logprint/log_misc.c:315 #, c-format msgid "AGI unlinked data skipped " msgstr "" #: .././logprint/log_misc.c:316 #, c-format msgid "(CONTINUE set, no space)\n" msgstr "" #: .././logprint/log_misc.c:322 .././logprint/log_print_all.c:148 #, c-format msgid "bucket[%d - %d]: " msgstr "" #: .././logprint/log_misc.c:338 #, c-format msgid "AGF Buffer: XAGF " msgstr "" #: .././logprint/log_misc.c:351 #, c-format msgid "ver: %d seq#: %d len: %d \n" msgstr "" #: .././logprint/log_misc.c:355 #, c-format msgid "root BNO: %d CNT: %d\n" msgstr "" #: .././logprint/log_misc.c:358 #, c-format msgid "level BNO: %d CNT: %d\n" msgstr "" #: .././logprint/log_misc.c:361 #, c-format msgid "1st: %d last: %d cnt: %d freeblks: %d longest: %d\n" msgstr "" #: .././logprint/log_misc.c:375 #, c-format msgid "DQUOT Buffer: DQ " msgstr "" #: .././logprint/log_misc.c:382 #, c-format msgid "ver: %d flags: 0x%x id: %d \n" msgstr "" #: .././logprint/log_misc.c:385 #, c-format msgid "blk limits hard: %llu soft: %llu\n" msgstr "" #: .././logprint/log_misc.c:390 #, c-format msgid "blk count: %llu warns: %d timer: %d\n" msgstr "" #: .././logprint/log_misc.c:394 #, c-format msgid "ino limits hard: %llu soft: %llu\n" msgstr "" #: .././logprint/log_misc.c:399 #, c-format msgid "ino count: %llu warns: %d timer: %d\n" msgstr "" #: .././logprint/log_misc.c:405 #, c-format msgid "BUF DATA\n" msgstr "" #: .././logprint/log_misc.c:441 #, c-format msgid "QOFF: #regs: %d flags: 0x%x\n" msgstr "" #: .././logprint/log_misc.c:444 #, c-format msgid "QOFF: Not enough data to decode further\n" msgstr "" #: .././logprint/log_misc.c:454 #, c-format msgid "INODE CORE\n" msgstr "" #: .././logprint/log_misc.c:455 #, c-format msgid "magic 0x%hx mode 0%ho version %d format %d\n" msgstr "" #: .././logprint/log_misc.c:458 #, c-format msgid "nlink %hd uid %d gid %d\n" msgstr "" #: .././logprint/log_misc.c:460 #, c-format msgid "atime 0x%x mtime 0x%x ctime 0x%x\n" msgstr "" #: .././logprint/log_misc.c:462 #, c-format msgid "size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n" msgstr "" #: .././logprint/log_misc.c:465 #, c-format msgid "naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n" msgstr "" #: .././logprint/log_misc.c:468 #, c-format msgid "flags 0x%x gen 0x%x\n" msgstr "" #: .././logprint/log_misc.c:471 .././logprint/log_print_all.c:276 #, c-format msgid "flags2 0x%llx cowextsize 0x%x\n" msgstr "" #: .././logprint/log_misc.c:488 #, c-format msgid "SHORTFORM DIRECTORY size %d\n" msgstr "" #: .././logprint/log_misc.c:494 #, c-format msgid "SHORTFORM DIRECTORY size %d count %d\n" msgstr "" #: .././logprint/log_misc.c:497 #, c-format msgid ".. ino 0x%llx\n" msgstr "" #: .././logprint/log_misc.c:505 #, c-format msgid "%s ino 0x%llx namelen %d\n" msgstr "" #: .././logprint/log_misc.c:544 #, c-format msgid "INODE: " msgstr "" #: .././logprint/log_misc.c:545 #, c-format msgid "#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n" msgstr "" #: .././logprint/log_misc.c:548 #, c-format msgid " blkno: %lld len: %d boff: %d\n" msgstr "" #: .././logprint/log_misc.c:553 #, c-format msgid "INODE: #regs: %d Not printing rest of data\n" msgstr "" #: .././logprint/log_misc.c:584 #, c-format msgid "DEV inode: no extra region\n" msgstr "" #: .././logprint/log_misc.c:587 #, c-format msgid "UUID inode: no extra region\n" msgstr "" #: .././logprint/log_misc.c:604 #, c-format msgid "EXTENTS inode data\n" msgstr "" #: .././logprint/log_misc.c:607 #, c-format msgid "BTREE inode data\n" msgstr "" #: .././logprint/log_misc.c:610 #, c-format msgid "LOCAL inode data\n" msgstr "" #: .././logprint/log_misc.c:631 #, c-format msgid "EXTENTS attr data\n" msgstr "" #: .././logprint/log_misc.c:634 #, c-format msgid "BTREE attr data\n" msgstr "" #: .././logprint/log_misc.c:637 #, c-format msgid "LOCAL attr data\n" msgstr "" #: .././logprint/log_misc.c:675 #, c-format msgid "#regs: %d id: 0x%x" msgstr "" #: .././logprint/log_misc.c:676 #, c-format msgid " blkno: %lld len: %d boff: %d\n" msgstr "" #: .././logprint/log_misc.c:680 #, c-format msgid "DQUOT: #regs: %d Not printing rest of data\n" msgstr "" #: .././logprint/log_misc.c:699 #, c-format msgid "DQUOT: magic 0x%hx flags 0%ho\n" msgstr "" #: .././logprint/log_misc.c:725 #, c-format msgid "ICR: split header, not printing\n" msgstr "" #: .././logprint/log_misc.c:729 #, c-format msgid "" "ICR: #ag: %d agbno: 0x%x len: %d\n" " cnt: %d isize: %d gen: 0x%x\n" msgstr "" #: .././logprint/log_misc.c:755 #, c-format msgid "%s: lseek to %lld failed: %s\n" msgstr "" #: .././logprint/log_misc.c:801 #, c-format msgid "%s: xlog_print_record: malloc failed\n" msgstr "" #: .././logprint/log_misc.c:810 #, c-format msgid "%s: xlog_print_record: read error\n" msgstr "" #: .././logprint/log_misc.c:905 .././logprint/log_misc.c:1008 #, c-format msgid "Left over region from split log item\n" msgstr "" #: .././logprint/log_misc.c:993 #, c-format msgid "Unmount filesystem\n" msgstr "" #: .././logprint/log_misc.c:1000 #, c-format msgid "%s: unknown log operation type (%x)\n" msgstr "" #: .././logprint/log_misc.c:1041 #, c-format msgid "Header 0x%x wanted 0x%x\n" msgstr "" #: .././logprint/log_misc.c:1055 #, c-format msgid "cycle: %d\tversion: %d\t" msgstr "" #: .././logprint/log_misc.c:1061 #, c-format msgid "length of Log Record: %d\tprev offset: %d\t\tnum ops: %d\n" msgstr "" #: .././logprint/log_misc.c:1067 .././logprint/log_misc.c:1109 #, c-format msgid "cycle num overwrites: " msgstr "" #: .././logprint/log_misc.c:1076 #, c-format msgid "uuid: %s format: " msgstr "" #: .././logprint/log_misc.c:1079 #, c-format msgid "unknown\n" msgstr "" #: .././logprint/log_misc.c:1082 #, c-format msgid "little endian linux\n" msgstr "" #: .././logprint/log_misc.c:1085 #, c-format msgid "big endian linux\n" msgstr "" #: .././logprint/log_misc.c:1088 #, c-format msgid "big endian irix\n" msgstr "" #: .././logprint/log_misc.c:1094 #, c-format msgid "h_size: %d\n" msgstr "" #: .././logprint/log_misc.c:1106 #, c-format msgid "extended-header: cycle: %d\n" msgstr "" #: .././logprint/log_misc.c:1122 #, c-format msgid "* ERROR: found data after zeroed blocks block=%-21lld *\n" msgstr "" #: .././logprint/log_misc.c:1133 #, c-format msgid "* ERROR: header cycle=%-11d block=%-21lld *\n" msgstr "" #: .././logprint/log_misc.c:1144 #, c-format msgid "* ERROR: data block=%-21lld *\n" msgstr "" #: .././logprint/log_misc.c:1155 #, c-format msgid "" "* ERROR: for header block=%lld\n" "* not enough hdrs for data length, required num = %d, hdr num = %d\n" msgstr "" #: .././logprint/log_misc.c:1161 msgid "Not enough headers for data length." msgstr "" #: .././logprint/log_misc.c:1171 #, c-format msgid "%s: xlog_print: malloc failed for ext hdrs\n" msgstr "" #: .././logprint/log_misc.c:1219 .././logprint/log_misc.c:1295 #: .././logprint/log_misc.c:1366 .././logprint/log_misc.c:1403 #, c-format msgid "%s: physical end of log\n" msgstr "" #: .././logprint/log_misc.c:1225 .././logprint/log_misc.c:1300 #: .././logprint/log_misc.c:1418 #, c-format msgid "BLKNO: %lld\n" msgstr "" #: .././logprint/log_misc.c:1283 #, c-format msgid "%s: problem finding oldest LR\n" msgstr "" #: .././logprint/log_misc.c:1309 #, c-format msgid "%s: after %d zeroed blocks\n" msgstr "" #: .././logprint/log_misc.c:1378 msgid "illegal value" msgstr "" #: .././logprint/log_misc.c:1384 #, c-format msgid "%s: skipped %d cleared blocks in range: %lld - %lld\n" msgstr "" #: .././logprint/log_misc.c:1389 #, c-format msgid "%s: totally cleared log\n" msgstr "" #: .././logprint/log_misc.c:1394 #, c-format msgid "%s: skipped %d zeroed blocks in range: %lld - %lld\n" msgstr "" #: .././logprint/log_misc.c:1399 #, c-format msgid "%s: totally zeroed log\n" msgstr "" #: .././logprint/log_misc.c:1415 msgid "xlog_find_head: bad read" msgstr "" #: .././logprint/log_misc.c:1467 #, c-format msgid "%s: logical end of log\n" msgstr "" #: .././logprint/log_print_all.c:96 #, c-format msgid "" "BUF: #regs:%d start blkno:0x%llx len:%d bmap size:%d flags:0x%x\n" msgstr "" #: .././logprint/log_print_all.c:106 #, c-format msgid "\tSUPER Block Buffer:\n" msgstr "" #: .././logprint/log_print_all.c:109 #, c-format msgid " icount:%llu ifree:%llu " msgstr "" #: .././logprint/log_print_all.c:114 #, c-format msgid "fdblks:%llu frext:%llu\n" msgstr "" #: .././logprint/log_print_all.c:119 #, c-format msgid "\t\tsunit:%u swidth:%u\n" msgstr "" #: .././logprint/log_print_all.c:125 #, c-format msgid "\tAGI Buffer: (XAGI)\n" msgstr "" #: .././logprint/log_print_all.c:128 #, c-format msgid "\t\tver:%d " msgstr "" #: .././logprint/log_print_all.c:130 #, c-format msgid "seq#:%d len:%d cnt:%d root:%d\n" msgstr "" #: .././logprint/log_print_all.c:135 #, c-format msgid "\t\tlevel:%d free#:0x%x newino:0x%x\n" msgstr "" #: .././logprint/log_print_all.c:159 #, c-format msgid "\tAGF Buffer: (XAGF)\n" msgstr "" #: .././logprint/log_print_all.c:162 #, c-format msgid "\t\tver:%d seq#:%d len:%d \n" msgstr "" #: .././logprint/log_print_all.c:166 #, c-format msgid "\t\troot BNO:%d CNT:%d\n" msgstr "" #: .././logprint/log_print_all.c:169 #, c-format msgid "\t\tlevel BNO:%d CNT:%d\n" msgstr "" #: .././logprint/log_print_all.c:172 #, c-format msgid "\t\t1st:%d last:%d cnt:%d freeblks:%d longest:%d\n" msgstr "" #: .././logprint/log_print_all.c:181 #, c-format msgid "\tDQUOT Buffer:\n" msgstr "" #: .././logprint/log_print_all.c:184 #, c-format msgid "\t\tUIDs 0x%lx-0x%lx\n" msgstr "" #: .././logprint/log_print_all.c:189 #, c-format msgid "\tBUF DATA\n" msgstr "" #: .././logprint/log_print_all.c:211 #, c-format msgid "\tQUOTAOFF: #regs:%d type:%s\n" msgstr "" #: .././logprint/log_print_all.c:226 #, c-format msgid "\tDQUOT: #regs:%d blkno:%lld boffset:%u id: %d\n" msgstr "" #: .././logprint/log_print_all.c:230 #, c-format msgid "\t\tmagic 0x%x\tversion 0x%x\tID 0x%x (%d)\t\n" msgstr "" #: .././logprint/log_print_all.c:235 #, c-format msgid "\t\tblk_hard 0x%x\tblk_soft 0x%x\tino_hard 0x%x\tino_soft 0x%x\n" msgstr "" #: .././logprint/log_print_all.c:241 #, c-format msgid "\t\tbcount 0x%x (%d) icount 0x%x (%d)\n" msgstr "" #: .././logprint/log_print_all.c:246 #, c-format msgid "\t\tbtimer 0x%x itimer 0x%x \n" msgstr "" #: .././logprint/log_print_all.c:255 #, c-format msgid "\tCORE inode:\n" msgstr "" #: .././logprint/log_print_all.c:258 #, c-format msgid "\t\tmagic:%c%c mode:0x%x ver:%d format:%d\n" msgstr "" #: .././logprint/log_print_all.c:261 #, c-format msgid "\t\tuid:%d gid:%d nlink:%d projid:0x%04x%04x\n" msgstr "" #: .././logprint/log_print_all.c:264 #, c-format msgid "\t\tatime:%d mtime:%d ctime:%d\n" msgstr "" #: .././logprint/log_print_all.c:266 #, c-format msgid "\t\tflushiter:%d\n" msgstr "" #: .././logprint/log_print_all.c:267 #, c-format msgid "\t\tsize:0x%llx nblks:0x%llx exsize:%d nextents:%d anextents:%d\n" msgstr "" #: .././logprint/log_print_all.c:271 #, c-format msgid "\t\tforkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x gen:%d\n" msgstr "" #: .././logprint/log_print_all.c:295 #, c-format msgid "\tINODE: #regs:%d ino:0x%llx flags:0x%x dsize:%d\n" msgstr "" #: .././logprint/log_print_all.c:311 #, c-format msgid "\t\tDATA FORK EXTENTS inode data:\n" msgstr "" #: .././logprint/log_print_all.c:318 #, c-format msgid "\t\tDATA FORK BTREE inode data:\n" msgstr "" #: .././logprint/log_print_all.c:325 #, c-format msgid "\t\tDATA FORK LOCAL inode data:\n" msgstr "" #: .././logprint/log_print_all.c:332 #, c-format msgid "\t\tDEV inode: no extra region\n" msgstr "" #: .././logprint/log_print_all.c:336 #, c-format msgid "\t\tUUID inode: no extra region\n" msgstr "" #: .././logprint/log_print_all.c:351 #, c-format msgid "\t\tATTR FORK EXTENTS inode data:\n" msgstr "" #: .././logprint/log_print_all.c:359 #, c-format msgid "\t\tATTR FORK BTREE inode data:\n" msgstr "" #: .././logprint/log_print_all.c:367 #, c-format msgid "\t\tATTR FORK LOCAL inode data:\n" msgstr "" #: .././logprint/log_print_all.c:388 #, c-format msgid "" "\tICR: #ag: %d agbno: 0x%x len: %d\n" "\t cnt: %d isize: %d gen: 0x%x\n" msgstr "" #: .././logprint/log_print_all.c:440 #, c-format msgid "xlog_recover_print_logitem: illegal type\n" msgstr "" #: .././logprint/log_print_all.c:492 #, c-format msgid "%s: illegal type" msgstr "" #: .././logprint/log_print_all.c:500 #, c-format msgid ": cnt:%d total:%d " msgstr "" #: .././logprint/log_print_all.c:502 #, c-format msgid "a:0x%lx len:%d " msgstr "" #: .././logprint/log_print_trans.c:27 #, c-format msgid "TRANS: tid:0x%x #items:%d trans:0x%x q:0x%lx\n" msgstr "" #: .././logprint/log_print_trans.c:53 #, c-format msgid "%s: failed to find head and tail, error: %d\n" msgstr "" #: .././logprint/log_print_trans.c:58 #, c-format msgid " log tail: %lld head: %lld state: %s\n" msgstr "" #: .././logprint/log_print_trans.c:64 #, c-format msgid " override tail: %d\n" msgstr "" #: .././logprint/log_print_trans.c:84 #, c-format msgid "" "Superblock has unknown incompatible log features (0x%x) enabled.\n" "Output may be incomplete or inaccurate. It is recommended that you\n" "upgrade your xfsprogs installation to match the filesystem features.\n" msgstr "" #: .././logprint/log_print_trans.c:92 #, c-format msgid "%s: failed in xfs_do_recovery_pass, error: %d\n" msgstr "" #: .././logprint/log_redo.c:71 #, c-format msgid "%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n" msgstr "" #: .././logprint/log_redo.c:94 .././logprint/log_redo.c:110 #, c-format msgid "%s: xlog_print_trans_efi: malloc failed\n" msgstr "" #: .././logprint/log_redo.c:104 #, c-format msgid "EFI: Not enough data to decode further\n" msgstr "" #: .././logprint/log_redo.c:118 #, c-format msgid "EFI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:122 #, c-format msgid "EFI free extent data skipped (CONTINUE set, no space)\n" msgstr "" #: .././logprint/log_redo.c:161 #, c-format msgid "%s: xlog_recover_print_efi: malloc failed\n" msgstr "" #: .././logprint/log_redo.c:170 #, c-format msgid "\tEFI: #regs:%d\tnum_extents:%d id:0x%llx\n" msgstr "" #: .././logprint/log_redo.c:202 #, c-format msgid "EFD: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:210 #, c-format msgid "EFD: Not enough data to decode further\n" msgstr "" #: .././logprint/log_redo.c:228 #, c-format msgid "\tEFD: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:249 #, c-format msgid "%s: bad size of RUI format: %u; expected %u; nextents = %u\n" msgstr "" #: .././logprint/log_redo.c:276 .././logprint/log_redo.c:295 #: .././logprint/log_redo.c:424 .././logprint/log_redo.c:443 #: .././logprint/log_redo.c:567 .././logprint/log_redo.c:586 #, c-format msgid "%s: %s: malloc failed\n" msgstr "" #: .././logprint/log_redo.c:288 #, c-format msgid "RUI: Not enough data to decode further\n" msgstr "" #: .././logprint/log_redo.c:304 #, c-format msgid "RUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:308 #, c-format msgid "RUI extent data skipped (CONTINUE set, no space)\n" msgstr "" #: .././logprint/log_redo.c:359 #, c-format msgid "RUD: #regs: %d\t id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:367 #, c-format msgid "RUD: Not enough data to decode further\n" msgstr "" #: .././logprint/log_redo.c:401 #, c-format msgid "%s: bad size of CUI format: %u; expected %u; nextents = %u\n" msgstr "" #: .././logprint/log_redo.c:436 #, c-format msgid "CUI: Not enough data to decode further\n" msgstr "" #: .././logprint/log_redo.c:452 #, c-format msgid "CUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:456 #, c-format msgid "CUI extent data skipped (CONTINUE set, no space)\n" msgstr "" #: .././logprint/log_redo.c:502 #, c-format msgid "CUD: #regs: %d\t id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:510 #, c-format msgid "CUD: Not enough data to decode further\n" msgstr "" #: .././logprint/log_redo.c:544 #, c-format msgid "%s: bad size of BUI format: %u; expected %u; nextents = %u\n" msgstr "" #: .././logprint/log_redo.c:579 #, c-format msgid "BUI: Not enough data to decode further\n" msgstr "" #: .././logprint/log_redo.c:595 #, c-format msgid "BUI: #regs: %d\tnum_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:599 #, c-format msgid "BUI extent data skipped (CONTINUE set, no space)\n" msgstr "" #: .././logprint/log_redo.c:646 #, c-format msgid "BUD: #regs: %d\t id: 0x%llx\n" msgstr "" #: .././logprint/log_redo.c:654 #, c-format msgid "BUD: Not enough data to decode further\n" msgstr "" #: .././logprint/logprint.c:45 #, c-format msgid "" "Usage: %s [options...] \n" "\n" "Options:\n" " -c\t try to continue if error found in log\n" " -C copy the log from the filesystem to filename\n" " -d\t dump the log in log-record format\n" " -e\t exit when an error is found in the log\n" " -f\t specified device is actually a file\n" " -l filename of external log\n" " -n\t don't try and interpret log data\n" " -o\t print buffer data in hex\n" " -s block # to start printing\n" " -v print \"overwrite\" data\n" " -t\t print out transactional view\n" "\t-b in transactional view, extract buffer info\n" "\t-i in transactional view, extract inode info\n" "\t-q in transactional view, extract quota info\n" " -D print only data; no decoding\n" " -V print version information\n" msgstr "" #: .././logprint/logprint.c:79 #, c-format msgid " Can't open device %s: %s\n" msgstr "" #: .././logprint/logprint.c:85 #, c-format msgid " read of XFS superblock failed\n" msgstr "" #: .././logprint/logprint.c:105 #, c-format msgid "" " external log device not specified\n" "\n" msgstr "" #: .././logprint/logprint.c:121 #, c-format msgid "Can't open file %s: %s\n" msgstr "" #: .././logprint/logprint.c:222 #, c-format msgid "xfs_logprint:\n" msgstr "" #: .././logprint/logprint.c:231 #, c-format msgid " data device: 0x%llx\n" msgstr "" #: .././logprint/logprint.c:234 #, c-format msgid " log file: \"%s\" " msgstr "" #: .././logprint/logprint.c:236 #, c-format msgid " log device: 0x%llx " msgstr "" #: .././logprint/logprint.c:239 #, c-format msgid "" "daddr: %lld length: %lld\n" "\n" msgstr "" #: .././mkfs/proto.c:79 #, c-format msgid "%s: failed to open %s: %s\n" msgstr "" #: .././mkfs/proto.c:86 .././mkfs/proto.c:309 #, c-format msgid "%s: read failed on %s: %s\n" msgstr "" #: .././mkfs/proto.c:91 #, c-format msgid "%s: proto file %s premature EOF\n" msgstr "" #: .././mkfs/proto.c:125 msgid "cannot reserve space" msgstr "" #: .././mkfs/proto.c:180 #, c-format msgid "%s: premature EOF in prototype file\n" msgstr "" #: .././mkfs/proto.c:200 msgid "error reserving space for a file" msgstr "" #: .././mkfs/proto.c:267 msgid "error allocating space for a file" msgstr "" #: .././mkfs/proto.c:271 #, c-format msgid "%s: cannot allocate space for file\n" msgstr "" #: .././mkfs/proto.c:336 msgid "directory createname error" msgstr "" #: .././mkfs/proto.c:350 msgid "directory create error" msgstr "" #: .././mkfs/proto.c:415 .././mkfs/proto.c:427 .././mkfs/proto.c:438 #: .././mkfs/proto.c:445 #, c-format msgid "%s: bad format string %s\n" msgstr "" #: .././mkfs/proto.c:466 .././mkfs/proto.c:513 .././mkfs/proto.c:528 #: .././mkfs/proto.c:540 .././mkfs/proto.c:552 .././mkfs/proto.c:563 msgid "Inode allocation failed" msgstr "" #: .././mkfs/proto.c:481 #, c-format msgid "%s: Bad value %s for proto file %s\n" msgstr "" #: .././mkfs/proto.c:490 msgid "Inode pre-allocation failed" msgstr "" #: .././mkfs/proto.c:500 msgid "Pre-allocated file creation failed" msgstr "" #: .././mkfs/proto.c:582 msgid "Directory creation failed" msgstr "" #: .././mkfs/proto.c:603 msgid "Unknown format" msgstr "" #: .././mkfs/proto.c:608 msgid "Error encountered creating file from prototype file" msgstr "" #: .././mkfs/proto.c:660 msgid "Realtime bitmap inode allocation failed" msgstr "" #: .././mkfs/proto.c:677 msgid "Realtime summary inode allocation failed" msgstr "" #: .././mkfs/proto.c:704 msgid "Allocation of the realtime bitmap failed" msgstr "" #: .././mkfs/proto.c:717 msgid "Completion of the realtime bitmap failed" msgstr "" #: .././mkfs/proto.c:740 msgid "Allocation of the realtime summary failed" msgstr "" #: .././mkfs/proto.c:752 msgid "Completion of the realtime summary failed" msgstr "" #: .././mkfs/proto.c:770 msgid "Error initializing the realtime space" msgstr "" #: .././mkfs/proto.c:775 msgid "Error completing the realtime space" msgstr "" #: .././mkfs/xfs_mkfs.c:752 #, c-format msgid "both data sunit and data swidth options must be specified\n" msgstr "" #: .././mkfs/xfs_mkfs.c:760 #, c-format msgid "both data su and data sw options must be specified\n" msgstr "" #: .././mkfs/xfs_mkfs.c:767 #, c-format msgid "data su must be a multiple of the sector size (%d)\n" msgstr "" #: .././mkfs/xfs_mkfs.c:778 #, c-format msgid "" "data stripe width (%d) must be a multiple of the data stripe unit (%d)\n" msgstr "" #: .././mkfs/xfs_mkfs.c:791 .././mkfs/xfs_mkfs.c:797 #, c-format msgid "log stripe unit (%d) must be a multiple of the block size (%d)\n" msgstr "" #: .././mkfs/xfs_mkfs.c:817 #, c-format msgid "if -%s file then -%s name and -%s size are required\n" msgstr "" #: .././mkfs/xfs_mkfs.c:823 #, c-format msgid "No device name specified\n" msgstr "" #: .././mkfs/xfs_mkfs.c:835 #, c-format msgid "Error accessing specified device %s: %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:843 #, c-format msgid "%s: Use the -f option to force overwrite.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:864 #, c-format msgid "specified \"-%s file\" on a block device %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:872 #, c-format msgid "specified device %s not a file or block device\n" msgstr "" #: .././mkfs/xfs_mkfs.c:903 #, c-format msgid "log size %lld is not a multiple of the log stripe unit %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:931 #, c-format msgid "Due to stripe alignment, the internal log size (%lld) is too large.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:933 #, c-format msgid "Must fit within an allocation group.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:944 #, c-format msgid "log size %lld blocks too small, minimum size is %d blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:950 #, c-format msgid "log size %lld blocks too large, maximum size is %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:956 #, c-format msgid "log size %lld bytes too large, maximum size is %lld bytes\n" msgstr "" #: .././mkfs/xfs_mkfs.c:993 #, c-format msgid "agsize (%lld blocks) too small, need at least %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1001 #, c-format msgid "agsize (%lld blocks) too big, maximum is %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1009 #, c-format msgid "agsize (%lld blocks) too big, data area is %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1016 #, c-format msgid "too many allocation groups for size = %lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1018 #, c-format msgid "need at most %lld allocation groups\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1026 #, c-format msgid "too few allocation groups for size = %lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1028 #, c-format msgid "need at least %lld allocation groups\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1041 #, c-format msgid "last AG size %lld blocks too small, minimum size is %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1052 #, c-format msgid "%lld allocation groups is too many, maximum is %lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1082 #, c-format msgid "error reading existing superblock -- failed to memalign buffer\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1097 #, c-format msgid "error reading existing superblock: %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1267 #, c-format msgid "Illegal value %s for -%c %s option. %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1342 #, c-format msgid "" "Option -%c %s has undefined minval/maxval.Can't verify value range. This is " "a bug.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1368 msgid "value is too small" msgstr "" #: .././mkfs/xfs_mkfs.c:1370 msgid "value is too large" msgstr "" #: .././mkfs/xfs_mkfs.c:1372 msgid "value must be a power of 2" msgstr "" #: .././mkfs/xfs_mkfs.c:1932 #, c-format msgid "extra arguments\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1949 #, c-format msgid "illegal block size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1954 #, c-format msgid "Minimum block size for CRC enabled filesystems is %d bytes.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1959 #, c-format msgid "cannot disable ftype with crcs enabled\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2013 #, c-format msgid "specified blocksize %d is less than device physical sector size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2016 #, c-format msgid "switching to logical sector size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2034 #, c-format msgid "illegal sector size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2037 #, c-format msgid "block size %d cannot be smaller than logical sector size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2042 #, c-format msgid "illegal sector size %d; hw sector is %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2048 #, c-format msgid "illegal log sector size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2064 .././mkfs/xfs_mkfs.c:2194 #, c-format msgid "Minimum inode size for CRCs is %d bytes\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2072 #, c-format msgid "Inodes always aligned for CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2079 #, c-format msgid "Lazy superblock counted always enabled for CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2086 #, c-format msgid "V2 logs always enabled for CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2093 #, c-format msgid "V2 attribute format always enabled on CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2101 #, c-format msgid "32 bit Project IDs always enabled on CRC enabled filesytems\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2116 #, c-format msgid "finobt not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2123 #, c-format msgid "sparse inodes not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2130 #, c-format msgid "rmapbt not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2137 #, c-format msgid "reflink not supported without CRC support\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2146 #, c-format msgid "rmapbt not supported with realtime devices\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2154 #, c-format msgid "illegal directory block size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2173 #, c-format msgid "illegal data length %lld, not a multiple of %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2179 #, c-format msgid "warning: data length %lld not a multiple of %d, truncated to %lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2205 #, c-format msgid "illegal log length %lld, not a multiple of %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2212 #, c-format msgid "warning: log length %lld not a multiple of %d, truncated to %lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2222 #, c-format msgid "illegal rt length %lld, not a multiple of %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2229 #, c-format msgid "warning: rt length %lld not a multiple of %d, truncated to %lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2242 #, c-format msgid "illegal rt extent size %lld, not a multiple of %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2285 #, c-format msgid "illegal inode size %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2290 #, c-format msgid "allowable inode size with %d byte blocks is %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2294 #, c-format msgid "allowable inode size with %d byte blocks is between %d and %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2302 #, c-format msgid "log stripe unit specified, using v2 logs\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2317 #, c-format msgid "no device name given in argument list\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2353 msgid "internal log" msgstr "" #: .././mkfs/xfs_mkfs.c:2355 msgid "volume log" msgstr "" #: .././mkfs/xfs_mkfs.c:2357 #, c-format msgid "no log subvolume or internal log\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2364 msgid "volume rt" msgstr "" #: .././mkfs/xfs_mkfs.c:2369 #, c-format msgid "" "size %s specified for data subvolume is too large, maximum is %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2376 #, c-format msgid "can't get size of data subvolume\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2381 #, c-format msgid "size %lld of data subvolume is too small, minimum %d blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2388 #, c-format msgid "can't have both external and internal logs\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2392 #, c-format msgid "data and log sector sizes must be equal for internal logs\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2398 #, c-format msgid "" "Warning: the data subvolume sector size %u is less than the sector size \n" "reported by the device (%u).\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2404 #, c-format msgid "" "Warning: the log subvolume sector size %u is less than the sector size\n" "reported by the device (%u).\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2410 #, c-format msgid "" "Warning: the realtime subvolume sector size %u is less than the sector size\n" "reported by the device (%u).\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2417 #, c-format msgid "" "size %s specified for rt subvolume is too large, maximum is %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2425 #, c-format msgid "size specified for non-existent rt subvolume\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2440 #, c-format msgid "" "%s: Specified data stripe unit %d is not the same as the volume stripe unit " "%d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2447 #, c-format msgid "" "%s: Specified data stripe width %d is not the same as the volume stripe " "width %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2465 #, c-format msgid "agsize (%lld) not a multiple of fs blk size (%d)\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2515 #, c-format msgid "agsize rounded to %lld, swidth = %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2547 #, c-format msgid "" "Warning: AG size is a multiple of stripe width. This can cause performance\n" "problems by aligning all AGs on the same disk. To avoid this, run mkfs " "with\n" "an AG size that is one stripe unit smaller, for example %llu.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2572 #, c-format msgid "" "%s: Stripe unit(%d) or stripe width(%d) is not a multiple of the block size" "(%d)\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2613 #, c-format msgid "log stripe unit (%d bytes) is too large (maximum is 256KiB)\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2616 #, c-format msgid "log stripe unit adjusted to 32KiB\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2632 #, c-format msgid "" "size %s specified for log subvolume is too large, maximum is %lld blocks\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2639 #, c-format msgid "size specified for non-existent log subvolume\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2642 #, c-format msgid "size %lld too large for internal log\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2720 #, c-format msgid "internal log size %lld too large, must fit in allocation group\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2728 #, c-format msgid "log ag number %d too large, must be less than %lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2758 #, c-format msgid "" "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2876 #, c-format msgid "%s: Growing the data section failed\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2906 #, c-format msgid "%s: filesystem failed to initialize\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3319 #, c-format msgid "%s: root inode created in AG %u, not AG 0\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3385 #, c-format msgid "Cannot specify both -%c %s and -%c %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3396 #, c-format msgid "Illegal value %s for -%s option\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3413 #, c-format msgid "-%c %s option requires a value\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3426 .././repair/xfs_repair.c:168 #, c-format msgid "option respecified\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3435 .././repair/xfs_repair.c:175 #, c-format msgid "unknown option -%c %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3461 #, c-format msgid "Blocksize must be provided prior to using 'b' suffix.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3470 #, c-format msgid "Sectorsize must be specified prior to using 's' suffix.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3505 #, c-format msgid "" "Usage: %s\n" "/* blocksize */\t\t[-b log=n|size=num]\n" "/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n" "/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num|noalign),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* force overwrite */\t[-f]\n" "/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n" "\t\t\t projid32bit=0|1,sparse=0|1]\n" "/* no discard */\t[-K]\n" "/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* label */\t\t[-L label (maximum 12 characters)]\n" "/* naming */\t\t[-n log=n|size=num,version=2|ci,ftype=0|1]\n" "/* no-op info only */\t[-N]\n" "/* prototype file */\t[-p fname]\n" "/* quiet */\t\t[-q]\n" "/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* sectorsize */\t[-s log=n|size=num]\n" "/* version */\t\t[-V]\n" "\t\t\tdevicename\n" " is required unless -d name=xxx is given.\n" " is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " is xxx (512 byte blocks).\n" msgstr "" #: .././quota/edit.c:36 #, c-format msgid "" "\n" " modify quota limits for the specified user\n" "\n" " Example:\n" " 'limit bsoft=100m bhard=110m tanya\n" "\n" " Changes the soft and/or hard block limits, inode limits and/or realtime\n" " block limits that are currently being used for the specified user, group,\n" " or project. The filesystem identified by the current path is modified.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota limits\n" " -p -- modify project quota limits\n" " -u -- modify user quota limits\n" " The block limit values can be specified with a units suffix - accepted\n" " units are: k (kilobytes), m (megabytes), g (gigabytes), and t (terabytes).\n" " The user/group/project can be specified either by name or by number.\n" "\n" msgstr "" #: .././quota/edit.c:59 #, c-format msgid "" "\n" " modify quota enforcement timeout for the current filesystem\n" "\n" " Example:\n" " 'timer -i 3days'\n" " (soft inode limit timer is changed to 3 days)\n" "\n" " Changes the timeout value associated with the block limits, inode limits\n" " and/or realtime block limits for all users, groups, or projects on the\n" " current filesystem.\n" " As soon as a user consumes the amount of space or number of inodes set as\n" " the soft limit, a timer is started. If the timer expires and the user is\n" " still over the soft limit, the soft limit is enforced as the hard limit.\n" " The default timeout is 7 days.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota timer\n" " -p -- modify project quota timer\n" " -u -- modify user quota timer\n" " -b -- modify the blocks-used timer\n" " -i -- modify the inodes-used timer\n" " -r -- modify the blocks-used timer for the (optional) realtime subvolume\n" " The timeout value is specified as a number of seconds, by default.\n" " However, a suffix may be used to alternatively specify minutes (m),\n" " hours (h), days (d), or weeks (w) - either the full word or the first\n" " letter of the word can be used.\n" "\n" msgstr "" #: .././quota/edit.c:91 #, c-format msgid "" "\n" " modify the number of quota warnings sent to the specified user\n" "\n" " Example:\n" " 'warn 2 jimmy'\n" " (tell the quota system that two warnings have been sent to user jimmy)\n" "\n" " Changes the warning count associated with the block limits, inode limits\n" " and/or realtime block limits for the specified user, group, or project.\n" " When a user has been warned the maximum number of times allowed, the soft\n" " limit is enforced as the hard limit. It is intended as an alternative to\n" " the timeout system, where the system administrator updates a count of the\n" " number of warnings issued to people, and they are penalised if the " "warnings\n" " are ignored.\n" " -d -- set maximum warning count, which triggers soft limit enforcement\n" " -g -- set group quota warning count\n" " -p -- set project quota warning count\n" " -u -- set user quota warning count\n" " -b -- set the blocks-used warning count\n" " -i -- set the inodes-used warning count\n" " -r -- set the blocks-used warn count for the (optional) realtime subvolume\n" " The user/group/project can be specified either by name or by number.\n" "\n" msgstr "" #: .././quota/edit.c:145 #, c-format msgid "%s: cannot set limits: %s\n" msgstr "" #: .././quota/edit.c:166 .././quota/edit.c:584 #, c-format msgid "%s: invalid user name: %s\n" msgstr "" #: .././quota/edit.c:189 .././quota/edit.c:601 #, c-format msgid "%s: invalid group name: %s\n" msgstr "" #: .././quota/edit.c:212 .././quota/edit.c:618 #, c-format msgid "%s: invalid project name: %s\n" msgstr "" #: .././quota/edit.c:237 #, c-format msgid "%s: Error: could not parse size %s.\n" msgstr "" #: .././quota/edit.c:243 #, c-format msgid "%s: Warning: `%s' in quota blocks is 0 (unlimited).\n" msgstr "" #: .././quota/edit.c:332 #, c-format msgid "%s: unrecognised argument %s\n" msgstr "" #: .././quota/edit.c:339 #, c-format msgid "%s: cannot find any valid arguments\n" msgstr "" #: .././quota/edit.c:457 #, c-format msgid "%s: fopen on %s failed: %s\n" msgstr "" #: .././quota/edit.c:489 #, c-format msgid "%s: cannot set timer: %s\n" msgstr "" #: .././quota/edit.c:568 #, c-format msgid "%s: cannot set warnings: %s\n" msgstr "" #: .././quota/edit.c:709 msgid "[-g|-p|-u] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" msgstr "" #: .././quota/edit.c:710 msgid "modify quota limits" msgstr "" #: .././quota/edit.c:718 .././quota/report.c:33 .././quota/report.c:768 msgid "[-g|-p|-u] [-f file]" msgstr "" #: .././quota/edit.c:719 msgid "restore quota limits from a backup file" msgstr "" #: .././quota/edit.c:726 msgid "[-bir] [-g|-p|-u] value" msgstr "" #: .././quota/edit.c:727 msgid "set quota enforcement timeouts" msgstr "" #: .././quota/edit.c:735 msgid "[-bir] [-g|-p|-u] value -d|id|name" msgstr "" #: .././quota/edit.c:736 msgid "get/set enforcement warning counter" msgstr "" #: .././quota/free.c:30 #, c-format msgid "" "\n" " reports the number of free disk blocks and inodes\n" "\n" " This command reports the number of total, used, and available disk blocks.\n" " It can optionally report the same set of numbers for inodes and realtime\n" " disk blocks, and will report on all known XFS filesystem mount points and\n" " project quota paths by default (see 'print' command for a list).\n" " -b -- report the block count values\n" " -i -- report the inode count values\n" " -r -- report the realtime block count values\n" " -h -- report in a human-readable format\n" " -N -- suppress the header from the output\n" "\n" msgstr "" #: .././quota/free.c:171 #, c-format msgid "%s: project quota flag not set on %s\n" msgstr "" #: .././quota/free.c:180 #, c-format msgid "%s: project ID %u (%s) doesn't match ID %u (%s)\n" msgstr "" #: .././quota/free.c:247 #, c-format msgid "Filesystem " msgstr "" #: .././quota/free.c:247 #, c-format msgid "Filesystem " msgstr "" #: .././quota/free.c:250 #, c-format msgid " Size Used Avail Use%%" msgstr "" #: .././quota/free.c:251 #, c-format msgid " 1K-blocks Used Available Use%%" msgstr "" #: .././quota/free.c:254 #, c-format msgid " Inodes Used Free Use%%" msgstr "" #: .././quota/free.c:255 #, c-format msgid " Inodes IUsed IFree IUse%%" msgstr "" #: .././quota/free.c:256 #, c-format msgid " Pathname\n" msgstr "" #: .././quota/free.c:388 msgid "[-bir] [-hN] [-f file]" msgstr "" #: .././quota/free.c:389 msgid "show free and used counts for blocks and inodes" msgstr "" #: .././quota/init.c:49 #, c-format msgid "Usage: %s [-V] [-x] [-f] [-p prog] [-c cmd]... [-d project]... [path]\n" msgstr "" #: .././quota/init.c:130 #, c-format msgid "%s: command is for XFS filesystems only\n" msgstr "" #: .././quota/init.c:137 #, c-format msgid "%s: foreign filesystem. Invoke xfs_quota with -f to enable.\n" msgstr "" #: .././quota/path.c:39 #, c-format msgid "%s%sFilesystem Pathname\n" msgstr "" #: .././quota/path.c:40 msgid " " msgstr "" #: .././quota/path.c:41 msgid " " msgstr "" #: .././quota/path.c:44 #, c-format msgid "%c%03d%c " msgstr "" #: .././quota/path.c:47 #, c-format msgid "%-19s %s" msgstr "" #: .././quota/path.c:50 #, c-format msgid " (project %u" msgstr "" #: .././quota/path.c:52 #, c-format msgid ", %s" msgstr "" #: .././quota/path.c:117 #, c-format msgid "No paths are available\n" msgstr "" #: .././quota/path.c:145 msgid "set current path, or show the list of paths" msgstr "" #: .././quota/path.c:153 msgid "list known mount points and projects" msgstr "" #: .././quota/project.c:45 #, c-format msgid "" "\n" " list projects or setup a project tree for tree quota management\n" "\n" " Example:\n" " 'project -c logfiles'\n" " (match project 'logfiles' to a directory, and setup the directory tree)\n" "\n" " Without arguments, report all projects found in the /etc/projects file.\n" " The project quota mechanism in XFS can be used to implement a form of\n" " directory tree quota, where a specified directory and all of the files\n" " and subdirectories below it (i.e. a tree) can be restricted to using a\n" " subset of the available space in the filesystem.\n" "\n" " A managed tree must be setup initially using the -c option with a project.\n" " The specified project name or identifier is matched to one or more trees\n" " defined in /etc/projects, and these trees are then recursively descended\n" " to mark the affected inodes as being part of that tree - which sets inode\n" " flags and the project identifier on every file.\n" " Once this has been done, new files created in the tree will automatically\n" " be accounted to the tree based on their project identifier. An attempt to\n" " create a hard link to a file in the tree will only succeed if the project\n" " identifier matches the project identifier for the tree. The xfs_io " "utility\n" " can be used to set the project ID for an arbitrary file, but this can only\n" " be done by a privileged user.\n" "\n" " A previously setup tree can be cleared from project quota control through\n" " use of the -C option, which will recursively descend the tree, clearing\n" " the affected inodes from project quota control.\n" "\n" " The -c option can be used to check whether a tree is setup, it reports\n" " nothing if the tree is correct, otherwise it reports the paths of inodes\n" " which do not have the project ID of the rest of the tree, or if the inode\n" " flag is not set.\n" "\n" " The -p option can be used to manually specify project path without\n" " need to create /etc/projects file. This option can be used multiple times\n" " to specify multiple paths. When using this option only one projid/name can\n" " be specified at command line. Note that /etc/projects is also used if " "exists.\n" "\n" " The -d option allows to descend at most levels of " "directories\n" " below the command line arguments. -d 0 means only apply the actions\n" " to the top level of the projects. -d -1 means no recursion limit " "(default).\n" "\n" " The /etc/projid and /etc/projects file formats are simple, and described\n" " on the xfs_quota man page.\n" "\n" msgstr "" #: .././quota/project.c:108 .././quota/project.c:153 .././quota/project.c:200 #, c-format msgid "%s: cannot stat file %s\n" msgstr "" #: .././quota/project.c:112 .././quota/project.c:157 .././quota/project.c:204 #, c-format msgid "%s: skipping special file %s\n" msgstr "" #: .././quota/project.c:126 #, c-format msgid "%s - project identifier is not set (inode=%u, tree=%u)\n" msgstr "" #: .././quota/project.c:130 #, c-format msgid "%s - project inheritance flag is not set\n" msgstr "" #: .././quota/project.c:178 #, c-format msgid "%s: cannot clear project on %s: %s\n" msgstr "" #: .././quota/project.c:225 #, c-format msgid "%s: cannot set project on %s: %s\n" msgstr "" #: .././quota/project.c:240 #, c-format msgid "Checking project %s (path %s)...\n" msgstr "" #: .././quota/project.c:244 #, c-format msgid "Setting up project %s (path %s)...\n" msgstr "" #: .././quota/project.c:248 #, c-format msgid "Clearing project %s (path %s)...\n" msgstr "" #: .././quota/project.c:271 #, c-format msgid "" "Processed %d (%s and cmdline) paths for project %s with recursion depth %s " "(%d).\n" msgstr "" #: .././quota/project.c:274 msgid "infinite" msgstr "" #: .././quota/project.c:274 msgid "limited" msgstr "" #: .././quota/project.c:319 #, c-format msgid "projects file \"%s\" doesn't exist\n" msgstr "" #: .././quota/project.c:326 #, c-format msgid "" "%s: only one projid/name can be specified when using -p , %d found.\n" msgstr "" #: .././quota/project.c:336 #, c-format msgid "%s - no such project in %s or invalid project number\n" msgstr "" #: .././quota/project.c:353 msgid "[-c|-s|-C|-d |-p ] project ..." msgstr "" #: .././quota/project.c:356 msgid "check, setup or clear project quota trees" msgstr "" #: .././quota/quot.c:56 #, c-format msgid "" "\n" " display a summary of filesystem ownership\n" "\n" " -a -- summarise for all local XFS filesystem mount points\n" " -c -- display three columns giving file size in kilobytes, number of files\n" " of that size, and cumulative total of kilobytes in that size or\n" " smaller file. The last row is used as an overflow bucket and is the\n" " total of all files greater than 500 kilobytes.\n" " -v -- display three columns containing the number of kilobytes not\n" " accessed in the last 30, 60, and 90 days.\n" " -g -- display group summary\n" " -p -- display project summary\n" " -u -- display user summary\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n" msgstr "" #: .././quota/quot.c:221 #, c-format msgid "%s (%s) %s:\n" msgstr "" #: .././quota/quot.c:297 #, c-format msgid "%s (%s):\n" msgstr "" #: .././quota/quot.c:302 .././quota/quot.c:306 #, c-format msgid "%d\t%llu\t%llu\n" msgstr "" #: .././quota/quot.c:425 msgid "[-bir] [-g|-p|-u] [-acv] [-f file]" msgstr "" #: .././quota/quot.c:426 msgid "summarize filesystem ownership" msgstr "" #: .././quota/quota.c:33 #, c-format msgid "" "\n" " display usage and quota information\n" "\n" " -g -- display group quota information\n" " -p -- display project quota information\n" " -u -- display user quota information\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -v -- increase verbosity in reporting (also dumps zero values)\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n" msgstr "" #: .././quota/quota.c:86 #, c-format msgid "" "Disk quotas for %s %s (%u)\n" "Filesystem%s" msgstr "" #: .././quota/quota.c:91 #, c-format msgid " Blocks Quota Limit Warn/Time " msgstr "" #: .././quota/quota.c:92 #, c-format msgid " Blocks Quota Limit Warn/Time " msgstr "" #: .././quota/quota.c:95 #, c-format msgid " Files Quota Limit Warn/Time " msgstr "" #: .././quota/quota.c:96 #, c-format msgid " Files Quota Limit Warn/Time " msgstr "" #: .././quota/quota.c:99 #, c-format msgid "Realtime Quota Limit Warn/Time " msgstr "" #: .././quota/quota.c:100 #, c-format msgid " Realtime Quota Limit Warn/Time " msgstr "" #: .././quota/quota.c:236 #, c-format msgid "%s: cannot find user %s\n" msgstr "" #: .././quota/quota.c:286 #, c-format msgid "%s: cannot find group %s\n" msgstr "" #: .././quota/quota.c:347 #, c-format msgid "%s: must specify a project name/ID\n" msgstr "" #: .././quota/quota.c:360 #, c-format msgid "%s: cannot find project %s\n" msgstr "" #: .././quota/quota.c:470 msgid "[-bir] [-g|-p|-u] [-hnNv] [-f file] [id|name]..." msgstr "" #: .././quota/quota.c:471 msgid "show usage and limits" msgstr "" #: .././quota/report.c:34 .././quota/report.c:769 msgid "dump quota information for backup utilities" msgstr "" #: .././quota/report.c:36 #, c-format msgid "" "\n" " create a backup file which contains quota limits information\n" " -g -- dump out group quota limits\n" " -p -- dump out project quota limits\n" " -u -- dump out user quota limits (default)\n" " -f -- write the dump out to the specified file\n" "\n" msgstr "" #: .././quota/report.c:48 msgid "[-bir] [-gpu] [-ahntlLNU] [-f file]" msgstr "" #: .././quota/report.c:49 .././quota/report.c:779 msgid "report filesystem quota information" msgstr "" #: .././quota/report.c:51 #, c-format msgid "" "\n" " report used space and inodes, and quota limits, for a filesystem\n" " Example:\n" " 'report -igh'\n" " (reports inode usage for all groups, in an easy-to-read format)\n" " This command is the equivalent of the traditional repquota command, which\n" " prints a summary of the disk usage and quotas for the current filesystem,\n" " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -L -- lower ID bound to report on\n" " -U -- upper ID bound to report on\n" " -l -- look up names for IDs in lower-upper range\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" " -u -- report user usage and quota information\n" " -b -- report blocks-used information only\n" " -i -- report inodes-used information only\n" " -r -- report realtime-blocks-used information only\n" "\n" msgstr "" #: .././quota/report.c:273 #, c-format msgid "%s quota on %s (%s)\n" msgstr "" #: .././quota/report.c:298 .././quota/report.c:306 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr "" #: .././quota/report.c:299 .././quota/report.c:307 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr "" #: .././quota/report.c:302 #, c-format msgid " Used Soft Hard Warn/Grace " msgstr "" #: .././quota/report.c:303 #, c-format msgid " Used Soft Hard Warn/ Grace " msgstr "" #: .././quota/report.c:778 msgid "[-bir] [-gpu] [-ahnt] [-f file]" msgstr "" #: .././quota/state.c:33 #, c-format msgid "" "\n" " turn filesystem quota off, both accounting and enforcement\n" "\n" " Example:\n" " 'off -uv' (switch off user quota on the current filesystem)\n" " This command is the equivalent of the traditional quotaoff command,\n" " which disables quota completely on a mounted filesystem.\n" " Note that there is no 'on' command - for XFS filesystems (with the\n" " exception of the root filesystem on IRIX) quota can only be enabled\n" " at mount time, through the use of one of the quota mount options.\n" "\n" " The state command is useful for displaying the current state. Using\n" " the -v (verbose) option with the 'off' command will display the quota\n" " state for the affected filesystem once the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" #: .././quota/state.c:56 #, c-format msgid "" "\n" " query the state of quota on the current filesystem\n" "\n" " This is a verbose status command, reporting whether or not accounting\n" " and/or enforcement are enabled for a filesystem, which inodes are in\n" " use as the quota state inodes, and how many extents and blocks are\n" " presently being used to hold that information.\n" " The quota type is specified via -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" #: .././quota/state.c:72 #, c-format msgid "" "\n" " enable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and has quota accounting enabled, but not\n" " quota enforcement, enforcement can be enabled with this command.\n" " With the -v (verbose) option, the status of the filesystem will be\n" " reported after the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" #: .././quota/state.c:88 #, c-format msgid "" "\n" " disable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and is currently enforcing quota, this\n" " provides a mechanism to switch off the enforcement, but continue to\n" " perform used space (and used inodes) accounting.\n" " The affected quota type is -g (groups), -p (projects) or -u (users).\n" "\n" msgstr "" #: .././quota/state.c:102 #, c-format msgid "" "\n" " remove any space being used by the quota subsystem\n" "\n" " Once quota has been switched 'off' on a filesystem, the space that\n" " was allocated to holding quota metadata can be freed via this command.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n" msgstr "" #: .././quota/state.c:121 #, c-format msgid "%s quota state on %s (%s)\n" msgstr "" #: .././quota/state.c:123 #, c-format msgid " Accounting: %s\n" msgstr "" #: .././quota/state.c:123 .././quota/state.c:124 msgid "ON" msgstr "" #: .././quota/state.c:123 .././quota/state.c:124 msgid "OFF" msgstr "" #: .././quota/state.c:124 #, c-format msgid " Enforcement: %s\n" msgstr "" #: .././quota/state.c:126 #, c-format msgid " Inode: #%llu (%llu blocks, %lu extents)\n" msgstr "" #: .././quota/state.c:131 #, c-format msgid " Inode: N/A\n" msgstr "" #: .././quota/state.c:140 #, c-format msgid "%s grace time: %s\n" msgstr "" #: .././quota/state.c:212 #, c-format msgid "%s quota are not enabled on %s\n" msgstr "" #: .././quota/state.c:584 .././quota/state.c:601 .././quota/state.c:609 #: .././quota/state.c:617 msgid "[-gpu] [-v]" msgstr "" #: .././quota/state.c:585 msgid "permanently switch quota off for a path" msgstr "" #: .././quota/state.c:592 msgid "[-gpu] [-a] [-v] [-f file]" msgstr "" #: .././quota/state.c:593 msgid "get overall quota state information" msgstr "" #: .././quota/state.c:602 msgid "enable quota enforcement" msgstr "" #: .././quota/state.c:610 msgid "disable quota enforcement" msgstr "" #: .././quota/state.c:618 msgid "remove quota extents from a filesystem" msgstr "" #: .././quota/util.c:70 #, c-format msgid "[-none-]" msgstr "" #: .././quota/util.c:70 #, c-format msgid "[--none--]" msgstr "" #: .././quota/util.c:73 #, c-format msgid "[------]" msgstr "" #: .././quota/util.c:73 #, c-format msgid "[--------]" msgstr "" #: .././quota/util.c:77 .././quota/util.c:80 msgid "day" msgstr "" #: .././quota/util.c:77 .././quota/util.c:80 msgid "days" msgstr "" #: .././quota/util.c:205 msgid "Blocks" msgstr "" #: .././quota/util.c:205 msgid "Inodes" msgstr "" #: .././quota/util.c:205 msgid "Realtime Blocks" msgstr "" #: .././quota/util.c:220 msgid "User" msgstr "" #: .././quota/util.c:220 msgid "Group" msgstr "" #: .././quota/util.c:220 msgid "Project" msgstr "" #: .././quota/util.c:428 #, c-format msgid "%s: open on %s failed: %s\n" msgstr "" #: .././quota/util.c:434 #, c-format msgid "%s: fdopen on %s failed: %s\n" msgstr "" #: .././repair/agheader.c:40 #, c-format msgid "bad magic # 0x%x for agf %d\n" msgstr "" #: .././repair/agheader.c:49 #, c-format msgid "bad version # %d for agf %d\n" msgstr "" #: .././repair/agheader.c:58 #, c-format msgid "bad sequence # %d for agf %d\n" msgstr "" #: .././repair/agheader.c:68 #, c-format msgid "bad length %d for agf %d, should be %d\n" msgstr "" #: .././repair/agheader.c:81 #, c-format msgid "bad length %d for agf %d, should be %\n" msgstr "" #: .././repair/agheader.c:95 #, c-format msgid "flfirst %d in agf %d too large (max = %zu)\n" msgstr "" #: .././repair/agheader.c:103 #, c-format msgid "fllast %d in agf %d too large (max = %zu)\n" msgstr "" #: .././repair/agheader.c:120 #, c-format msgid "bad uuid %s for agf %d\n" msgstr "" #: .././repair/agheader.c:139 #, c-format msgid "bad magic # 0x%x for agi %d\n" msgstr "" #: .././repair/agheader.c:148 #, c-format msgid "bad version # %d for agi %d\n" msgstr "" #: .././repair/agheader.c:157 #, c-format msgid "bad sequence # %d for agi %d\n" msgstr "" #: .././repair/agheader.c:167 #, c-format msgid "bad length # %d for agi %d, should be %d\n" msgstr "" #: .././repair/agheader.c:180 #, c-format msgid "bad length # %d for agi %d, should be %\n" msgstr "" #: .././repair/agheader.c:199 #, c-format msgid "bad uuid %s for agi %d\n" msgstr "" #: .././repair/agheader.c:305 #, c-format msgid "zeroing unused portion of %s superblock (AG #%u)\n" msgstr "" #: .././repair/agheader.c:306 .././repair/agheader.c:324 msgid "primary" msgstr "" #: .././repair/agheader.c:306 .././repair/agheader.c:324 msgid "secondary" msgstr "" #: .././repair/agheader.c:323 #, c-format msgid "would zero unused portion of %s superblock (AG #%u)\n" msgstr "" #: .././repair/agheader.c:341 #, c-format msgid "bad flags field in superblock %d\n" msgstr "" #: .././repair/agheader.c:364 #, c-format msgid "non-null user quota inode field in superblock %d\n" msgstr "" #: .././repair/agheader.c:379 #, c-format msgid "non-null group quota inode field in superblock %d\n" msgstr "" #: .././repair/agheader.c:400 #, c-format msgid "non-null project quota inode field in superblock %d\n" msgstr "" #: .././repair/agheader.c:412 #, c-format msgid "non-null quota flags in superblock %d\n" msgstr "" #: .././repair/agheader.c:430 #, c-format msgid "bad inode alignment field in superblock %d\n" msgstr "" #: .././repair/agheader.c:443 #, c-format msgid "bad stripe unit/width fields in superblock %d\n" msgstr "" #: .././repair/agheader.c:461 #, c-format msgid "bad log/data device sector size fields in superblock %d\n" msgstr "" #: .././repair/agheader.c:492 #, c-format msgid "bad on-disk superblock %d - %s\n" msgstr "" #: .././repair/agheader.c:499 #, c-format msgid "primary/secondary superblock %d conflict - %s\n" msgstr "" #: .././repair/attr_repair.c:70 #, c-format msgid "bad range claimed [%d, %d) in da block\n" msgstr "" #: .././repair/attr_repair.c:77 #, c-format msgid "byte range end [%d %d) in da block larger than blocksize %d\n" msgstr "" #: .././repair/attr_repair.c:84 #, c-format msgid "multiply claimed byte %d in da block\n" msgstr "" #: .././repair/attr_repair.c:164 msgid "No memory for ACL check!\n" msgstr "" #: .././repair/attr_repair.c:172 msgid "" "entry contains illegal value in attribute named SGI_ACL_FILE or " "SGI_ACL_DEFAULT\n" msgstr "" #: .././repair/attr_repair.c:198 msgid "entry contains illegal value in attribute named SGI_MAC_LABEL\n" msgstr "" #: .././repair/attr_repair.c:204 msgid "entry contains illegal value in attribute named SGI_CAP_FILE\n" msgstr "" #: .././repair/attr_repair.c:244 #, c-format msgid "there are no attributes in the fork for inode %\n" msgstr "" #: .././repair/attr_repair.c:252 #, c-format msgid "would junk the attribute fork since count is 0 for inode %\n" msgstr "" #: .././repair/attr_repair.c:272 msgid "zero length name entry in attribute fork," msgstr "" #: .././repair/attr_repair.c:275 .././repair/attr_repair.c:295 #, c-format msgid " truncating attributes for inode % to %d\n" msgstr "" #: .././repair/attr_repair.c:280 .././repair/attr_repair.c:301 #, c-format msgid " would truncate attributes for inode % to %d\n" msgstr "" #: .././repair/attr_repair.c:292 msgid "name or value attribute lengths are too large,\n" msgstr "" #: .././repair/attr_repair.c:314 msgid "entry contains illegal character in shortform attribute name\n" msgstr "" #: .././repair/attr_repair.c:320 msgid "entry has INCOMPLETE flag on in shortform attribute\n" msgstr "" #: .././repair/attr_repair.c:338 #, c-format msgid "removing attribute entry %d for inode %\n" msgstr "" #: .././repair/attr_repair.c:350 #, c-format msgid "would remove attribute entry %d for inode %\n" msgstr "" #: .././repair/attr_repair.c:365 #, c-format msgid "" "would have corrected attribute entry count in inode % from %d to %d\n" msgstr "" #: .././repair/attr_repair.c:369 #, c-format msgid "corrected attribute entry count in inode %, was %d, now %d\n" msgstr "" #: .././repair/attr_repair.c:380 #, c-format msgid "" "would have corrected attribute totsize in inode % from %d to %d\n" msgstr "" #: .././repair/attr_repair.c:385 #, c-format msgid "corrected attribute entry totsize in inode %, was %d, now %d\n" msgstr "" #: .././repair/attr_repair.c:419 #, c-format msgid "remote block for attributes of inode % is missing\n" msgstr "" #: .././repair/attr_repair.c:428 #, c-format msgid "can't read remote block for attributes of inode %\n" msgstr "" #: .././repair/attr_repair.c:435 #, c-format msgid "Corrupt remote block for attributes of inode %\n" msgstr "" #: .././repair/attr_repair.c:476 #, c-format msgid "" "attribute entry %d in attr block %u, inode % has bad name (namelen = " "%d)\n" msgstr "" #: .././repair/attr_repair.c:493 #, c-format msgid "" "bad hashvalue for attribute entry %d in attr block %u, inode %\n" msgstr "" #: .././repair/attr_repair.c:503 #, c-format msgid "" "bad security value for attribute entry %d in attr block %u, inode %\n" msgstr "" #: .././repair/attr_repair.c:536 #, c-format msgid "" "inconsistent remote attribute entry %d in attr block %u, ino %\n" msgstr "" #: .././repair/attr_repair.c:546 #, c-format msgid "cannot malloc enough for remotevalue attribute for inode %\n" msgstr "" #: .././repair/attr_repair.c:548 msgid "SKIPPING this remote attribute\n" msgstr "" #: .././repair/attr_repair.c:554 #, c-format msgid "remote attribute get failed for entry %d, inode %\n" msgstr "" #: .././repair/attr_repair.c:561 #, c-format msgid "remote attribute value check failed for entry %d, inode %\n" msgstr "" #: .././repair/attr_repair.c:600 #, c-format msgid "bad attribute count %d in attr block %u, inode %\n" msgstr "" #: .././repair/attr_repair.c:615 #, c-format msgid "bad attribute nameidx %d in attr block %u, inode %\n" msgstr "" #: .././repair/attr_repair.c:624 #, c-format msgid "attribute entry #%d in attr block %u, inode % is INCOMPLETE\n" msgstr "" #: .././repair/attr_repair.c:635 #, c-format msgid "" "attribute entry %d in attr block %u, inode % claims already used " "space\n" msgstr "" #: .././repair/attr_repair.c:658 #, c-format msgid "" "attribute entry %d in attr block %u, inode % claims used space\n" msgstr "" #: .././repair/attr_repair.c:682 #, c-format msgid "" "- resetting first used heap value from %d to %d in block %u of attribute " "fork of inode %\n" msgstr "" #: .././repair/attr_repair.c:690 #, c-format msgid "" "- would reset first used value from %d to %d in block %u of attribute fork " "of inode %\n" msgstr "" #: .././repair/attr_repair.c:700 #, c-format msgid "" "- resetting usedbytes cnt from %d to %d in block %u of attribute fork of " "inode %\n" msgstr "" #: .././repair/attr_repair.c:708 #, c-format msgid "" "- would reset usedbytes cnt from %d to %d in block %u of attribute fork of " "%\n" msgstr "" #: .././repair/attr_repair.c:770 #, c-format msgid "can't map block %u for attribute fork for inode %\n" msgstr "" #: .././repair/attr_repair.c:780 #, c-format msgid "" "can't read file block %u (fsbno %) for attribute fork of inode " "%\n" msgstr "" #: .././repair/attr_repair.c:792 #, c-format msgid "bad attribute leaf magic %#x for inode %\n" msgstr "" #: .././repair/attr_repair.c:823 #, c-format msgid "" "bad sibling back pointer for block %u in attribute fork for inode %\n" msgstr "" #: .././repair/attr_repair.c:858 #, c-format msgid "bad hash path in attribute fork for inode %\n" msgstr "" #: .././repair/attr_repair.c:940 #, c-format msgid "expected owner inode %, got %llu, attr block %\n" msgstr "" #: .././repair/attr_repair.c:947 #, c-format msgid "expected block %, got %llu, inode %attr block\n" msgstr "" #: .././repair/attr_repair.c:954 #, c-format msgid "wrong FS UUID, inode % attr block %\n" msgstr "" #: .././repair/attr_repair.c:996 #, c-format msgid "block 0 of inode % attribute fork is missing\n" msgstr "" #: .././repair/attr_repair.c:1003 #, c-format msgid "agno of attribute fork of inode % out of regular partition\n" msgstr "" #: .././repair/attr_repair.c:1011 #, c-format msgid "can't read block 0 of inode % attribute fork\n" msgstr "" #: .././repair/attr_repair.c:1035 #, c-format msgid "" "clearing forw/back pointers in block 0 for attributes in inode %\n" msgstr "" #: .././repair/attr_repair.c:1044 #, c-format msgid "" "would clear forw/back pointers in block 0 for attributes in inode %\n" msgstr "" #: .././repair/attr_repair.c:1080 #, c-format msgid "bad attribute leaf magic # %#x for dir ino %\n" msgstr "" #: .././repair/attr_repair.c:1110 #, c-format msgid "Too many ACL entries, count %d\n" msgstr "" #: .././repair/attr_repair.c:1119 msgid "cannot malloc enough for ACL attribute\n" msgstr "" #: .././repair/attr_repair.c:1120 msgid "SKIPPING this ACL\n" msgstr "" #: .././repair/attr_repair.c:1170 .././repair/dinode.c:2065 #, c-format msgid "illegal attribute format %d, ino %\n" msgstr "" #: .././repair/avl.c:1011 .././repair/avl64.c:1032 #, c-format msgid "avl_insert: Warning! duplicate range [%llu,%llu]\n" msgstr "" #: .././repair/avl.c:1206 .././repair/avl64.c:1227 #, c-format msgid "Command [fpdir] : " msgstr "" #: .././repair/avl.c:1215 .././repair/avl64.c:1236 #, c-format msgid "end of range ? " msgstr "" #: .././repair/avl.c:1226 .././repair/avl64.c:1247 #, c-format msgid "Cannot find %d\n" msgstr "" #: .././repair/avl.c:1239 .././repair/avl64.c:1260 #, c-format msgid "size of range ? " msgstr "" #: .././repair/avl.c:1250 .././repair/avl64.c:1271 #, c-format msgid "End of range ? " msgstr "" #: .././repair/avl.c:1254 .././repair/avl64.c:1275 #, c-format msgid "checklen 0/1 ? " msgstr "" #: .././repair/avl.c:1261 .././repair/avl64.c:1282 #, c-format msgid "Found something\n" msgstr "" #: .././repair/bmap.c:53 #, c-format msgid "" "Number of extents requested in blkmap_alloc (%d) overflows 32 bits.\n" "If this is not a corruption, then you will need a 64 bit system\n" "to repair this filesystem.\n" msgstr "" #: .././repair/bmap.c:66 #, c-format msgid "malloc failed in blkmap_alloc (%zu bytes)\n" msgstr "" #: .././repair/bmap.c:189 #, c-format msgid "blkmap_getn malloc failed (% bytes)\n" msgstr "" #: .././repair/bmap.c:296 #, c-format msgid "" "Number of extents requested in blkmap_grow (%d) overflows 32 bits.\n" "You need a 64 bit system to repair this filesystem.\n" msgstr "" #: .././repair/bmap.c:304 #, c-format msgid "" "Number of extents requested in blkmap_grow (%d) overflowed the\n" "maximum number of supported extents (%d).\n" msgstr "" #: .././repair/bmap.c:312 msgid "realloc failed in blkmap_grow\n" msgstr "" #: .././repair/da_util.c:88 .././repair/prefetch.c:238 msgid "couldn't malloc dir2 buffer list\n" msgstr "" #: .././repair/da_util.c:105 msgid "attribute" msgstr "" #: .././repair/da_util.c:164 .././repair/da_util.c:585 #, c-format msgid "can't read %s block %u for inode %\n" msgstr "" #: .././repair/da_util.c:177 #, c-format msgid "found non-root LEAFN node in inode % bno = %u\n" msgstr "" #: .././repair/da_util.c:188 #, c-format msgid "bad %s magic number 0x%x in inode % bno = %u\n" msgstr "" #: .././repair/da_util.c:199 #, c-format msgid "corrupt %s tree block %u for inode %\n" msgstr "" #: .././repair/da_util.c:207 #, c-format msgid "bad %s record count in inode %, count = %d, max = %d\n" msgstr "" #: .././repair/da_util.c:221 #, c-format msgid "bad header depth for directory inode %\n" msgstr "" #: .././repair/da_util.c:232 #, c-format msgid "bad %s btree for inode %\n" msgstr "" #: .././repair/da_util.c:282 #, c-format msgid "release_da_cursor_int got unexpected non-null bp, dabno = %u\n" msgstr "" #: .././repair/da_util.c:360 #, c-format msgid "%s block used/count inconsistency - %d/%hu\n" msgstr "" #: .././repair/da_util.c:370 #, c-format msgid "%s block hashvalue inconsistency, expected > %u / saw %u\n" msgstr "" #: .././repair/da_util.c:378 #, c-format msgid "bad %s forward block pointer, expected 0, saw %u\n" msgstr "" #: .././repair/da_util.c:383 #, c-format msgid "bad %s block in inode %\n" msgstr "" #: .././repair/da_util.c:413 #, c-format msgid "" "correcting bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %.\n" msgstr "" #: .././repair/da_util.c:421 #, c-format msgid "" "would correct bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %.\n" msgstr "" #: .././repair/da_util.c:574 #, c-format msgid "can't get map info for %s block %u of inode %\n" msgstr "" #: .././repair/da_util.c:602 #, c-format msgid "bad magic number %x in %s block %u for inode %\n" msgstr "" #: .././repair/da_util.c:609 #, c-format msgid "bad back pointer in %s block %u for inode %\n" msgstr "" #: .././repair/da_util.c:615 #, c-format msgid "entry count %d too large in %s block %u for inode %\n" msgstr "" #: .././repair/da_util.c:622 #, c-format msgid "bad level %d in %s block %u for inode %\n" msgstr "" #: .././repair/da_util.c:686 #, c-format msgid "" "correcting bad hashval in interior %s block\n" "\tin (level %d) in inode %.\n" msgstr "" #: .././repair/da_util.c:694 #, c-format msgid "" "would correct bad hashval in interior %s block\n" "\tin (level %d) in inode %.\n" msgstr "" #: .././repair/dino_chunks.c:57 #, c-format msgid "cannot read agbno (%u/%u), disk block %\n" msgstr "" #: .././repair/dino_chunks.c:150 #, c-format msgid "uncertain inode block %d/%d already known\n" msgstr "" #: .././repair/dino_chunks.c:166 .././repair/dino_chunks.c:438 #: .././repair/dino_chunks.c:497 #, c-format msgid "inode block %d/%d multiply claimed, (state %d)\n" msgstr "" #: .././repair/dino_chunks.c:173 .././repair/dino_chunks.c:502 #, c-format msgid "inode block %d/%d bad state, (state %d)\n" msgstr "" #: .././repair/dino_chunks.c:445 #, c-format msgid "uncertain inode block overlap, agbno = %d, ino = %\n" msgstr "" #: .././repair/dino_chunks.c:484 #, c-format msgid "uncertain inode block % already known\n" msgstr "" #: .././repair/dino_chunks.c:578 #, c-format msgid "bad state in block map %d\n" msgstr "" #: .././repair/dino_chunks.c:583 #, c-format msgid "inode block % multiply claimed, state was %d\n" msgstr "" #: .././repair/dino_chunks.c:654 #, c-format msgid "failed to allocate %zd bytes of memory\n" msgstr "" #: .././repair/dino_chunks.c:678 #, c-format msgid "cannot read inode %, disk block %, cnt %d\n" msgstr "" #: .././repair/dino_chunks.c:834 #, c-format msgid "imap claims in-use inode % is free, " msgstr "" #: .././repair/dino_chunks.c:839 msgid "correcting imap\n" msgstr "" #: .././repair/dino_chunks.c:841 msgid "would correct imap\n" msgstr "" #: .././repair/dino_chunks.c:896 #, c-format msgid "cleared root inode %\n" msgstr "" #: .././repair/dino_chunks.c:900 #, c-format msgid "would clear root inode %\n" msgstr "" #: .././repair/dino_chunks.c:908 #, c-format msgid "cleared realtime bitmap inode %\n" msgstr "" #: .././repair/dino_chunks.c:912 #, c-format msgid "would clear realtime bitmap inode %\n" msgstr "" #: .././repair/dino_chunks.c:920 #, c-format msgid "cleared realtime summary inode %\n" msgstr "" #: .././repair/dino_chunks.c:924 #, c-format msgid "would clear realtime summary inode %\n" msgstr "" #: .././repair/dino_chunks.c:928 #, c-format msgid "cleared inode %\n" msgstr "" #: .././repair/dino_chunks.c:931 #, c-format msgid "would have cleared inode %\n" msgstr "" #: .././repair/dino_chunks.c:1122 .././repair/dino_chunks.c:1157 #: .././repair/dino_chunks.c:1271 msgid "found inodes not in the inode allocation tree\n" msgstr "" #: .././repair/dinode.c:54 msgid "real-time" msgstr "" #: .././repair/dinode.c:55 msgid "regular" msgstr "" #: .././repair/dinode.c:78 #, c-format msgid "clearing inode % attributes\n" msgstr "" #: .././repair/dinode.c:81 #, c-format msgid "would have cleared inode % attributes\n" msgstr "" #: .././repair/dinode.c:444 #, c-format msgid "" "inode % - bad rt extent start block number %, offset " "%\n" msgstr "" #: .././repair/dinode.c:452 #, c-format msgid "" "inode % - bad rt extent last block number %, offset " "%\n" msgstr "" #: .././repair/dinode.c:460 #, c-format msgid "" "inode % - bad rt extent overflows - start %, end %, " "offset %\n" msgstr "" #: .././repair/dinode.c:477 #, c-format msgid "malformed rt inode extent [% %] (fs rtext size = %u)\n" msgstr "" #: .././repair/dinode.c:498 #, c-format msgid "" "data fork in rt ino % claims dup rt extent,off - %, start - " "%, count %\n" msgstr "" #: .././repair/dinode.c:517 #, c-format msgid "bad state in rt block map %\n" msgstr "" #: .././repair/dinode.c:523 #, c-format msgid "" "data fork in rt inode % found metadata block % in rt bmap\n" msgstr "" #: .././repair/dinode.c:531 #, c-format msgid "data fork in rt inode % claims used rt block %\n" msgstr "" #: .././repair/dinode.c:537 #, c-format msgid "illegal state %d in rt block map %\n" msgstr "" #: .././repair/dinode.c:600 #, c-format msgid "" "bmap rec out of order, inode % entry %d [o s c] [% % " "%], %d [% % %]\n" msgstr "" #: .././repair/dinode.c:616 #, c-format msgid "" "zero length extent (off = %, fsbno = %) in ino %\n" msgstr "" #: .././repair/dinode.c:647 #, c-format msgid "" "inode % - bad extent starting block number %, offset " "%\n" msgstr "" #: .././repair/dinode.c:655 #, c-format msgid "" "inode % - bad extent last block number %, offset %\n" msgstr "" #: .././repair/dinode.c:663 #, c-format msgid "" "inode % - bad extent overflows - start %, end %, " "offset %\n" msgstr "" #: .././repair/dinode.c:675 #, c-format msgid "" "inode % - extent exceeds max offset - start %, count " "%, physical block %\n" msgstr "" #: .././repair/dinode.c:696 #, c-format msgid "" "Fatal error: inode % - blkmap_set_ext(): %s\n" "\t%s fork, off - %, start - %, cnt %\n" msgstr "" #: .././repair/dinode.c:729 #, c-format msgid "" "%s fork in ino % claims dup extent, off - %, start - " "%, cnt %\n" msgstr "" #: .././repair/dinode.c:748 #, c-format msgid "%s fork in ino % claims free block %\n" msgstr "" #: .././repair/dinode.c:757 #, c-format msgid "bad state in block map %\n" msgstr "" #: .././repair/dinode.c:762 msgid "rmap claims metadata use!\n" msgstr "" #: .././repair/dinode.c:768 #, c-format msgid "%s fork in inode % claims metadata block %\n" msgstr "" #: .././repair/dinode.c:779 #, c-format msgid "%s fork in %s inode % claims used block %\n" msgstr "" #: .././repair/dinode.c:785 #, c-format msgid "illegal state %d in block map %\n" msgstr "" #: .././repair/dinode.c:793 msgid "couldn't add reverse mapping\n" msgstr "" #: .././repair/dinode.c:805 #, c-format msgid "correcting nextents for inode %\n" msgstr "" #: .././repair/dinode.c:897 #, c-format msgid "cannot read inode (%u/%u), disk block %\n" msgstr "" #: .././repair/dinode.c:965 #, c-format msgid "bad level %d in inode % bmap btree root block\n" msgstr "" #: .././repair/dinode.c:971 #, c-format msgid "bad numrecs 0 in inode % bmap btree root block\n" msgstr "" #: .././repair/dinode.c:980 #, c-format msgid "" "indicated size of %s btree root (%d bytes) greater than space in inode " "% %s fork\n" msgstr "" #: .././repair/dinode.c:1001 #, c-format msgid "bad bmap btree ptr 0x% in ino %\n" msgstr "" #: .././repair/dinode.c:1021 #, c-format msgid "" "correcting key in bmbt root (was %, now %) in inode " "% %s fork\n" msgstr "" #: .././repair/dinode.c:1033 #, c-format msgid "" "bad key in bmbt root (is %, would reset to %) in inode " "% %s fork\n" msgstr "" #: .././repair/dinode.c:1049 #, c-format msgid "out of order bmbt root key % in inode % %s fork\n" msgstr "" #: .././repair/dinode.c:1066 #, c-format msgid "" "extent count for ino % %s fork too low (%) for file format\n" msgstr "" #: .././repair/dinode.c:1077 #, c-format msgid "bad fwd (right) sibling pointer (saw % should be NULLFSBLOCK)\n" msgstr "" #: .././repair/dinode.c:1080 #, c-format msgid "\tin inode % (%s fork) bmap btree block %\n" msgstr "" #: .././repair/dinode.c:1162 #, c-format msgid "local inode % data fork is too large (size = %lld, max = %d)\n" msgstr "" #: .././repair/dinode.c:1170 #, c-format msgid "local inode % attr fork too large (size %d, max = %d)\n" msgstr "" #: .././repair/dinode.c:1177 #, c-format msgid "local inode % attr too small (size = %d, min size = %zd)\n" msgstr "" #: .././repair/dinode.c:1201 #, c-format msgid "" "mismatch between format (%d) and size (%) in symlink ino %\n" msgstr "" #: .././repair/dinode.c:1208 #, c-format msgid "" "mismatch between format (%d) and size (%) in symlink inode " "%\n" msgstr "" #: .././repair/dinode.c:1223 #, c-format msgid "bad number of extents (%d) in symlink % data fork\n" msgstr "" #: .././repair/dinode.c:1235 #, c-format msgid "bad extent #%d offset (%) in symlink % data fork\n" msgstr "" #: .././repair/dinode.c:1241 #, c-format msgid "bad extent #%d count (%) in symlink % data fork\n" msgstr "" #: .././repair/dinode.c:1299 #, c-format msgid "cannot read inode %, file block %d, NULL disk block\n" msgstr "" #: .././repair/dinode.c:1321 #, c-format msgid "cannot read inode %, file block %d, disk block %\n" msgstr "" #: .././repair/dinode.c:1327 #, c-format msgid "" "Bad symlink buffer CRC, block %, inode %.\n" "Correcting CRC, but symlink may be bad.\n" msgstr "" #: .././repair/dinode.c:1340 #, c-format msgid "bad symlink header ino %, file block %d, disk block %\n" msgstr "" #: .././repair/dinode.c:1383 #, c-format msgid "symlink in inode % too long (%llu chars)\n" msgstr "" #: .././repair/dinode.c:1415 #, c-format msgid "found illegal null character in symlink inode %\n" msgstr "" #: .././repair/dinode.c:1440 #, c-format msgid "inode % has bad inode type (IFMNT)\n" msgstr "" #: .././repair/dinode.c:1451 #, c-format msgid "size of character device inode % != 0 (% bytes)\n" msgstr "" #: .././repair/dinode.c:1456 #, c-format msgid "size of block device inode % != 0 (% bytes)\n" msgstr "" #: .././repair/dinode.c:1461 #, c-format msgid "size of socket inode % != 0 (% bytes)\n" msgstr "" #: .././repair/dinode.c:1466 #, c-format msgid "size of fifo inode % != 0 (% bytes)\n" msgstr "" #: .././repair/dinode.c:1470 #, c-format msgid "Internal error - process_misc_ino_types, illegal type %d\n" msgstr "" #: .././repair/dinode.c:1497 #, c-format msgid "size of character device inode % != 0 (% blocks)\n" msgstr "" #: .././repair/dinode.c:1502 #, c-format msgid "size of block device inode % != 0 (% blocks)\n" msgstr "" #: .././repair/dinode.c:1507 #, c-format msgid "size of socket inode % != 0 (% blocks)\n" msgstr "" #: .././repair/dinode.c:1512 #, c-format msgid "size of fifo inode % != 0 (% blocks)\n" msgstr "" #: .././repair/dinode.c:1590 #, c-format msgid "root inode % has bad type 0x%x\n" msgstr "" #: .././repair/dinode.c:1594 msgid "resetting to directory\n" msgstr "" #: .././repair/dinode.c:1598 msgid "would reset to directory\n" msgstr "" #: .././repair/dinode.c:1604 #, c-format msgid "user quota inode % has bad type 0x%x\n" msgstr "" #: .././repair/dinode.c:1613 #, c-format msgid "group quota inode % has bad type 0x%x\n" msgstr "" #: .././repair/dinode.c:1622 #, c-format msgid "project quota inode % has bad type 0x%x\n" msgstr "" #: .././repair/dinode.c:1632 #, c-format msgid "realtime summary inode % has bad type 0x%x, " msgstr "" #: .././repair/dinode.c:1635 .././repair/dinode.c:1656 msgid "resetting to regular file\n" msgstr "" #: .././repair/dinode.c:1639 .././repair/dinode.c:1660 msgid "would reset to regular file\n" msgstr "" #: .././repair/dinode.c:1644 #, c-format msgid "bad # of extents (%u) for realtime summary inode %\n" msgstr "" #: .././repair/dinode.c:1653 #, c-format msgid "realtime bitmap inode % has bad type 0x%x, " msgstr "" #: .././repair/dinode.c:1665 #, c-format msgid "bad # of extents (%u) for realtime bitmap inode %\n" msgstr "" #: .././repair/dinode.c:1700 #, c-format msgid "" "mismatch between format (%d) and size (%) in directory ino " "%\n" msgstr "" #: .././repair/dinode.c:1706 #, c-format msgid "directory inode % has bad size %\n" msgstr "" #: .././repair/dinode.c:1714 #, c-format msgid "bad data fork in symlink %\n" msgstr "" #: .././repair/dinode.c:1735 #, c-format msgid "found inode % claiming to be a real-time file\n" msgstr "" #: .././repair/dinode.c:1744 #, c-format msgid "" "realtime bitmap inode % has bad size % (should be " "%)\n" msgstr "" #: .././repair/dinode.c:1755 #, c-format msgid "" "realtime summary inode % has bad size % (should be %d)\n" msgstr "" #: .././repair/dinode.c:1783 #, c-format msgid "bad attr fork offset %d in dev inode %, should be %d\n" msgstr "" #: .././repair/dinode.c:1795 #, c-format msgid "bad attr fork offset %d in inode %, max=%d\n" msgstr "" #: .././repair/dinode.c:1802 #, c-format msgid "unexpected inode format %d\n" msgstr "" #: .././repair/dinode.c:1823 #, c-format msgid "correcting nblocks for inode %, was %llu - counted %\n" msgstr "" #: .././repair/dinode.c:1830 #, c-format msgid "bad nblocks %llu for inode %, would reset to %\n" msgstr "" #: .././repair/dinode.c:1838 #, c-format msgid "too many data fork extents (%) in inode %\n" msgstr "" #: .././repair/dinode.c:1845 #, c-format msgid "correcting nextents for inode %, was %d - counted %\n" msgstr "" #: .././repair/dinode.c:1853 #, c-format msgid "bad nextents %d for inode %, would reset to %\n" msgstr "" #: .././repair/dinode.c:1861 #, c-format msgid "too many attr fork extents (%) in inode %\n" msgstr "" #: .././repair/dinode.c:1868 #, c-format msgid "correcting anextents for inode %, was %d - counted %\n" msgstr "" #: .././repair/dinode.c:1875 #, c-format msgid "bad anextents %d for inode %, would reset to %\n" msgstr "" #: .././repair/dinode.c:1887 #, c-format msgid "nblocks (%) smaller than nextents for inode %\n" msgstr "" #: .././repair/dinode.c:1952 .././repair/dinode.c:1990 #, c-format msgid "unknown format %d, ino % (mode = %d)\n" msgstr "" #: .././repair/dinode.c:1957 #, c-format msgid "bad data fork in inode %\n" msgstr "" #: .././repair/dinode.c:2028 #, c-format msgid "bad attribute format %d in inode %, " msgstr "" #: .././repair/dinode.c:2031 msgid "resetting value\n" msgstr "" #: .././repair/dinode.c:2035 msgid "would reset value\n" msgstr "" #: .././repair/dinode.c:2080 #, c-format msgid "bad attribute fork in inode %" msgstr "" #: .././repair/dinode.c:2084 msgid ", clearing attr fork\n" msgstr "" #: .././repair/dinode.c:2093 msgid ", would clear attr fork\n" msgstr "" #: .././repair/dinode.c:2121 #, c-format msgid "illegal attribute fmt %d, ino %\n" msgstr "" #: .././repair/dinode.c:2141 #, c-format msgid "problem with attribute contents in inode %\n" msgstr "" #: .././repair/dinode.c:2149 msgid "would clear attr fork\n" msgstr "" #: .././repair/dinode.c:2182 #, c-format msgid "" "clearing obsolete nlink field in version 2 inode %, was %d, now 0\n" msgstr "" #: .././repair/dinode.c:2188 #, c-format msgid "" "would clear obsolete nlink field in version 2 inode %, currently %d\n" msgstr "" #: .././repair/dinode.c:2267 #, c-format msgid "bad CRC for inode %%c" msgstr "" #: .././repair/dinode.c:2271 msgid " will rewrite\n" msgstr "" #: .././repair/dinode.c:2274 msgid " would rewrite\n" msgstr "" #: .././repair/dinode.c:2281 #, c-format msgid "bad magic number 0x%x on inode %%c" msgstr "" #: .././repair/dinode.c:2286 msgid " resetting magic number\n" msgstr "" #: .././repair/dinode.c:2290 msgid " would reset magic number\n" msgstr "" #: .././repair/dinode.c:2297 #, c-format msgid "bad version number 0x%x on inode %%c" msgstr "" #: .././repair/dinode.c:2302 msgid " resetting version number\n" msgstr "" #: .././repair/dinode.c:2307 msgid " would reset version number\n" msgstr "" #: .././repair/dinode.c:2320 #, c-format msgid "inode identifier %llu mismatch on inode %\n" msgstr "" #: .././repair/dinode.c:2330 #, c-format msgid "UUID mismatch on inode %\n" msgstr "" #: .././repair/dinode.c:2343 #, c-format msgid "bad (negative) size % on inode %\n" msgstr "" #: .././repair/dinode.c:2376 #, c-format msgid "imap claims a free inode % is in use, " msgstr "" #: .././repair/dinode.c:2378 msgid "correcting imap and clearing inode\n" msgstr "" #: .././repair/dinode.c:2382 msgid "would correct imap and clear inode\n" msgstr "" #: .././repair/dinode.c:2399 #, c-format msgid "bad inode format in inode %\n" msgstr "" #: .././repair/dinode.c:2415 #, c-format msgid "Bad flags set in inode %\n" msgstr "" #: .././repair/dinode.c:2426 #, c-format msgid "inode % has RT flag set but there is no RT device\n" msgstr "" #: .././repair/dinode.c:2438 #, c-format msgid "inode % not rt bitmap\n" msgstr "" #: .././repair/dinode.c:2452 #, c-format msgid "directory flags set on non-directory inode %\n" msgstr "" #: .././repair/dinode.c:2466 #, c-format msgid "file flags set on non-file inode %\n" msgstr "" #: .././repair/dinode.c:2475 msgid "fixing bad flags.\n" msgstr "" #: .././repair/dinode.c:2479 msgid "would fix bad flags.\n" msgstr "" #: .././repair/dinode.c:2494 #, c-format msgid "Bad flags2 set in inode %\n" msgstr "" #: .././repair/dinode.c:2504 #, c-format msgid "" "inode % is marked reflinked but file system does not support " "reflink\n" msgstr "" #: .././repair/dinode.c:2515 #, c-format msgid "reflink flag set on non-file inode %\n" msgstr "" #: .././repair/dinode.c:2526 #, c-format msgid "Cannot have a reflinked realtime inode %\n" msgstr "" #: .././repair/dinode.c:2536 #, c-format msgid "" "inode % has CoW extent size hint but file system does not support " "reflink\n" msgstr "" #: .././repair/dinode.c:2547 #, c-format msgid "CoW extent size flag set on non-file, non-directory inode %\n" msgstr "" #: .././repair/dinode.c:2558 #, c-format msgid "Cannot have CoW extent size hint on a realtime inode %\n" msgstr "" #: .././repair/dinode.c:2566 msgid "fixing bad flags2.\n" msgstr "" #: .././repair/dinode.c:2570 msgid "would fix bad flags2.\n" msgstr "" #: .././repair/dinode.c:2621 #, c-format msgid "bad inode type %#o inode %\n" msgstr "" #: .././repair/dinode.c:2645 #, c-format msgid "bad non-zero extent size %u for non-realtime/extsize inode %, " msgstr "" #: .././repair/dinode.c:2648 .././repair/dinode.c:2671 msgid "resetting to zero\n" msgstr "" #: .././repair/dinode.c:2652 .././repair/dinode.c:2675 msgid "would reset to zero\n" msgstr "" #: .././repair/dinode.c:2668 #, c-format msgid "" "Cannot have non-zero CoW extent size %u on non-cowextsize inode %, " msgstr "" #: .././repair/dinode.c:2734 #, c-format msgid "problem with directory contents in inode %\n" msgstr "" #: .././repair/dinode.c:2742 #, c-format msgid "problem with symbolic link in inode %\n" msgstr "" #: .././repair/dinode.c:2837 #, c-format msgid "processing inode %d/%d\n" msgstr "" #: .././repair/dir2.c:50 #, c-format msgid "malloc failed (%zu bytes) dir2_add_badlist:ino %\n" msgstr "" #: .././repair/dir2.c:93 msgid "couldn't malloc dir2 shortform copy\n" msgstr "" #: .././repair/dir2.c:229 msgid "current" msgstr "" #: .././repair/dir2.c:232 .././repair/dir2.c:693 msgid "invalid" msgstr "" #: .././repair/dir2.c:235 .././repair/dir2.c:695 msgid "realtime bitmap" msgstr "" #: .././repair/dir2.c:238 .././repair/dir2.c:697 msgid "realtime summary" msgstr "" #: .././repair/dir2.c:241 .././repair/dir2.c:699 msgid "user quota" msgstr "" #: .././repair/dir2.c:244 .././repair/dir2.c:701 msgid "group quota" msgstr "" #: .././repair/dir2.c:247 .././repair/dir2.c:703 msgid "project quota" msgstr "" #: .././repair/dir2.c:265 .././repair/dir2.c:733 msgid "free" msgstr "" #: .././repair/dir2.c:282 .././repair/dir2.c:713 msgid "non-existent" msgstr "" #: .././repair/dir2.c:287 #, c-format msgid "" "entry \"%*.*s\" in shortform directory % references %s inode " "%\n" msgstr "" #: .././repair/dir2.c:293 msgid "is zero length" msgstr "" #: .././repair/dir2.c:298 msgid "extends past end of dir" msgstr "" #: .././repair/dir2.c:304 #, c-format msgid "entry #%d %s in shortform dir %" msgstr "" #: .././repair/dir2.c:307 #, c-format msgid ", junking %d entries\n" msgstr "" #: .././repair/dir2.c:310 #, c-format msgid ", would junk %d entries\n" msgstr "" #: .././repair/dir2.c:330 #, c-format msgid "entry contains illegal character in shortform dir %\n" msgstr "" #: .././repair/dir2.c:337 #, c-format msgid "entry contains offset out of order in shortform dir %\n" msgstr "" #: .././repair/dir2.c:394 #, c-format msgid "junking entry \"%s\" in directory inode %\n" msgstr "" #: .././repair/dir2.c:398 #, c-format msgid "would have junked entry \"%s\" in directory inode %\n" msgstr "" #: .././repair/dir2.c:423 #, c-format msgid "would have corrected entry count in directory % from %d to %d\n" msgstr "" #: .././repair/dir2.c:427 #, c-format msgid "corrected entry count in directory %, was %d, now %d\n" msgstr "" #: .././repair/dir2.c:438 #, c-format msgid "would have corrected i8 count in directory % from %d to %d\n" msgstr "" #: .././repair/dir2.c:442 #, c-format msgid "corrected i8 count in directory %, was %d, now %d\n" msgstr "" #: .././repair/dir2.c:456 #, c-format msgid "" "would have corrected directory % size from % to %\n" msgstr "" #: .././repair/dir2.c:461 #, c-format msgid "corrected directory % size, was %, now %\n" msgstr "" #: .././repair/dir2.c:473 #, c-format msgid "directory % offsets too high\n" msgstr "" #: .././repair/dir2.c:479 #, c-format msgid "would have corrected entry offsets in directory %\n" msgstr "" #: .././repair/dir2.c:483 #, c-format msgid "corrected entry offsets in directory %\n" msgstr "" #: .././repair/dir2.c:502 #, c-format msgid "bogus .. inode number (%) in directory inode %, " msgstr "" #: .././repair/dir2.c:506 .././repair/dir2.c:541 msgid "clearing inode number\n" msgstr "" #: .././repair/dir2.c:512 .././repair/dir2.c:547 msgid "would clear inode number\n" msgstr "" #: .././repair/dir2.c:520 #, c-format msgid "" "corrected root directory % .. entry, was %, now %\n" msgstr "" #: .././repair/dir2.c:528 #, c-format msgid "" "would have corrected root directory % .. entry from % to " "%\n" msgstr "" #: .././repair/dir2.c:538 #, c-format msgid "bad .. entry in directory inode %, points to self, " msgstr "" #: .././repair/dir2.c:651 #, c-format msgid "corrupt block %u in directory inode %\n" msgstr "" #: .././repair/dir2.c:654 msgid "\twill junk block\n" msgstr "" #: .././repair/dir2.c:656 msgid "\twould junk block\n" msgstr "" #: .././repair/dir2.c:742 #, c-format msgid "" "entry \"%*.*s\" at block %d offset % in directory inode % " "references %s inode %\n" msgstr "" #: .././repair/dir2.c:765 #, c-format msgid "" "entry at block %u offset % in directory inode %has 0 " "namelength\n" msgstr "" #: .././repair/dir2.c:778 #, c-format msgid "\tclearing inode number in entry at offset %...\n" msgstr "" #: .././repair/dir2.c:784 #, c-format msgid "\twould clear inode number in entry at offset %...\n" msgstr "" #: .././repair/dir2.c:797 #, c-format msgid "" "entry at block %u offset % in directory inode % has illegal " "name \"%*.*s\": " msgstr "" #: .././repair/dir2.c:828 #, c-format msgid "bad .. entry in directory inode %, points to self: " msgstr "" #: .././repair/dir2.c:839 #, c-format msgid "bad .. entry in root directory inode %, was %: " msgstr "" #: .././repair/dir2.c:842 .././repair/dir2.c:875 .././repair/phase2.c:217 #: .././repair/phase2.c:226 .././repair/phase2.c:235 msgid "correcting\n" msgstr "" #: .././repair/dir2.c:846 .././repair/dir2.c:879 .././repair/phase2.c:219 #: .././repair/phase2.c:228 .././repair/phase2.c:237 msgid "would correct\n" msgstr "" #: .././repair/dir2.c:859 #, c-format msgid "multiple .. entries in directory inode %: " msgstr "" #: .././repair/dir2.c:872 #, c-format msgid "bad . entry in directory inode %, was %: " msgstr "" #: .././repair/dir2.c:884 #, c-format msgid "multiple . entries in directory inode %: " msgstr "" #: .././repair/dir2.c:894 #, c-format msgid "entry \"%*.*s\" in directory inode % points to self: " msgstr "" #: .././repair/dir2.c:905 msgid "clearing entry\n" msgstr "" #: .././repair/dir2.c:907 msgid "would clear entry\n" msgstr "" #: .././repair/dir2.c:920 #, c-format msgid "bad bestfree table in block %u in directory inode %: " msgstr "" #: .././repair/dir2.c:923 msgid "repairing table\n" msgstr "" #: .././repair/dir2.c:928 msgid "would repair table\n" msgstr "" #: .././repair/dir2.c:968 #, c-format msgid "block %u for directory inode % is missing\n" msgstr "" #: .././repair/dir2.c:977 #, c-format msgid "can't read block %u for directory inode %\n" msgstr "" #: .././repair/dir2.c:988 #, c-format msgid "" "bad directory block magic # %#x in block %u for directory inode %\n" msgstr "" #: .././repair/dir2.c:1040 #, c-format msgid "bad entry count in block %u of directory inode %\n" msgstr "" #: .././repair/dir2.c:1048 #, c-format msgid "bad hash ordering in block %u of directory inode %\n" msgstr "" #: .././repair/dir2.c:1056 #, c-format msgid "bad stale count in block %u of directory inode %\n" msgstr "" #: .././repair/dir2.c:1105 #, c-format msgid "can't map block %u for directory inode %\n" msgstr "" #: .././repair/dir2.c:1115 #, c-format msgid "can't read file block %u for directory inode %\n" msgstr "" #: .././repair/dir2.c:1127 #, c-format msgid "bad directory leaf magic # %#x for directory inode % block %u\n" msgstr "" #: .././repair/dir2.c:1155 #, c-format msgid "bad sibling back pointer for block %u in directory inode %\n" msgstr "" #: .././repair/dir2.c:1186 #, c-format msgid "bad hash path in directory %\n" msgstr "" #: .././repair/dir2.c:1296 #, c-format msgid "block % for directory inode % is missing\n" msgstr "" #: .././repair/dir2.c:1305 #, c-format msgid "can't read block % for directory inode %\n" msgstr "" #: .././repair/dir2.c:1313 #, c-format msgid "" "bad directory block magic # %#x in block % for directory inode " "%\n" msgstr "" #: .././repair/dir2.c:1394 #, c-format msgid "bad size/format for directory %\n" msgstr "" #: .././repair/dir2.c:1401 #, c-format msgid "no . entry for directory %\n" msgstr "" #: .././repair/dir2.c:1411 #, c-format msgid "no .. entry for directory %\n" msgstr "" #: .././repair/dir2.c:1413 #, c-format msgid "no .. entry for root directory %\n" msgstr "" #: .././repair/incore.c:230 #, c-format msgid "couldn't allocate realtime block map, size = %\n" msgstr "" #: .././repair/incore.c:295 msgid "couldn't allocate block map btree roots\n" msgstr "" #: .././repair/incore.c:299 msgid "couldn't allocate block map locks\n" msgstr "" #: .././repair/incore_ext.c:135 .././repair/incore_ext.c:562 msgid "couldn't allocate new extent descriptor.\n" msgstr "" #: .././repair/incore_ext.c:232 msgid "duplicate bno extent range\n" msgstr "" #: .././repair/incore_ext.c:369 msgid ": duplicate bno extent range\n" msgstr "" #: .././repair/incore_ext.c:644 .././repair/incore_ext.c:699 msgid "duplicate extent range\n" msgstr "" #: .././repair/incore_ext.c:752 .././repair/incore_ext.c:756 msgid "couldn't malloc dup extent tree descriptor table\n" msgstr "" #: .././repair/incore_ext.c:761 msgid "couldn't malloc free by-bno extent tree descriptor table\n" msgstr "" #: .././repair/incore_ext.c:766 msgid "couldn't malloc free by-bcnt extent tree descriptor table\n" msgstr "" #: .././repair/incore_ext.c:772 msgid "couldn't malloc bno extent tree descriptor\n" msgstr "" #: .././repair/incore_ext.c:776 msgid "couldn't malloc bcnt extent tree descriptor\n" msgstr "" #: .././repair/incore_ext.c:787 msgid "couldn't malloc dup rt extent tree descriptor\n" msgstr "" #: .././repair/incore_ino.c:47 msgid "could not allocate nlink array\n" msgstr "" #: .././repair/incore_ino.c:225 msgid "could not allocate ftypes array\n" msgstr "" #: .././repair/incore_ino.c:251 msgid "inode map malloc failed\n" msgstr "" #: .././repair/incore_ino.c:367 msgid "add_aginode_uncertain - duplicate inode range\n" msgstr "" #: .././repair/incore_ino.c:462 msgid "add_inode - duplicate inode range\n" msgstr "" #: .././repair/incore_ino.c:556 #, c-format msgid "good inode list is --\n" msgstr "" #: .././repair/incore_ino.c:559 #, c-format msgid "uncertain inode list is --\n" msgstr "" #: .././repair/incore_ino.c:564 #, c-format msgid "agno %d -- no inodes\n" msgstr "" #: .././repair/incore_ino.c:568 #, c-format msgid "agno %d\n" msgstr "" #: .././repair/incore_ino.c:572 #, c-format msgid "\tptr = %lx, start = 0x%x, free = 0x%llx, confirmed = 0x%llx\n" msgstr "" #: .././repair/incore_ino.c:623 msgid "couldn't malloc parent list table\n" msgstr "" #: .././repair/incore_ino.c:634 .././repair/incore_ino.c:680 msgid "couldn't memalign pentries table\n" msgstr "" #: .././repair/incore_ino.c:738 msgid "could not malloc inode extra data\n" msgstr "" #: .././repair/incore_ino.c:804 msgid "couldn't malloc inode tree descriptor table\n" msgstr "" #: .././repair/incore_ino.c:808 msgid "couldn't malloc uncertain ino tree descriptor table\n" msgstr "" #: .././repair/incore_ino.c:813 msgid "couldn't malloc inode tree descriptor\n" msgstr "" #: .././repair/incore_ino.c:817 msgid "couldn't malloc uncertain ino tree descriptor\n" msgstr "" #: .././repair/incore_ino.c:825 msgid "couldn't malloc uncertain inode cache area\n" msgstr "" #: .././repair/init.c:46 #, c-format msgid "getrlimit(RLIMIT_FSIZE) failed!\n" msgstr "" #: .././repair/init.c:54 #, c-format msgid "setrlimit failed - current: %lld, max: %lld\n" msgstr "" #: .././repair/init.c:107 #, c-format msgid "" "Unmount or use the dangerous (-d) option to repair a read-only mounted " "filesystem\n" msgstr "" #: .././repair/init.c:109 msgid "couldn't initialize XFS library\n" msgstr "" #: .././repair/phase1.c:28 msgid "Sorry, could not find valid secondary superblock\n" msgstr "" #: .././repair/phase1.c:29 msgid "Exiting now.\n" msgstr "" #: .././repair/phase1.c:40 #, c-format msgid "could not allocate ag header buffer (%d bytes)\n" msgstr "" #: .././repair/phase1.c:58 msgid "Phase 1 - find and verify superblock...\n" msgstr "" #: .././repair/phase1.c:75 msgid "error reading primary superblock\n" msgstr "" #: .././repair/phase1.c:81 #, c-format msgid "bad primary superblock - %s !!!\n" msgstr "" #: .././repair/phase1.c:88 #, c-format msgid "couldn't verify primary superblock - %s !!!\n" msgstr "" #: .././repair/phase1.c:106 msgid "superblock has a features2 mismatch, correcting\n" msgstr "" #: .././repair/phase1.c:123 #, c-format msgid "Enabling lazy-counters\n" msgstr "" #: .././repair/phase1.c:127 #, c-format msgid "Cannot disable lazy-counters on V5 fs\n" msgstr "" #: .././repair/phase1.c:132 #, c-format msgid "Disabling lazy-counters\n" msgstr "" #: .././repair/phase1.c:135 #, c-format msgid "Lazy-counters are already %s\n" msgstr "" #: .././repair/phase1.c:136 msgid "enabled" msgstr "" #: .././repair/phase1.c:136 msgid "disabled" msgstr "" #: .././repair/phase1.c:143 msgid "writing modified primary superblock\n" msgstr "" #: .././repair/phase1.c:146 msgid "would write modified primary superblock\n" msgstr "" #: .././repair/phase2.c:79 #, c-format msgid "zero_log: cannot find log head/tail (xlog_find_tail=%d)\n" msgstr "" #: .././repair/phase2.c:83 msgid "" "ERROR: The log head and/or tail cannot be discovered. Attempt to mount the\n" "filesystem to replay the log or use the -L option to destroy the log and\n" "attempt a repair.\n" msgstr "" #: .././repair/phase2.c:90 #, c-format msgid "zero_log: head block % tail block %\n" msgstr "" #: .././repair/phase2.c:96 msgid "" "ALERT: The filesystem has valuable metadata changes in a log which is being\n" "destroyed because the -L option was used.\n" msgstr "" #: .././repair/phase2.c:100 msgid "" "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running xfs_repair. If you are unable to mount the filesystem, then use\n" "the -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n" msgstr "" #: .././repair/phase2.c:128 msgid "failed to clear log" msgstr "" #: .././repair/phase2.c:162 msgid "" "This filesystem has an external log. Specify log device with the -l " "option.\n" msgstr "" #: .././repair/phase2.c:165 #, c-format msgid "Phase 2 - using external log on %s\n" msgstr "" #: .././repair/phase2.c:167 msgid "Phase 2 - using internal log\n" msgstr "" #: .././repair/phase2.c:170 msgid " - zero log...\n" msgstr "" #: .././repair/phase2.c:173 msgid " - scan filesystem freespace and inode maps...\n" msgstr "" #: .././repair/phase2.c:189 msgid "root inode chunk not found\n" msgstr "" #: .././repair/phase2.c:208 msgid " - found root inode chunk\n" msgstr "" #: .././repair/phase2.c:214 msgid "root inode marked free, " msgstr "" #: .././repair/phase2.c:223 msgid "realtime bitmap inode marked free, " msgstr "" #: .././repair/phase2.c:232 msgid "realtime summary inode marked free, " msgstr "" #: .././repair/phase3.c:47 #, c-format msgid "cannot read agi block % for ag %u\n" msgstr "" #: .././repair/phase3.c:78 .././repair/phase4.c:142 .././repair/phase5.c:2260 #: .././repair/phase6.c:3134 #, c-format msgid " - agno = %d\n" msgstr "" #: .././repair/phase3.c:119 msgid "Phase 3 - for each AG...\n" msgstr "" #: .././repair/phase3.c:121 msgid " - scan and clear agi unlinked lists...\n" msgstr "" #: .././repair/phase3.c:123 msgid " - scan (but don't clear) agi unlinked lists...\n" msgstr "" #: .././repair/phase3.c:143 msgid " - process known inodes and perform inode discovery...\n" msgstr "" #: .././repair/phase3.c:154 msgid " - process newly discovered inodes...\n" msgstr "" #: .././repair/phase3.c:159 msgid "no memory for uncertain inode counts\n" msgstr "" #: .././repair/phase4.c:165 #, c-format msgid "" "unable to finish adding attr/data fork reverse-mapping data for AG %u.\n" msgstr "" #: .././repair/phase4.c:181 #, c-format msgid "unable to add AG %u metadata reverse-mapping data.\n" msgstr "" #: .././repair/phase4.c:186 #, c-format msgid "unable to merge AG %u metadata reverse-mapping data.\n" msgstr "" #: .././repair/phase4.c:191 #, c-format msgid "%s while checking reverse-mappings" msgstr "" #: .././repair/phase4.c:206 #, c-format msgid "%s while computing reference count records.\n" msgstr "" #: .././repair/phase4.c:221 #, c-format msgid "%s while fixing inode reflink flags.\n" msgstr "" #: .././repair/phase4.c:236 #, c-format msgid "%s while checking reference counts" msgstr "" #: .././repair/phase4.c:290 msgid "Phase 4 - check for duplicate blocks...\n" msgstr "" #: .././repair/phase4.c:291 msgid " - setting up duplicate extent list...\n" msgstr "" #: .././repair/phase4.c:305 msgid "root inode would be lost\n" msgstr "" #: .././repair/phase4.c:307 msgid "root inode lost\n" msgstr "" #: .././repair/phase4.c:324 #, c-format msgid "unknown block state, ag %d, block %d\n" msgstr "" #: .././repair/phase4.c:357 #, c-format msgid "unknown rt extent state, extent %\n" msgstr "" #: .././repair/phase4.c:406 msgid " - check for inodes claiming duplicate blocks...\n" msgstr "" #: .././repair/phase5.c:223 msgid "could not set up btree block array\n" msgstr "" #: .././repair/phase5.c:244 msgid "error - not enough free space in filesystem\n" msgstr "" #: .././repair/phase5.c:259 #, c-format msgid "could not set up btree rmaps: %s\n" msgstr "" #: .././repair/phase5.c:475 #, c-format msgid "can't rebuild fs trees -- not enough free space on ag %u\n" msgstr "" #: .././repair/phase5.c:498 #, c-format msgid "ag %u - not enough free space to build freespace btrees\n" msgstr "" #: .././repair/phase5.c:533 #, c-format msgid "not enough free blocks left to describe all free blocks in AG %u\n" msgstr "" #: .././repair/phase5.c:1622 msgid "Insufficient memory to construct reverse-map cursor." msgstr "" #: .././repair/phase5.c:1928 msgid "Insufficient memory to construct refcount cursor." msgstr "" #: .././repair/phase5.c:2139 .././repair/phase5.c:2147 msgid "Insufficient memory saving lost blocks.\n" msgstr "" #: .././repair/phase5.c:2202 .././repair/xfs_repair.c:1032 msgid "couldn't get superblock\n" msgstr "" #: .././repair/phase5.c:2283 #, c-format msgid "unable to rebuild AG %u. Not enough free space in on-disk AG.\n" msgstr "" #: .././repair/phase5.c:2335 #, c-format msgid "unable to rebuild AG %u. No free space.\n" msgstr "" #: .././repair/phase5.c:2459 #, c-format msgid "unable to add AG %u reverse-mapping data to btree.\n" msgstr "" #: .././repair/phase5.c:2519 msgid "Phase 5 - rebuild AG headers and trees...\n" msgstr "" #: .././repair/phase5.c:2548 msgid "cannot alloc sb_icount_ag buffers\n" msgstr "" #: .././repair/phase5.c:2552 msgid "cannot alloc sb_ifree_ag buffers\n" msgstr "" #: .././repair/phase5.c:2556 msgid "cannot alloc sb_fdblocks_ag buffers\n" msgstr "" #: .././repair/phase5.c:2560 msgid "cannot alloc lost block slab\n" msgstr "" #: .././repair/phase5.c:2579 msgid " - generate realtime summary info and bitmap...\n" msgstr "" #: .././repair/phase5.c:2584 msgid " - reset superblock...\n" msgstr "" #: .././repair/phase5.c:2593 msgid "Unable to reinsert lost blocks into filesystem.\n" msgstr "" #: .././repair/phase6.c:64 #, c-format msgid "malloc failed add_dotdot_update (%zu bytes)\n" msgstr "" #: .././repair/phase6.c:216 #, c-format msgid "malloc failed in dir_hash_add (%zu bytes)\n" msgstr "" #: .././repair/phase6.c:270 msgid "ok" msgstr "" #: .././repair/phase6.c:271 msgid "duplicate leaf" msgstr "" #: .././repair/phase6.c:272 msgid "hash value mismatch" msgstr "" #: .././repair/phase6.c:273 msgid "no data entry" msgstr "" #: .././repair/phase6.c:274 msgid "no leaf entry" msgstr "" #: .././repair/phase6.c:275 msgid "bad stale count" msgstr "" #: .././repair/phase6.c:283 #, c-format msgid "bad hash table for directory inode % (%s): " msgstr "" #: .././repair/phase6.c:286 msgid "rebuilding\n" msgstr "" #: .././repair/phase6.c:288 msgid "would rebuild\n" msgstr "" #: .././repair/phase6.c:324 msgid "calloc failed in dir_hash_init\n" msgstr "" #: .././repair/phase6.c:472 msgid "ran out of disk space!\n" msgstr "" #: .././repair/phase6.c:474 #, c-format msgid "xfs_trans_reserve returned %d\n" msgstr "" #: .././repair/phase6.c:504 .././repair/phase6.c:606 #, c-format msgid "couldn't iget realtime bitmap inode -- error - %d\n" msgstr "" #: .././repair/phase6.c:562 #, c-format msgid "couldn't allocate realtime bitmap, error = %d\n" msgstr "" #: .././repair/phase6.c:575 #, c-format msgid "allocation of the realtime bitmap failed, error = %d\n" msgstr "" #: .././repair/phase6.c:620 #, c-format msgid "couldn't map realtime bitmap block %, error = %d\n" msgstr "" #: .././repair/phase6.c:633 #, c-format msgid "" "can't access block % (fsbno %) of realtime bitmap inode " "%\n" msgstr "" #: .././repair/phase6.c:677 .././repair/phase6.c:751 #, c-format msgid "couldn't iget realtime summary inode -- error - %d\n" msgstr "" #: .././repair/phase6.c:691 #, c-format msgid "couldn't map realtime summary inode block %, error = %d\n" msgstr "" #: .././repair/phase6.c:704 #, c-format msgid "" "can't access block % (fsbno %) of realtime summary inode " "%\n" msgstr "" #: .././repair/phase6.c:814 #, c-format msgid "couldn't allocate realtime summary inode, error = %d\n" msgstr "" #: .././repair/phase6.c:827 #, c-format msgid "allocation of the realtime summary ino failed, error = %d\n" msgstr "" #: .././repair/phase6.c:856 #, c-format msgid "could not iget root inode -- error - %d\n" msgstr "" #: .././repair/phase6.c:933 #, c-format msgid "%d - couldn't iget root inode to obtain %s\n" msgstr "" #: .././repair/phase6.c:963 #, c-format msgid "%s inode allocation failed %d\n" msgstr "" #: .././repair/phase6.c:1010 #, c-format msgid "can't make %s, createname error %d\n" msgstr "" #: .././repair/phase6.c:1030 #, c-format msgid "%s directory creation failed -- bmapf error %d\n" msgstr "" #: .././repair/phase6.c:1072 #, c-format msgid "%d - couldn't iget orphanage inode\n" msgstr "" #: .././repair/phase6.c:1083 #, c-format msgid "%d - couldn't iget disconnected inode\n" msgstr "" #: .././repair/phase6.c:1104 .././repair/phase6.c:1146 #: .././repair/phase6.c:1202 #, c-format msgid "space reservation failed (%d), filesystem may be out of space\n" msgstr "" #: .././repair/phase6.c:1115 .././repair/phase6.c:1158 #: .././repair/phase6.c:1213 #, c-format msgid "name create failed in %s (%d), filesystem may be out of space\n" msgstr "" #: .././repair/phase6.c:1128 #, c-format msgid "creation of .. entry failed (%d), filesystem may be out of space\n" msgstr "" #: .././repair/phase6.c:1137 #, c-format msgid "bmap finish failed (err - %d), filesystem may be out of space\n" msgstr "" #: .././repair/phase6.c:1177 #, c-format msgid "name replace op failed (%d), filesystem may be out of space\n" msgstr "" #: .././repair/phase6.c:1184 .././repair/phase6.c:1223 #: .././repair/phase6.c:1357 #, c-format msgid "bmap finish failed (%d), filesystem may be out of space\n" msgstr "" #: .././repair/phase6.c:1242 msgid ", marking entry to be junked\n" msgstr "" #: .././repair/phase6.c:1246 msgid ", would junk entry\n" msgstr "" #: .././repair/phase6.c:1279 #, c-format msgid "rebuilding directory inode %\n" msgstr "" #: .././repair/phase6.c:1301 #, c-format msgid "xfs_bmap_last_offset failed -- error - %d\n" msgstr "" #: .././repair/phase6.c:1308 #, c-format msgid "xfs_bunmapi failed -- error - %d\n" msgstr "" #: .././repair/phase6.c:1316 #, c-format msgid "xfs_dir_init failed -- error - %d\n" msgstr "" #: .././repair/phase6.c:1349 #, c-format msgid "" "name create failed in ino % (%d), filesystem may be out of space\n" msgstr "" #: .././repair/phase6.c:1412 #, c-format msgid "shrink_inode failed inode % block %u\n" msgstr "" #: .././repair/phase6.c:1503 .././repair/phase6.c:2300 #, c-format msgid "realloc failed in %s (%zu bytes)\n" msgstr "" #: .././repair/phase6.c:1560 #, c-format msgid "empty data block %u in directory inode %: " msgstr "" #: .././repair/phase6.c:1564 #, c-format msgid "corrupt block %u in directory inode %: " msgstr "" #: .././repair/phase6.c:1568 msgid "junking block\n" msgstr "" #: .././repair/phase6.c:1571 msgid "would junk block\n" msgstr "" #: .././repair/phase6.c:1593 #, c-format msgid "" "bad directory block magic # %#x for directory inode % block %d: " msgstr "" #: .././repair/phase6.c:1596 #, c-format msgid "fixing magic # to %#x\n" msgstr "" #: .././repair/phase6.c:1600 #, c-format msgid "would fix magic # to %#x\n" msgstr "" #: .././repair/phase6.c:1621 #, c-format msgid "directory inode % block %u has consecutive free entries: " msgstr "" #: .././repair/phase6.c:1625 msgid "joining together\n" msgstr "" #: .././repair/phase6.c:1634 msgid "would join together\n" msgstr "" #: .././repair/phase6.c:1667 #, c-format msgid "" "entry \"%s\" in directory inode % points to non-existent inode " "%" msgstr "" #: .././repair/phase6.c:1684 #, c-format msgid "" "entry \"%s\" in directory inode % points to free inode %" msgstr "" #: .././repair/phase6.c:1702 .././repair/phase6.c:2627 #, c-format msgid "%s (ino %) in root (%) is not a directory" msgstr "" #: .././repair/phase6.c:1724 .././repair/phase6.c:2649 #, c-format msgid "entry \"%s\" (ino %) in dir % is a duplicate name" msgstr "" #: .././repair/phase6.c:1755 #, c-format msgid "" "entry \"%s\" (ino %) in dir % is not in the the first block" msgstr "" #: .././repair/phase6.c:1781 #, c-format msgid "entry \"%s\" in dir % is not the first entry" msgstr "" #: .././repair/phase6.c:1807 .././repair/phase6.c:2718 #, c-format msgid "" "would fix ftype mismatch (%d/%d) in directory/child inode %/" "%\n" msgstr "" #: .././repair/phase6.c:1812 .././repair/phase6.c:2723 #, c-format msgid "" "fixing ftype mismatch (%d/%d) in directory/child inode %/%\n" msgstr "" #: .././repair/phase6.c:1845 #, c-format msgid "" "entry \"%s\" in dir % points to an already connected directory inode " "%\n" msgstr "" #: .././repair/phase6.c:1854 .././repair/phase6.c:2687 #, c-format msgid "" "entry \"%s\" in dir ino % doesn't have a .. entry, will set it in " "ino %.\n" msgstr "" #: .././repair/phase6.c:1864 #, c-format msgid "" "entry \"%s\" in dir inode % inconsistent with .. value (%) " "in ino %\n" msgstr "" #: .././repair/phase6.c:1876 #, c-format msgid "\twill clear entry \"%s\"\n" msgstr "" #: .././repair/phase6.c:1879 #, c-format msgid "\twould clear entry \"%s\"\n" msgstr "" #: .././repair/phase6.c:1912 #, c-format msgid "expected owner inode %, got %llu, directory block %\n" msgstr "" #: .././repair/phase6.c:1919 #, c-format msgid "expected block %, got %llu, directory inode %\n" msgstr "" #: .././repair/phase6.c:1926 #, c-format msgid "wrong FS UUID, directory inode % block %\n" msgstr "" #: .././repair/phase6.c:1986 #, c-format msgid "leaf block %u for directory inode % bad CRC\n" msgstr "" #: .././repair/phase6.c:1991 #, c-format msgid "can't read block %u for directory inode %, error %d\n" msgstr "" #: .././repair/phase6.c:2009 .././repair/phase6.c:2132 #, c-format msgid "leaf block %u for directory inode % bad header\n" msgstr "" #: .././repair/phase6.c:2035 #, c-format msgid "leaf block %u for directory inode % bad tail\n" msgstr "" #: .././repair/phase6.c:2089 #, c-format msgid "can't read leaf block %u for directory inode %, error %d\n" msgstr "" #: .././repair/phase6.c:2101 #, c-format msgid "unknown magic number %#x for block %u in directory inode %\n" msgstr "" #: .././repair/phase6.c:2157 #, c-format msgid "can't read freespace block %u for directory inode %, error %d\n" msgstr "" #: .././repair/phase6.c:2172 #, c-format msgid "free block %u for directory inode % bad header\n" msgstr "" #: .././repair/phase6.c:2190 #, c-format msgid "free block %u entry %i for directory ino % bad\n" msgstr "" #: .././repair/phase6.c:2200 #, c-format msgid "free block %u for directory inode % bad nused\n" msgstr "" #: .././repair/phase6.c:2211 #, c-format msgid "missing freetab entry %u for directory inode %\n" msgstr "" #: .././repair/phase6.c:2250 #, c-format msgid "malloc failed in %s (% bytes)\n" msgstr "" #: .././repair/phase6.c:2264 #, c-format msgid "calloc failed in %s (%zu bytes)\n" msgstr "" #: .././repair/phase6.c:2313 #, c-format msgid "can't read data block %u for directory inode % error %d\n" msgstr "" #: .././repair/phase6.c:2420 msgid "would junk entry\n" msgstr "" #: .././repair/phase6.c:2444 msgid "junking entry\n" msgstr "" #: .././repair/phase6.c:2490 #, c-format msgid "would set .. in sf dir inode % to %\n" msgstr "" #: .././repair/phase6.c:2494 #, c-format msgid "setting .. in sf dir inode % to %\n" msgstr "" #: .././repair/phase6.c:2594 #, c-format msgid "" "entry \"%s\" in shortform directory % references non-existent inode " "%\n" msgstr "" #: .././repair/phase6.c:2611 #, c-format msgid "" "entry \"%s\" in shortform directory inode % points to free inode " "%\n" msgstr "" #: .././repair/phase6.c:2673 #, c-format msgid "" "entry \"%s\" in directory inode % references already connected inode " "%.\n" msgstr "" #: .././repair/phase6.c:2696 #, c-format msgid "" "entry \"%s\" in directory inode % not consistent with .. value " "(%) in inode %,\n" msgstr "" #: .././repair/phase6.c:2753 #, c-format msgid "would fix i8count in inode %\n" msgstr "" #: .././repair/phase6.c:2768 #, c-format msgid "fixing i8count in inode %\n" msgstr "" #: .././repair/phase6.c:2788 #, c-format msgid "setting size to % bytes to reflect junked entries\n" msgstr "" #: .././repair/phase6.c:2827 .././repair/phase6.c:2831 .././repair/phase7.c:52 #, c-format msgid "couldn't map inode %, err = %d\n" msgstr "" #: .././repair/phase6.c:2932 msgid "recreating root directory .. entry\n" msgstr "" #: .././repair/phase6.c:2948 #, c-format msgid "can't make \"..\" entry in root inode %, createname error %d\n" msgstr "" #: .././repair/phase6.c:2958 msgid "would recreate root directory .. entry\n" msgstr "" #: .././repair/phase6.c:2982 #, c-format msgid "would create missing \".\" entry in dir ino %\n" msgstr "" #: .././repair/phase6.c:2989 #, c-format msgid "creating missing \".\" entry in dir ino %\n" msgstr "" #: .././repair/phase6.c:3005 #, c-format msgid "can't make \".\" entry in dir ino %, createname error %d\n" msgstr "" #: .././repair/phase6.c:3101 #, c-format msgid "disconnected dir inode %, " msgstr "" #: .././repair/phase6.c:3103 #, c-format msgid "disconnected inode %, " msgstr "" #: .././repair/phase6.c:3107 #, c-format msgid "moving to %s\n" msgstr "" #: .././repair/phase6.c:3110 #, c-format msgid "would move to %s\n" msgstr "" #: .././repair/phase6.c:3195 msgid "Phase 6 - check inode connectivity...\n" msgstr "" #: .././repair/phase6.c:3209 msgid "reinitializing root directory\n" msgstr "" #: .././repair/phase6.c:3214 msgid "would reinitialize root directory\n" msgstr "" #: .././repair/phase6.c:3220 msgid "reinitializing realtime bitmap inode\n" msgstr "" #: .././repair/phase6.c:3224 msgid "would reinitialize realtime bitmap inode\n" msgstr "" #: .././repair/phase6.c:3230 msgid "reinitializing realtime summary inode\n" msgstr "" #: .././repair/phase6.c:3234 msgid "would reinitialize realtime summary inode\n" msgstr "" #: .././repair/phase6.c:3240 msgid " - resetting contents of realtime bitmap and summary inodes\n" msgstr "" #: .././repair/phase6.c:3243 .././repair/phase6.c:3248 msgid "Warning: realtime bitmap may be inconsistent\n" msgstr "" #: .././repair/phase6.c:3254 msgid " - traversing filesystem ...\n" msgstr "" #: .././repair/phase6.c:3277 msgid " - traversal finished ...\n" msgstr "" #: .././repair/phase6.c:3278 #, c-format msgid " - moving disconnected inodes to %s ...\n" msgstr "" #: .././repair/phase7.c:56 #, c-format msgid "couldn't map inode %, err = %d, can't compare link counts\n" msgstr "" #: .././repair/phase7.c:68 #, c-format msgid "resetting inode % nlinks from %u to %u\n" msgstr "" #: .././repair/phase7.c:74 #, c-format msgid "would have reset inode % nlinks from %u to %u\n" msgstr "" #: .././repair/phase7.c:142 msgid "Phase 7 - verify and correct link counts...\n" msgstr "" #: .././repair/phase7.c:144 msgid "Phase 7 - verify link counts...\n" msgstr "" #: .././repair/prefetch.c:543 msgid "prefetch corruption\n" msgstr "" #: .././repair/prefetch.c:704 .././repair/prefetch.c:817 #, c-format msgid "failed to create prefetch thread: %s\n" msgstr "" #: .././repair/prefetch.c:854 msgid "failed to initialize prefetch mutex\n" msgstr "" #: .././repair/prefetch.c:856 .././repair/prefetch.c:858 msgid "failed to initialize prefetch cond var\n" msgstr "" #: .././repair/progress.c:16 msgid "inodes" msgstr "" #: .././repair/progress.c:20 msgid "directories" msgstr "" #: .././repair/progress.c:22 msgid "allocation groups" msgstr "" #: .././repair/progress.c:24 msgid "AGI unlinked buckets" msgstr "" #: .././repair/progress.c:28 msgid "realtime extents" msgstr "" #: .././repair/progress.c:30 msgid "unlinked lists" msgstr "" #: .././repair/progress.c:37 #, c-format msgid " - %02d:%02d:%02d: %s - %llu of %llu %s done\n" msgstr "" #: .././repair/progress.c:39 #, c-format msgid " - %02d:%02d:%02d: %s - %llu %s done\n" msgstr "" #: .././repair/progress.c:51 msgid "scanning filesystem freespace" msgstr "" #: .././repair/progress.c:53 msgid "scanning agi unlinked lists" msgstr "" #: .././repair/progress.c:55 msgid "check uncertain AG inodes" msgstr "" #: .././repair/progress.c:57 msgid "process known inodes and inode discovery" msgstr "" #: .././repair/progress.c:59 msgid "process newly discovered inodes" msgstr "" #: .././repair/progress.c:61 msgid "setting up duplicate extent list" msgstr "" #: .././repair/progress.c:63 msgid "initialize realtime bitmap" msgstr "" #: .././repair/progress.c:65 msgid "reset realtime bitmaps" msgstr "" #: .././repair/progress.c:67 msgid "check for inodes claiming duplicate blocks" msgstr "" #: .././repair/progress.c:69 msgid "rebuild AG headers and trees" msgstr "" #: .././repair/progress.c:71 msgid "traversing filesystem" msgstr "" #: .././repair/progress.c:73 msgid "traversing all unattached subtrees" msgstr "" #: .././repair/progress.c:75 msgid "moving disconnected inodes to lost+found" msgstr "" #: .././repair/progress.c:77 msgid "verify and correct link counts" msgstr "" #: .././repair/progress.c:79 msgid "verify link counts" msgstr "" #: .././repair/progress.c:118 msgid "cannot malloc pointer to done vector\n" msgstr "" #: .././repair/progress.c:135 msgid "unable to create progress report thread\n" msgstr "" #: .././repair/progress.c:178 msgid "progress_rpt: cannot malloc progress msg buffer\n" msgstr "" #: .././repair/progress.c:191 msgid "progress_rpt: cannot create timer\n" msgstr "" #: .././repair/progress.c:194 msgid "progress_rpt: cannot set timer\n" msgstr "" #: .././repair/progress.c:218 msgid "progress_rpt: cannot lock progress mutex\n" msgstr "" #: .././repair/progress.c:255 .././repair/progress.c:358 #, c-format msgid "%s" msgstr "" #: .././repair/progress.c:263 #, c-format msgid "" "\t- %02d:%02d:%02d: Phase %d: elapsed time %s - processed %d %s per minute\n" msgstr "" #: .././repair/progress.c:268 #, c-format msgid "" "\t- %02d:%02d:%02d: Phase %d: %%% done - estimated remaining time " "%s\n" msgstr "" #: .././repair/progress.c:276 msgid "progress_rpt: error unlock msg mutex\n" msgstr "" #: .././repair/progress.c:282 msgid "cannot delete timer\n" msgstr "" #: .././repair/progress.c:296 msgid "set_progress_msg: cannot lock progress mutex\n" msgstr "" #: .././repair/progress.c:306 msgid "set_progress_msg: cannot unlock progress mutex\n" msgstr "" #: .././repair/progress.c:326 msgid "print_final_rpt: cannot lock progress mutex\n" msgstr "" #: .././repair/progress.c:362 msgid "print_final_rpt: cannot unlock progress mutex\n" msgstr "" #: .././repair/progress.c:411 #, c-format msgid "%02d:%02d:%02d" msgstr "" #: .././repair/progress.c:433 #, c-format msgid "%d week" msgstr "" #: .././repair/progress.c:434 .././repair/progress.c:444 #: .././repair/progress.c:460 .././repair/progress.c:478 #: .././repair/progress.c:493 msgid "s" msgstr "" #: .././repair/progress.c:443 #, c-format msgid "%d day" msgstr "" #: .././repair/progress.c:450 .././repair/progress.c:467 #: .././repair/progress.c:485 .././repair/progress.c:495 msgid ", " msgstr "" #: .././repair/progress.c:459 #, c-format msgid "%d hour" msgstr "" #: .././repair/progress.c:477 #, c-format msgid "%d minute" msgstr "" #: .././repair/progress.c:492 #, c-format msgid "%d second" msgstr "" #: .././repair/progress.c:513 #, c-format msgid "" "\n" " XFS_REPAIR Summary %s\n" msgstr "" #: .././repair/progress.c:515 msgid "Phase\t\tStart\t\tEnd\t\tDuration\n" msgstr "" #: .././repair/progress.c:520 .././repair/progress.c:523 #, c-format msgid "Phase %d:\tSkipped\n" msgstr "" #: .././repair/progress.c:527 #, c-format msgid "Phase %d:\t%02d/%02d %02d:%02d:%02d\t%02d/%02d %02d:%02d:%02d\t%s\n" msgstr "" #: .././repair/progress.c:533 #, c-format msgid "" "\n" "Total run time: %s\n" msgstr "" #: .././repair/rmap.c:112 msgid "couldn't allocate per-AG reverse map roots\n" msgstr "" #: .././repair/rmap.c:119 msgid "Insufficient memory while allocating reverse mapping slabs." msgstr "" #: .././repair/rmap.c:124 .././repair/rmap.c:363 msgid "" "Insufficient memory while allocating raw metadata reverse mapping slabs." msgstr "" #: .././repair/rmap.c:130 msgid "Insufficient memory while allocating refcount item slabs." msgstr "" #: .././repair/rmap.c:736 msgid "Insufficient memory while recreating refcount tree." msgstr "" #: .././repair/rmap.c:993 msgid "would rebuild corrupt rmap btrees.\n" msgstr "" #: .././repair/rmap.c:1036 #, c-format msgid "" "Missing reverse-mapping record for (%u/%u) %slen %u owner % %s%soff " "%\n" msgstr "" #: .././repair/rmap.c:1040 .././repair/rmap.c:1058 .././repair/rmap.c:1068 msgid "unwritten " msgstr "" #: .././repair/rmap.c:1044 .././repair/rmap.c:1062 .././repair/rmap.c:1072 msgid "attr " msgstr "" #: .././repair/rmap.c:1046 .././repair/rmap.c:1064 .././repair/rmap.c:1074 msgid "bmbt " msgstr "" #: .././repair/rmap.c:1054 #, c-format msgid "" "Incorrect reverse-mapping: saw (%u/%u) %slen %u owner % %s%soff " "%; should be (%u/%u) %slen %u owner % %s%soff %\n" msgstr "" #: .././repair/rmap.c:1189 #, c-format msgid "setting reflink flag on inode %\n" msgstr "" #: .././repair/rmap.c:1193 #, c-format msgid "clearing reflink flag on inode %\n" msgstr "" #: .././repair/rmap.c:1264 #, c-format msgid "Unable to fix reflink flag on inode %.\n" msgstr "" #: .././repair/rmap.c:1325 msgid "would rebuild corrupt refcount btrees.\n" msgstr "" #: .././repair/rmap.c:1358 .././repair/rmap.c:1369 #, c-format msgid "Missing reference count record for (%u/%u) len %u count %u\n" msgstr "" #: .././repair/rmap.c:1380 #, c-format msgid "" "Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) " "len %u nlinks %u\n" msgstr "" #: .././repair/rmap.c:1422 .././repair/rmap.c:1453 #, c-format msgid "failed to fix AGFL on AG %d, error %d\n" msgstr "" #: .././repair/rt.c:47 msgid "couldn't allocate memory for incore realtime bitmap.\n" msgstr "" #: .././repair/rt.c:51 msgid "couldn't allocate memory for incore realtime summary info.\n" msgstr "" #: .././repair/rt.c:203 #, c-format msgid "can't find block %d for rtbitmap inode\n" msgstr "" #: .././repair/rt.c:211 #, c-format msgid "can't read block %d for rtbitmap inode\n" msgstr "" #: .././repair/rt.c:265 #, c-format msgid "block %d for rtsummary inode is missing\n" msgstr "" #: .././repair/rt.c:273 #, c-format msgid "can't read block %d for rtsummary inode\n" msgstr "" #: .././repair/sb.c:125 msgid "error finding secondary superblock -- failed to memalign buffer\n" msgstr "" #: .././repair/sb.c:162 msgid "found candidate secondary superblock...\n" msgstr "" #: .././repair/sb.c:174 msgid "verified secondary superblock...\n" msgstr "" #: .././repair/sb.c:179 msgid "unable to verify superblock, continuing...\n" msgstr "" #: .././repair/sb.c:229 msgid "" "\n" "attempting to find secondary superblock...\n" msgstr "" #: .././repair/sb.c:510 msgid "failed to memalign superblock buffer\n" msgstr "" #: .././repair/sb.c:517 msgid "couldn't seek to offset 0 in filesystem\n" msgstr "" #: .././repair/sb.c:527 msgid "primary superblock write failed!\n" msgstr "" #: .././repair/sb.c:545 #, c-format msgid "error reading superblock %u -- failed to memalign buffer\n" msgstr "" #: .././repair/sb.c:556 #, c-format msgid "error reading superblock %u -- seek to offset % failed\n" msgstr "" #: .././repair/sb.c:565 #, c-format msgid "superblock read failed, offset %, size %d, ag %u, rval %d\n" msgstr "" #: .././repair/sb.c:612 msgid "couldn't malloc geometry structure\n" msgstr "" #: .././repair/sb.c:766 msgid "" "Only two AGs detected and they do not match - cannot validate filesystem " "geometry.\n" "Use the -o force_geometry option to proceed.\n" msgstr "" #: .././repair/sb.c:782 msgid "" "Only one AG detected - cannot validate filesystem geometry.\n" "Use the -o force_geometry option to proceed.\n" msgstr "" #: .././repair/sb.c:797 msgid "Not enough matching superblocks - cannot proceed.\n" msgstr "" #: .././repair/sb.c:812 msgid "could not read superblock\n" msgstr "" #: .././repair/scan.c:85 .././repair/scan.c:140 #, c-format msgid "can't read btree block %d/%d\n" msgstr "" #: .././repair/scan.c:89 .././repair/scan.c:152 #, c-format msgid "btree block %d/%d is suspect, error %d\n" msgstr "" #: .././repair/scan.c:213 #, c-format msgid "bad magic # %#x in inode % (%s fork) bmbt block %\n" msgstr "" #: .././repair/scan.c:219 #, c-format msgid "" "expected level %d got %d in inode %, (%s fork) bmbt block %\n" msgstr "" #: .././repair/scan.c:229 #, c-format msgid "expected owner inode %, got %llu, bmbt block %\n" msgstr "" #: .././repair/scan.c:237 #, c-format msgid "expected block %, got %llu, bmbt block %\n" msgstr "" #: .././repair/scan.c:246 #, c-format msgid "wrong FS UUID, bmbt block %\n" msgstr "" #: .././repair/scan.c:266 #, c-format msgid "" "bad fwd (right) sibling pointer (saw % parent block says %)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" #: .././repair/scan.c:276 #, c-format msgid "" "bad back (left) sibling pointer (saw %llu parent block says %)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" #: .././repair/scan.c:291 #, c-format msgid "" "bad back (left) sibling pointer (saw %llu should be NULL (0))\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" #: .././repair/scan.c:339 #, c-format msgid "inode 0x%bmap block 0x% claimed, state is %d\n" msgstr "" #: .././repair/scan.c:346 #, c-format msgid "inode 0x% bmap block 0x% claimed, state is %d\n" msgstr "" #: .././repair/scan.c:361 #, c-format msgid "bad state %d, inode % bmap block 0x%\n" msgstr "" #: .././repair/scan.c:389 #, c-format msgid "couldn't add inode % bmbt block % reverse-mapping data." msgstr "" #: .././repair/scan.c:397 .././repair/scan.c:448 #, c-format msgid "inode % bad # of bmap records (%u, min - %u, max - %u)\n" msgstr "" #: .././repair/scan.c:427 #, c-format msgid "" "out-of-order bmap key (file offset) in inode %, %s fork, fsbno " "%\n" msgstr "" #: .././repair/scan.c:465 #, c-format msgid "bad bmap btree ptr 0x%llx in ino %\n" msgstr "" #: .././repair/scan.c:493 #, c-format msgid "" "correcting bt key (was %llu, now %) in inode %\n" "\t\t%s fork, btree block %\n" msgstr "" #: .././repair/scan.c:505 #, c-format msgid "" "bad btree key (is %llu, should be %) in inode %\n" "\t\t%s fork, btree block %\n" msgstr "" #: .././repair/scan.c:523 #, c-format msgid "" "bad fwd (right) sibling pointer (saw % should be NULLFSBLOCK)\n" "\tin inode % (%s fork) bmap btree block %\n" msgstr "" #: .././repair/scan.c:581 .././repair/scan.c:958 #, c-format msgid "bad magic # %#x in bt%s block %d/%d\n" msgstr "" #: .././repair/scan.c:599 .././repair/scan.c:977 #, c-format msgid "expected level %d got %d in bt%s block %d/%d\n" msgstr "" #: .././repair/scan.c:613 #, c-format msgid "" "%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" #: .././repair/scan.c:633 .././repair/scan.c:734 .././repair/scan.c:1008 #: .././repair/scan.c:1152 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n" msgstr "" #: .././repair/scan.c:651 .././repair/scan.c:1043 .././repair/scan.c:1329 #, c-format msgid "invalid start block %u in record %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:657 .././repair/scan.c:1049 .././repair/scan.c:1335 #, c-format msgid "invalid length %u in record %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:704 #, c-format msgid "block (%d,%d-%d) multiply claimed by %s space tree, state - %d\n" msgstr "" #: .././repair/scan.c:833 #, c-format msgid "" "Static meta block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:842 #, c-format msgid "AG meta block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:850 #, c-format msgid "inode block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:858 #, c-format msgid "" "AG refcount block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:867 #, c-format msgid "in use block (%d,%d-%d) mismatch in %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:889 #, c-format msgid "unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%\n" msgstr "" #: .././repair/scan.c:989 #, c-format msgid "%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" #: .././repair/scan.c:1033 #, c-format msgid "invalid flags in record %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:1062 #, c-format msgid "invalid owner in rmap btree record %d (% %u) block %u/%u\n" msgstr "" #: .././repair/scan.c:1069 #, c-format msgid "" "record %d of block (%u/%u) in %s btree cannot have non-inode owner with " "flags\n" msgstr "" #: .././repair/scan.c:1073 #, c-format msgid "" "record %d of block (%u/%u) in %s btree cannot have non-inode owner with " "offset\n" msgstr "" #: .././repair/scan.c:1094 #, c-format msgid "" "out-of-order rmap btree record %d (%u % % %u) block %u/%u\n" msgstr "" #: .././repair/scan.c:1103 .././repair/scan.c:1381 #, c-format msgid "" "record %d in block (%u/%u) of %s tree should be merged with previous record\n" msgstr "" #: .././repair/scan.c:1118 #, c-format msgid "record %d greater than high key of block (%u/%u) in %s tree\n" msgstr "" #: .././repair/scan.c:1174 #, c-format msgid "invalid flags in key %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:1180 #, c-format msgid "key %d greater than high key of block (%u/%u) in %s tree\n" msgstr "" #: .././repair/scan.c:1206 #, c-format msgid "invalid flags in high key %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:1257 #, c-format msgid "bad magic # %#x in %s btree block %d/%d\n" msgstr "" #: .././repair/scan.c:1265 #, c-format msgid "expected level %d got %d in %s btree block %d/%d\n" msgstr "" #: .././repair/scan.c:1279 #, c-format msgid "%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" #: .././repair/scan.c:1298 .././repair/scan.c:1415 #, c-format msgid "bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:1316 #, c-format msgid "" "leftover CoW extent has incorrect refcount in record %u of %s btree block %u/" "%u\n" msgstr "" #: .././repair/scan.c:1321 #, c-format msgid "" "leftover CoW extent has invalid startblock in record %u of %s btree block %u/" "%u\n" msgstr "" #: .././repair/scan.c:1356 #, c-format msgid "extent (%u/%u) len %u claimed, state is %d\n" msgstr "" #: .././repair/scan.c:1363 #, c-format msgid "invalid reference count %u in record %u of %s btree block %u/%u\n" msgstr "" #: .././repair/scan.c:1370 #, c-format msgid "out-of-order %s btree record %d (%u %u) block %u/%u\n" msgstr "" #: .././repair/scan.c:1496 #, c-format msgid "badly aligned %s rec (starting inode = %)\n" msgstr "" #: .././repair/scan.c:1510 #, c-format msgid "bad starting inode # (% (0x%x 0x%x)) in %s rec, skipping rec\n" msgstr "" #: .././repair/scan.c:1519 #, c-format msgid "bad ending inode # (% (0x%x 0x%zx)) in %s rec, skipping rec\n" msgstr "" #: .././repair/scan.c:1584 #, c-format msgid "" "ir_holemask/ir_free mismatch, %s chunk %d/%u, holemask 0x%x free 0x%llx\n" msgstr "" #: .././repair/scan.c:1671 #, c-format msgid "" "inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n" msgstr "" #: .././repair/scan.c:1689 #, c-format msgid "" "inode rec for ino % (%d/%d) overlaps existing rec (start %d/%d)\n" msgstr "" #: .././repair/scan.c:1713 #, c-format msgid "ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n" msgstr "" #: .././repair/scan.c:1721 .././repair/scan.c:1911 #, c-format msgid "invalid inode count, inode chunk %d/%u, count %d ninodes %d\n" msgstr "" #: .././repair/scan.c:1775 #, c-format msgid "" "sparse inode chunk claims inode block, finobt block - agno %d, bno %d, inopb " "%d\n" msgstr "" #: .././repair/scan.c:1790 .././repair/scan.c:1802 #, c-format msgid "" "inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb " "%d\n" msgstr "" #: .././repair/scan.c:1812 #, c-format msgid "" "inode chunk claims used block, finobt block - agno %d, bno %d, inopb %d\n" msgstr "" #: .././repair/scan.c:1834 #, c-format msgid "" "finobt rec for ino % (%d/%u) does not match existing rec (%d/%d)\n" msgstr "" #: .././repair/scan.c:1876 #, c-format msgid "undiscovered finobt record, ino % (%d/%u)\n" msgstr "" #: .././repair/scan.c:1898 #, c-format msgid "" "finobt ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n" msgstr "" #: .././repair/scan.c:1904 #, c-format msgid "finobt record with no free inodes, inode chunk %d/%u\n" msgstr "" #: .././repair/scan.c:1957 #, c-format msgid "bad magic # %#x in inobt block %d/%d\n" msgstr "" #: .././repair/scan.c:1965 #, c-format msgid "expected level %d got %d in inobt block %d/%d\n" msgstr "" #: .././repair/scan.c:1988 #, c-format msgid "inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n" msgstr "" #: .././repair/scan.c:2011 #, c-format msgid "dubious inode btree block header %d/%d\n" msgstr "" #: .././repair/scan.c:2129 #, c-format msgid "can't read agfl block for ag %d\n" msgstr "" #: .././repair/scan.c:2133 #, c-format msgid "agfl has bad CRC for ag %d\n" msgstr "" #: .././repair/scan.c:2154 #, c-format msgid "bad agbno %u in agfl, agno %d\n" msgstr "" #: .././repair/scan.c:2163 #, c-format msgid "freeblk count %d != flcount %d in ag %d\n" msgstr "" #: .././repair/scan.c:2189 #, c-format msgid "bad agbno %u for btbno root, agno %d\n" msgstr "" #: .././repair/scan.c:2201 #, c-format msgid "bad agbno %u for btbcnt root, agno %d\n" msgstr "" #: .././repair/scan.c:2220 #, c-format msgid "bad rmapbt block count %u, saw %u\n" msgstr "" #: .././repair/scan.c:2224 #, c-format msgid "bad agbno %u for rmapbt root, agno %d\n" msgstr "" #: .././repair/scan.c:2241 #, c-format msgid "bad refcountbt block count %u, saw %u\n" msgstr "" #: .././repair/scan.c:2245 #, c-format msgid "bad agbno %u for refcntbt root, agno %d\n" msgstr "" #: .././repair/scan.c:2263 #, c-format msgid "agf_btreeblks %u, counted % in ag %u\n" msgstr "" #: .././repair/scan.c:2287 #, c-format msgid "bad agbno %u for inobt root, agno %d\n" msgstr "" #: .././repair/scan.c:2300 #, c-format msgid "bad agbno %u for finobt root, agno %d\n" msgstr "" #: .././repair/scan.c:2317 #, c-format msgid "agi_freecount %u, counted %u in ag %u finobt\n" msgstr "" #: .././repair/scan.c:2327 #, c-format msgid "agi unlinked bucket %d is %u in ag %u (inode=%)\n" msgstr "" #: .././repair/scan.c:2358 msgid "can't allocate memory for superblock\n" msgstr "" #: .././repair/scan.c:2365 msgid "root superblock" msgstr "" #: .././repair/scan.c:2374 msgid "agf block" msgstr "" #: .././repair/scan.c:2383 msgid "agi block" msgstr "" #: .././repair/scan.c:2404 #, c-format msgid "reset bad sb for ag %d\n" msgstr "" #: .././repair/scan.c:2407 #, c-format msgid "would reset bad sb for ag %d\n" msgstr "" #: .././repair/scan.c:2412 #, c-format msgid "reset bad agf for ag %d\n" msgstr "" #: .././repair/scan.c:2415 #, c-format msgid "would reset bad agf for ag %d\n" msgstr "" #: .././repair/scan.c:2420 #, c-format msgid "reset bad agi for ag %d\n" msgstr "" #: .././repair/scan.c:2423 #, c-format msgid "would reset bad agi for ag %d\n" msgstr "" #: .././repair/scan.c:2428 #, c-format msgid "bad uncorrected agheader %d, skipping ag...\n" msgstr "" #: .././repair/scan.c:2491 #, c-format msgid "can't get %s for ag %d\n" msgstr "" #: .././repair/scan.c:2511 msgid "no memory for ag header counts\n" msgstr "" #: .././repair/scan.c:2537 #, c-format msgid "sb_icount %, counted %\n" msgstr "" #: .././repair/scan.c:2542 #, c-format msgid "sb_ifree %, counted %\n" msgstr "" #: .././repair/scan.c:2547 #, c-format msgid "sb_fdblocks %, counted %\n" msgstr "" #: .././repair/scan.c:2553 #, c-format msgid "used blocks %, counted %\n" msgstr "" #: .././repair/threads.c:90 #, c-format msgid "cannot create worker threads, error = [%d] %s\n" msgstr "" #: .././repair/threads.c:108 #, c-format msgid "cannot allocate worker item, error = [%d] %s\n" msgstr "" #: .././repair/versions.c:68 #, c-format msgid "bogus quota flags 0x%x set in superblock" msgstr "" #: .././repair/versions.c:74 msgid ", bogus flags will be cleared\n" msgstr "" #: .././repair/versions.c:76 msgid ", bogus flags would be cleared\n" msgstr "" #: .././repair/versions.c:115 .././repair/versions.c:120 #: .././repair/versions.c:125 msgid "Shared Version bit set. Not supported. Ever.\n" msgstr "" #: .././repair/versions.c:138 msgid "This filesystem has uninitialized extent flags.\n" msgstr "" #: .././repair/versions.c:144 msgid "" "This filesystem uses feature(s) not yet supported in this release.\n" "Please run a more recent version of xfs_repair.\n" msgstr "" #: .././repair/versions.c:150 #, c-format msgid "WARNING: unknown superblock version %d\n" msgstr "" #: .././repair/versions.c:153 msgid "This filesystem contains features not understood by this program.\n" msgstr "" #: .././repair/versions.c:161 msgid "" "WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twill be downgraded. This may cause loss of filesystem meta-data\n" msgstr "" #: .././repair/versions.c:166 msgid "" "WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twould be downgraded. This might cause loss of filesystem\n" "\tmeta-data.\n" msgstr "" #: .././repair/versions.c:182 #, c-format msgid "" "Superblock has unknown compat/rocompat/incompat features (0x%x/0x%x/0x%x).\n" "Using a more recent xfs_repair is recommended.\n" msgstr "" #: .././repair/versions.c:194 msgid "" "WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attributes will be removed.\n" msgstr "" #: .././repair/versions.c:199 msgid "" "WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attributes would be removed.\n" msgstr "" #: .././repair/versions.c:212 msgid "" "WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attr2 attributes will be removed.\n" msgstr "" #: .././repair/versions.c:217 msgid "" "WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attr2 attributes would be removed.\n" msgstr "" #: .././repair/versions.c:229 msgid "" "WARNING: you have a V1 inode filesystem. It will be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././repair/versions.c:234 msgid "" "WARNING: you have a V1 inode filesystem. It would be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././repair/versions.c:244 msgid "" "WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem will be downgraded and\n" "\tall quota information will be removed.\n" msgstr "" #: .././repair/versions.c:249 msgid "" "WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem would be downgraded and\n" "\tall quota information would be removed.\n" msgstr "" #: .././repair/versions.c:277 msgid "" "WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem will be downgraded.\n" "\tThis will permanently degrade the performance of this filesystem.\n" msgstr "" #: .././repair/versions.c:282 msgid "" "WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem would be downgraded.\n" "\tThis would permanently degrade the performance of this filesystem.\n" msgstr "" #: .././repair/xfs_repair.c:85 #, c-format msgid "" "Usage: %s [options] device\n" "\n" "Options:\n" " -f The device is a file\n" " -L Force log zeroing. Do this as a last resort.\n" " -l logdev Specifies the device where the external log resides.\n" " -m maxmem Maximum amount of memory to be used in megabytes.\n" " -n No modify mode, just checks the filesystem for damage.\n" " -P Disables prefetching.\n" " -r rtdev Specifies the device where the realtime section resides.\n" " -v Verbose output.\n" " -c subopts Change filesystem parameters - use xfs_admin.\n" " -o subopts Override default behaviour, refer to man page.\n" " -t interval Reporting interval in seconds.\n" " -d Repair dangerously.\n" " -V Reports version and exits.\n" msgstr "" #: .././repair/xfs_repair.c:111 msgid "no error" msgstr "" #: .././repair/xfs_repair.c:112 msgid "bad magic number" msgstr "" #: .././repair/xfs_repair.c:113 msgid "bad blocksize field" msgstr "" #: .././repair/xfs_repair.c:114 msgid "bad blocksize log field" msgstr "" #: .././repair/xfs_repair.c:115 msgid "bad or unsupported version" msgstr "" #: .././repair/xfs_repair.c:117 msgid "filesystem mkfs-in-progress bit set" msgstr "" #: .././repair/xfs_repair.c:119 msgid "inconsistent filesystem geometry information" msgstr "" #: .././repair/xfs_repair.c:121 msgid "bad inode size or inconsistent with number of inodes/block" msgstr "" #: .././repair/xfs_repair.c:122 msgid "bad sector size" msgstr "" #: .././repair/xfs_repair.c:124 msgid "AGF geometry info conflicts with filesystem geometry" msgstr "" #: .././repair/xfs_repair.c:126 msgid "AGI geometry info conflicts with filesystem geometry" msgstr "" #: .././repair/xfs_repair.c:128 msgid "AG superblock geometry info conflicts with filesystem geometry" msgstr "" #: .././repair/xfs_repair.c:129 msgid "attempted to perform I/O beyond EOF" msgstr "" #: .././repair/xfs_repair.c:131 msgid "inconsistent filesystem geometry in realtime filesystem component" msgstr "" #: .././repair/xfs_repair.c:133 msgid "maximum indicated percentage of inodes > 100%" msgstr "" #: .././repair/xfs_repair.c:135 msgid "inconsistent inode alignment value" msgstr "" #: .././repair/xfs_repair.c:137 msgid "not enough secondary superblocks with matching geometry" msgstr "" #: .././repair/xfs_repair.c:139 msgid "bad stripe unit in superblock" msgstr "" #: .././repair/xfs_repair.c:141 msgid "bad stripe width in superblock" msgstr "" #: .././repair/xfs_repair.c:143 msgid "bad shared version number in superblock" msgstr "" #: .././repair/xfs_repair.c:145 msgid "bad CRC in superblock" msgstr "" #: .././repair/xfs_repair.c:150 #, c-format msgid "bad error code - %d\n" msgstr "" #: .././repair/xfs_repair.c:158 #, c-format msgid "-%c %s option cannot have a value\n" msgstr "" #: .././repair/xfs_repair.c:248 msgid "-o ihash option has been removed and will be ignored\n" msgstr "" #: .././repair/xfs_repair.c:253 msgid "-o bhash option cannot be used with -m option\n" msgstr "" #: .././repair/xfs_repair.c:305 msgid "-m option cannot be used with -o bhash option\n" msgstr "" #: .././repair/xfs_repair.c:347 #, c-format msgid "" "\n" "fatal error -- " msgstr "" #: .././repair/xfs_repair.c:474 #, c-format msgid "sb root inode value % %sinconsistent with calculated value %u\n" msgstr "" #: .././repair/xfs_repair.c:481 #, c-format msgid "resetting superblock root inode pointer to %u\n" msgstr "" #: .././repair/xfs_repair.c:485 #, c-format msgid "would reset superblock root inode pointer to %u\n" msgstr "" #: .././repair/xfs_repair.c:497 #, c-format msgid "" "sb realtime bitmap inode % %sinconsistent with calculated value %u\n" msgstr "" #: .././repair/xfs_repair.c:504 #, c-format msgid "resetting superblock realtime bitmap ino pointer to %u\n" msgstr "" #: .././repair/xfs_repair.c:508 #, c-format msgid "would reset superblock realtime bitmap ino pointer to %u\n" msgstr "" #: .././repair/xfs_repair.c:520 #, c-format msgid "" "sb realtime summary inode % %sinconsistent with calculated value %u\n" msgstr "" #: .././repair/xfs_repair.c:527 #, c-format msgid "resetting superblock realtime summary ino pointer to %u\n" msgstr "" #: .././repair/xfs_repair.c:531 #, c-format msgid "would reset superblock realtime summary ino pointer to %u\n" msgstr "" #: .././repair/xfs_repair.c:587 #, c-format msgid "Maximum metadata LSN (%d:%d) is ahead of log (%d:%d).\n" msgstr "" #: .././repair/xfs_repair.c:591 #, c-format msgid "Would format log to cycle %d.\n" msgstr "" #: .././repair/xfs_repair.c:595 #, c-format msgid "Format log to cycle %d.\n" msgstr "" #: .././repair/xfs_repair.c:663 msgid "" "Primary superblock would have been modified.\n" "Cannot proceed further in no_modify mode.\n" "Exiting now.\n" msgstr "" #: .././repair/xfs_repair.c:671 msgid "" "Primary superblock bad after phase 1!\n" "Exiting now.\n" msgstr "" #: .././repair/xfs_repair.c:682 #, c-format msgid "%s: couldn't stat \"%s\"\n" msgstr "" #: .././repair/xfs_repair.c:699 msgid "" "Cannot get host filesystem geometry.\n" "Repair may fail if there is a sector size mismatch between\n" "the image and the host filesystem.\n" msgstr "" #: .././repair/xfs_repair.c:711 msgid "" "Sector size on host filesystem larger than image sector size.\n" "Cannot turn off direct IO, so exiting.\n" msgstr "" #: .././repair/xfs_repair.c:728 #, c-format msgid "%s: cannot repair this filesystem. Sorry.\n" msgstr "" #: .././repair/xfs_repair.c:804 #, c-format msgid " - reporting progress in intervals of %s\n" msgstr "" #: .././repair/xfs_repair.c:849 #, c-format msgid "" " - max_mem = %lu, icount = %, imem = %, dblock = " "%, dmem = %\n" msgstr "" #: .././repair/xfs_repair.c:858 #, c-format msgid "" "Required memory for repair is greater that the maximum specified\n" "with the -m option. Please increase it to at least %lu.\n" msgstr "" #: .././repair/xfs_repair.c:863 #, c-format msgid "" "Memory available for repair (%luMB) may not be sufficient.\n" "At least %luMB is needed to repair this filesystem efficiently\n" "If repair fails due to lack of memory, please\n" msgstr "" #: .././repair/xfs_repair.c:869 msgid "turn prefetching off (-P) to reduce the memory footprint.\n" msgstr "" #: .././repair/xfs_repair.c:872 #, c-format msgid "increase system RAM and/or swap space to at least %luMB.\n" msgstr "" #: .././repair/xfs_repair.c:887 #, c-format msgid " - block cache size set to %d entries\n" msgstr "" #: .././repair/xfs_repair.c:912 msgid "Found unsupported filesystem features. Exiting now.\n" msgstr "" #: .././repair/xfs_repair.c:930 #, c-format msgid "No modify flag set, skipping phase 5\n" msgstr "" #: .././repair/xfs_repair.c:950 msgid "Inode allocation btrees are too corrupted, skipping phases 6 and 7\n" msgstr "" #: .././repair/xfs_repair.c:956 msgid "Warning: no quota inodes were found. Quotas disabled.\n" msgstr "" #: .././repair/xfs_repair.c:959 msgid "Warning: no quota inodes were found. Quotas would be disabled.\n" msgstr "" #: .././repair/xfs_repair.c:964 msgid "Warning: quota inodes were cleared. Quotas disabled.\n" msgstr "" #: .././repair/xfs_repair.c:967 msgid "Warning: quota inodes would be cleared. Quotas would be disabled.\n" msgstr "" #: .././repair/xfs_repair.c:973 msgid "" "Warning: user quota information was cleared.\n" "User quotas can not be enforced until limit information is recreated.\n" msgstr "" #: .././repair/xfs_repair.c:977 msgid "" "Warning: user quota information would be cleared.\n" "User quotas could not be enforced until limit information was recreated.\n" msgstr "" #: .././repair/xfs_repair.c:985 msgid "" "Warning: group quota information was cleared.\n" "Group quotas can not be enforced until limit information is recreated.\n" msgstr "" #: .././repair/xfs_repair.c:989 msgid "" "Warning: group quota information would be cleared.\n" "Group quotas could not be enforced until limit information was recreated.\n" msgstr "" #: .././repair/xfs_repair.c:997 msgid "" "Warning: project quota information was cleared.\n" "Project quotas can not be enforced until limit information is recreated.\n" msgstr "" #: .././repair/xfs_repair.c:1001 msgid "" "Warning: project quota information would be cleared.\n" "Project quotas could not be enforced until limit information was recreated.\n" msgstr "" #: .././repair/xfs_repair.c:1018 msgid "No modify flag set, skipping filesystem flush and exiting.\n" msgstr "" #: .././repair/xfs_repair.c:1037 msgid "Note - quota info will be regenerated on next quota mount.\n" msgstr "" #: .././repair/xfs_repair.c:1044 #, c-format msgid "" "Note - stripe unit (%d) and width (%d) were copied from a backup " "superblock.\n" "Please reset with mount -o sunit=,swidth= if necessary\n" msgstr "" #: .././repair/xfs_repair.c:1068 msgid "done\n" msgstr "" #: .././repair/xfs_repair.c:1072 msgid "Repair of readonly mount complete. Immediate reboot encouraged.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:30 #, c-format msgid "%s [-e extsize] [-p] [-V] source target\n" msgstr "" #: .././rtcp/xfs_rtcp.c:69 #, c-format msgid "%s: must specify files to copy\n" msgstr "" #: .././rtcp/xfs_rtcp.c:84 #, c-format msgid "%s: stat of %s failed\n" msgstr "" #: .././rtcp/xfs_rtcp.c:91 #, c-format msgid "%s: final argument is not directory\n" msgstr "" #: .././rtcp/xfs_rtcp.c:138 #, c-format msgid "%s: failed stat on %s: %s\n" msgstr "" #: .././rtcp/xfs_rtcp.c:159 #, c-format msgid "%s: %s filesystem has no realtime partition\n" msgstr "" #: .././rtcp/xfs_rtcp.c:180 .././rtcp/xfs_rtcp.c:208 #, c-format msgid "%s: open of %s failed: %s\n" msgstr "" #: .././rtcp/xfs_rtcp.c:197 #, c-format msgid "%s: set attributes on %s failed: %s\n" msgstr "" #: .././rtcp/xfs_rtcp.c:215 #, c-format msgid "%s: get attributes of %s failed: %s\n" msgstr "" #: .././rtcp/xfs_rtcp.c:225 .././rtcp/xfs_rtcp.c:262 #, c-format msgid "%s: %s is not a realtime file.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:235 #, c-format msgid "%s: %s file extent size is %d, instead of %d.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:248 .././rtcp/xfs_rtcp.c:271 #, c-format msgid "%s: open of %s source failed: %s\n" msgstr "" #: .././rtcp/xfs_rtcp.c:285 #, c-format msgid "%s: couldn't get direct I/O information: %s\n" msgstr "" #: .././rtcp/xfs_rtcp.c:295 #, c-format msgid "%s: extent size %d not a multiple of %d.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:309 #, c-format msgid "The size of %s is not a multiple of %d.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:312 #, c-format msgid "%s will be padded to %lld bytes.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:318 #, c-format msgid "" "Use the -p option to pad %s to a size which is a multiple of %d bytes.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:360 #, c-format msgid "%s: write error: %s\n" msgstr "" #: .././rtcp/xfs_rtcp.c:388 #, c-format msgid "%s: could not open %s: %s\n" msgstr "" #: .././copy/xfs_copy.c:155 msgid "lseek64 error" msgstr "" #: .././copy/xfs_copy.c:256 #, c-format msgid "%s: lseek64 error on target %d \"%s\" at offset %lld\n" msgstr "" #: .././copy/xfs_copy.c:383 #, c-format msgid "%s: lseek64 failure at offset %lld\n" msgstr "" #: .././db/write.c:58 msgid "" "\n" " The 'write' command takes on different personalities depending on the\n" " type of object being worked with.\n" "\n" " Write has 3 modes:\n" " 'struct mode' - is active anytime you're looking at a filesystem object\n" " which contains individual fields (ex: an inode).\n" " 'data mode' - is active anytime you set a disk address directly or set\n" " the type to 'data'.\n" " 'string mode' - only used for writing symlink blocks.\n" "\n" " Examples:\n" " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n" " 'write fname \"hello\\000\"' - write superblock fname.\n" " (note: in struct mode strings are not null terminated)\n" " 'write fname #6669736800' - write superblock fname with " "hex.\n" " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n" " - write superblock uuid.\n" " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n" " 'write lshift 3' - shift the block 3 bytes to the left\n" " 'write sequence 1 5' - write a cycle of number [1-5] through\n" " the entire block.\n" " String mode: 'write \"This_is_a_filename\" - write null terminated " "string.\n" "\n" " In data mode type 'write' by itself for a list of specific commands.\n" "\n" " Specifying the -c option will allow writes of invalid (corrupt) data.\n" "\n" msgstr "" #: .././db/write.c:137 msgid "Allowing write of corrupted data\n" msgstr "" #: .././db/dquot.c:37 msgid "[projid|gid|uid]" msgstr "" #: .././db/dquot.c:38 msgid "set current address to project, group or user quota block" msgstr "" #: .././growfs/xfs_growfs.c:64 #, c-format msgid "" "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n" msgstr "" #: .././io/init.c:35 #, c-format msgid "Usage: %s [-adfmnrRstVx] [-p prog] [-c cmd]... file\n" msgstr "" #: .././io/reflink.c:85 #, c-format msgid "Extents did not match.\n" msgstr "" #: .././io/attr.c:58 #, c-format msgid "" "\n" " displays the set of extended inode flags associated with the current file\n" "\n" " Each individual flag is displayed as a single character, in this order:\n" " r -- file data is stored in the realtime section\n" " p -- file has preallocated extents (cannot be changed using chattr)\n" " i -- immutable, file cannot be modified\n" " a -- append-only, file can only be appended to\n" " s -- all updates are synchronous\n" " A -- the access time is not updated for this inode\n" " d -- do not include this file in a dump of the filesystem\n" " t -- child created in this directory has realtime bit set by default\n" " P -- child created in this directory has parents project ID by default\n" " n -- symbolic links cannot be created in this directory\n" " e -- for non-realtime files, observe the inode extent size value\n" " E -- children created in this directory inherit the extent size value\n" " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, but only list attributes on directories\n" " -a -- show all flags which can be set alongside those which are set\n" " -v -- verbose mode; show long names of flags, not single characters\n" "\n" msgstr "" #: .././io/attr.c:89 #, c-format msgid "" "\n" " modifies the set of extended inode flags associated with the current file\n" "\n" " Examples:\n" " 'chattr +a' - sets the append-only flag\n" " 'chattr -a' - clears the append-only flag\n" "\n" " -R -- recursively descend (useful when current file is a directory)\n" " -D -- recursively descend, only modifying attributes on directories\n" " +/-r -- set/clear the realtime flag\n" " +/-i -- set/clear the immutable flag\n" " +/-a -- set/clear the append-only flag\n" " +/-s -- set/clear the sync flag\n" " +/-A -- set/clear the no-atime flag\n" " +/-d -- set/clear the no-dump flag\n" " +/-t -- set/clear the realtime inheritance flag\n" " +/-P -- set/clear the project ID inheritance flag\n" " +/-n -- set/clear the no-symbolic-links flag\n" " +/-e -- set/clear the extent-size flag\n" " +/-E -- set/clear the extent-size inheritance flag\n" " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " Note1: user must have certain capabilities to modify immutable/append-" "only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" " Note3: the realtime flag can only be set if the filesystem has a realtime\n" " section, and the (regular) file must be empty when the flag is set.\n" "\n" msgstr "" #: .././io/bmap.c:30 #, c-format msgid "" "\n" " prints the block mapping for an XFS file's data or attribute forks\n" " Example:\n" " 'bmap -vp' - tabular format verbose map, including unwritten extents\n" "\n" " bmap prints the map of disk blocks used by the current file.\n" " The map lists each extent used by the file, as well as regions in the\n" " file that do not have any corresponding blocks (holes).\n" " By default, each line of the listing takes the following form:\n" " extent: [startoffset..endoffset]: startblock..endblock\n" " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are " "unwritten.)\n" " -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" " Note: the bmap for non-regular files can be obtained provided the file\n" " was opened appropriately (in particular, must be opened read-only).\n" "\n" msgstr "" #: .././io/open.c:762 msgid "[-acdrstxT] [path]" msgstr "" #: .././io/prealloc.c:349 msgid "[-c] [-k] [-p] off len" msgstr "" #: .././io/mmap.c:135 #, c-format msgid "" "\n" " maps a range within the current file into memory\n" "\n" " Example:\n" " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" "\n" " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" " With no arguments, mmap shows the current mappings. The current mapping\n" " can be set by using the single argument form (mapping number or address).\n" " If two arguments are specified (a range), a new mapping is created and the\n" " following options are available:\n" " -r -- map with PROT_READ protection\n" " -w -- map with PROT_WRITE protection\n" " -x -- map with PROT_EXEC protection\n" " If no protection mode is specified, all are used by default.\n" "\n" msgstr "" #: .././io/mmap.c:584 #, c-format msgid "" "\n" " resizes the current memory mapping\n" "\n" " Examples:\n" " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" "\n" " Resizes the mappping, growing or shrinking from the current size.\n" " The default stored value is 'X', repeated to fill the range specified.\n" " -f -- use the MREMAP_FIXED flag\n" " -m -- use the MREMAP_MAYMOVE flag\n" "\n" msgstr "" #: .././io/mmap.c:650 msgid "[N] | [-rwx] [off len]" msgstr "" #: .././io/mmap.c:702 msgid "[-m|-f] newsize" msgstr "" #: .././libxfs/rdwr.c:1036 #, c-format msgid "%s: pwrite64 failed: %s\n" msgstr "" #: .././libxfs/rdwr.c:1042 #, c-format msgid "%s: error - pwrite64 only %d of %d bytes\n" msgstr "" #: .././logprint/log_print_all.c:258 #, c-format msgid "\t\tmagic:%c%c mode:0x%x ver:%d format:%d onlink:%d\n" msgstr "" #: .././logprint/log_print_all.c:262 #, c-format msgid "\t\tuid:%d gid:%d nlink:%d projid:%u\n" msgstr "" #: .././logprint/log_print_all.c:388 #, c-format msgid "\tEFD: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_print_all.c:420 #, c-format msgid "\tEFI: #regs:%d num_extents:%d id:0x%llx\n" msgstr "" #: .././logprint/log_print_trans.c:27 #, c-format msgid "TRANS: tid:0x%x type:%s #items:%d trans:0x%x q:0x%lx\n" msgstr "" #: .././logprint/log_misc.c:236 #, c-format msgid " type: %s tid: %x num_items: %d\n" msgstr "" #: .././logprint/log_misc.c:493 #, c-format msgid "EFD: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_misc.c:548 #, c-format msgid "EFI: #regs: %d num_extents: %d id: 0x%llx\n" msgstr "" #: .././logprint/log_misc.c:890 #, c-format msgid "%s: lseek64 to %lld failed: %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:230 #, c-format msgid "data su/sw must not be used in conjunction with data sunit/swidth\n" msgstr "" #: .././mkfs/xfs_mkfs.c:246 #, c-format msgid "data sunit/swidth must not be used in conjunction with data su/sw\n" msgstr "" #: .././mkfs/xfs_mkfs.c:281 #, c-format msgid "log su should not be used in conjunction with log sunit\n" msgstr "" #: .././mkfs/xfs_mkfs.c:290 #, c-format msgid "log sunit should not be used in conjunction with log su\n" msgstr "" #: .././mkfs/xfs_mkfs.c:820 #, c-format msgid "existing superblock read failed: %s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:826 #, c-format msgid "warning: could not read existing superblock, skip zeroing\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1137 #, c-format msgid "%s: Specify data sunit in 512-byte blocks, no unit suffix\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1153 #, c-format msgid "%s: Specify data swidth in 512-byte blocks, no unit suffix\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1180 #, c-format msgid "%s: Specify data sw as multiple of su, no unit suffix\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1417 #, c-format msgid "Specify log sunit in 512-byte blocks, no size suffix\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1726 #, c-format msgid "cannot specify both %s and -d name=%s\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1880 #, c-format msgid "warning: finobt not supported without CRC support, disabled.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1887 #, c-format msgid "warning: sparse inodes not supported without CRC support, disabled.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1908 #, c-format msgid "both -d agcount= and agsize= specified, use one or the other\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1914 #, c-format msgid "if -d file then -d name and -d size are required\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1951 #, c-format msgid "if -l file then -l name and -l size are required\n" msgstr "" #: .././mkfs/xfs_mkfs.c:1973 #, c-format msgid "if -r file then -r name and -r size are required\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2008 #, c-format msgid "rt extent size %s too large, maximum %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2014 #, c-format msgid "rt extent size %s too small, minimum %d\n" msgstr "" #: .././mkfs/xfs_mkfs.c:2567 #, c-format msgid "" "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3181 #, c-format msgid "blocksize not available yet.\n" msgstr "" #: .././mkfs/xfs_mkfs.c:3207 #, c-format msgid "" "Usage: %s\n" "/* blocksize */\t\t[-b log=n|size=num]\n" "/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx]\n" "/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n" "\t\t\t (sunit=value,swidth=value|su=num,sw=num|noalign),\n" "\t\t\t sectlog=n|sectsize=num\n" "/* force overwrite */\t[-f]\n" "/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n" "\t\t\t projid32bit=0|1,sparse=0|1]\n" "/* no discard */\t[-K]\n" "/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n" "\t\t\t sunit=value|su=num,sectlog=n|sectsize=num,\n" "\t\t\t lazy-count=0|1]\n" "/* label */\t\t[-L label (maximum 12 characters)]\n" "/* naming */\t\t[-n log=n|size=num,version=2|ci,ftype=0|1]\n" "/* no-op info only */\t[-N]\n" "/* prototype file */\t[-p fname]\n" "/* quiet */\t\t[-q]\n" "/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n" "/* sectorsize */\t[-s log=n|size=num]\n" "/* version */\t\t[-V]\n" "\t\t\tdevicename\n" " is required unless -d name=xxx is given.\n" " is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n" " xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n" " is xxx (512 byte blocks).\n" msgstr "" #: .././quota/edit.c:689 msgid "[-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name" msgstr "" #: .././quota/edit.c:697 .././quota/report.c:33 .././quota/report.c:647 msgid "[-gpu] [-f file]" msgstr "" #: .././quota/edit.c:704 .././quota/edit.c:712 msgid "[-bir] [-gpu] value -d|id|name" msgstr "" #: .././quota/edit.c:705 msgid "get/set quota enforcement timeouts" msgstr "" #: .././quota/free.c:371 msgid "[-bir] [-hn] [-f file]" msgstr "" #: .././quota/init.c:48 #, c-format msgid "Usage: %s [-V] [-x] [-p prog] [-c cmd]... [-d project]... [path]\n" msgstr "" #: .././quota/path.c:39 #, c-format msgid "%sFilesystem Pathname\n" msgstr "" #: .././quota/quot.c:419 msgid "[-bir] [-gpu] [-acv] [-f file]" msgstr "" #: .././quota/quota.c:464 msgid "[-bir] [-gpu] [-hnNv] [-f file] [id|name]..." msgstr "" #: .././quota/report.c:48 msgid "[-bir] [-gpu] [-ahntLNU] [-f file]" msgstr "" #: .././quota/report.c:51 #, c-format msgid "" "\n" " report used space and inodes, and quota limits, for a filesystem\n" " Example:\n" " 'report -igh'\n" " (reports inode usage for all groups, in an easy-to-read format)\n" " This command is the equivalent of the traditional repquota command, which\n" " prints a summary of the disk usage and quotas for the current filesystem,\n" " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -L -- lower ID bound to report on\n" " -U -- upper ID bound to report on\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" " -u -- report user usage and quota information\n" " -b -- report blocks-used information only\n" " -i -- report inodes-used information only\n" " -r -- report realtime-blocks-used information only\n" "\n" msgstr "" #: .././repair/phase5.c:1463 #, c-format msgid "lost %d blocks in ag %u\n" msgstr "" #: .././repair/phase5.c:1466 #, c-format msgid "thought we were going to lose %d blocks in ag %u, actually lost %d\n" msgstr "" #: .././repair/phase5.c:1685 #, c-format msgid "lost %d blocks in agno %d, sorry.\n" msgstr "" #: .././repair/versions.c:228 #, c-format msgid "" "WARNING: you have a V1 inode filesystem. It %s be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n" msgstr "" #: .././rtcp/xfs_rtcp.c:84 #, c-format msgid "%s: stat64 of %s failed\n" msgstr "" #: .././rtcp/xfs_rtcp.c:138 #, c-format msgid "%s: failed stat64 on %s: %s\n" msgstr "" xfsprogs-4.9.0+nmu1ubuntu2/quota/0000755000000000000000000000000013063067174013626 5ustar xfsprogs-4.9.0+nmu1ubuntu2/quota/Makefile0000644000000000000000000000154113063067172015265 0ustar # # Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_quota HFILES = init.h quota.h CFILES = init.c util.c \ edit.c free.c path.c project.c quot.c quota.c report.c state.c CFILES += $(PKG_PLATFORM).c PCFILES = darwin.c freebsd.c irix.c linux.c LSRCFILES = $(shell echo $(PCFILES) | sed -e "s/$(PKG_PLATFORM).c//g") LLDLIBS = $(LIBXCMD) LTDEPENDENCIES = $(LIBXCMD) LLDFLAGS = -static ifeq ($(ENABLE_READLINE),yes) LLDLIBS += $(LIBREADLINE) $(LIBTERMCAP) CFLAGS += -DENABLE_READLINE endif ifeq ($(ENABLE_EDITLINE),yes) LLDLIBS += $(LIBEDITLINE) $(LIBTERMCAP) CFLAGS += -DENABLE_EDITLINE endif default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/quota/darwin.c0000644000000000000000000000166513063067172015264 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "quota.h" #include int xfsquotactl( int command, const char *device, uint type, uint id, void *addr) { /* return quotactl(device, QCMD(command, type), id, addr); */ errno = -ENOSYS; return -1; } xfsprogs-4.9.0+nmu1ubuntu2/quota/edit.c0000644000000000000000000004164513063067172014727 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "input.h" #include "command.h" #include "init.h" #include "quota.h" static cmdinfo_t limit_cmd; static cmdinfo_t restore_cmd; static cmdinfo_t timer_cmd; static cmdinfo_t warn_cmd; static void limit_help(void) { printf(_( "\n" " modify quota limits for the specified user\n" "\n" " Example:\n" " 'limit bsoft=100m bhard=110m tanya\n" "\n" " Changes the soft and/or hard block limits, inode limits and/or realtime\n" " block limits that are currently being used for the specified user, group,\n" " or project. The filesystem identified by the current path is modified.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota limits\n" " -p -- modify project quota limits\n" " -u -- modify user quota limits\n" " The block limit values can be specified with a units suffix - accepted\n" " units are: k (kilobytes), m (megabytes), g (gigabytes), and t (terabytes).\n" " The user/group/project can be specified either by name or by number.\n" "\n")); } static void timer_help(void) { printf(_( "\n" " modify quota enforcement timeout for the current filesystem\n" "\n" " Example:\n" " 'timer -i 3days'\n" " (soft inode limit timer is changed to 3 days)\n" "\n" " Changes the timeout value associated with the block limits, inode limits\n" " and/or realtime block limits for all users, groups, or projects on the\n" " current filesystem.\n" " As soon as a user consumes the amount of space or number of inodes set as\n" " the soft limit, a timer is started. If the timer expires and the user is\n" " still over the soft limit, the soft limit is enforced as the hard limit.\n" " The default timeout is 7 days.\n" " -d -- set the default values, used the first time a file is created\n" " -g -- modify group quota timer\n" " -p -- modify project quota timer\n" " -u -- modify user quota timer\n" " -b -- modify the blocks-used timer\n" " -i -- modify the inodes-used timer\n" " -r -- modify the blocks-used timer for the (optional) realtime subvolume\n" " The timeout value is specified as a number of seconds, by default.\n" " However, a suffix may be used to alternatively specify minutes (m),\n" " hours (h), days (d), or weeks (w) - either the full word or the first\n" " letter of the word can be used.\n" "\n")); } static void warn_help(void) { printf(_( "\n" " modify the number of quota warnings sent to the specified user\n" "\n" " Example:\n" " 'warn 2 jimmy'\n" " (tell the quota system that two warnings have been sent to user jimmy)\n" "\n" " Changes the warning count associated with the block limits, inode limits\n" " and/or realtime block limits for the specified user, group, or project.\n" " When a user has been warned the maximum number of times allowed, the soft\n" " limit is enforced as the hard limit. It is intended as an alternative to\n" " the timeout system, where the system administrator updates a count of the\n" " number of warnings issued to people, and they are penalised if the warnings\n" " are ignored.\n" " -d -- set maximum warning count, which triggers soft limit enforcement\n" " -g -- set group quota warning count\n" " -p -- set project quota warning count\n" " -u -- set user quota warning count\n" " -b -- set the blocks-used warning count\n" " -i -- set the inodes-used warning count\n" " -r -- set the blocks-used warn count for the (optional) realtime subvolume\n" " The user/group/project can be specified either by name or by number.\n" "\n")); } static void set_limits( __uint32_t id, uint type, uint mask, char *dev, __uint64_t *bsoft, __uint64_t *bhard, __uint64_t *isoft, __uint64_t *ihard, __uint64_t *rtbsoft, __uint64_t *rtbhard) { fs_disk_quota_t d; memset(&d, 0, sizeof(d)); d.d_version = FS_DQUOT_VERSION; d.d_id = id; d.d_flags = type; d.d_fieldmask = mask; d.d_blk_hardlimit = *bhard; d.d_blk_softlimit = *bsoft; d.d_ino_hardlimit = *ihard; d.d_ino_softlimit = *isoft; d.d_rtb_hardlimit = *rtbhard; d.d_rtb_softlimit = *rtbsoft; if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot set limits: %s\n"), progname, strerror(errno)); } } static void set_user_limits( char *name, uint type, uint mask, __uint64_t *bsoft, __uint64_t *bhard, __uint64_t *isoft, __uint64_t *ihard, __uint64_t *rtbsoft, __uint64_t *rtbhard) { uid_t uid = uid_from_string(name); if (uid == -1) { exitcode = 1; fprintf(stderr, _("%s: invalid user name: %s\n"), progname, name); } else set_limits(uid, type, mask, fs_path->fs_name, bsoft, bhard, isoft, ihard, rtbsoft, rtbhard); } static void set_group_limits( char *name, uint type, uint mask, __uint64_t *bsoft, __uint64_t *bhard, __uint64_t *isoft, __uint64_t *ihard, __uint64_t *rtbsoft, __uint64_t *rtbhard) { gid_t gid = gid_from_string(name); if (gid == -1) { exitcode = 1; fprintf(stderr, _("%s: invalid group name: %s\n"), progname, name); } else set_limits(gid, type, mask, fs_path->fs_name, bsoft, bhard, isoft, ihard, rtbsoft, rtbhard); } static void set_project_limits( char *name, uint type, uint mask, __uint64_t *bsoft, __uint64_t *bhard, __uint64_t *isoft, __uint64_t *ihard, __uint64_t *rtbsoft, __uint64_t *rtbhard) { prid_t prid = prid_from_string(name); if (prid == -1) { exitcode = 1; fprintf(stderr, _("%s: invalid project name: %s\n"), progname, name); } else set_limits(prid, type, mask, fs_path->fs_name, bsoft, bhard, isoft, ihard, rtbsoft, rtbhard); } /* extract number of blocks from an ascii string */ static int extractb( char *string, const char *prefix, int length, uint blocksize, uint sectorsize, __uint64_t *value) { long long v; char *s = string; if (strncmp(string, prefix, length) == 0) { s = string + length + 1; v = cvtnum(blocksize, sectorsize, s); if (v == -1LL) { fprintf(stderr, _("%s: Error: could not parse size %s.\n"), progname, s); return 0; } *value = (__uint64_t)v >> 9; /* syscalls use basic blocks */ if (v > 0 && *value == 0) fprintf(stderr, _("%s: Warning: `%s' in quota blocks is 0 (unlimited).\n"), progname, s); return 1; } return 0; } /* extract number of inodes from an ascii string */ static int extracti( char *string, const char *prefix, int length, __uint64_t *value) { char *sp, *s = string; if (strncmp(string, prefix, length) == 0) { s = string + length + 1; *value = strtoll(s, &sp, 0); return 1; } return 0; } static int limit_f( int argc, char **argv) { char *name; __uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard; int c, type = 0, mask = 0, flags = 0; uint bsize, ssize, endoptions; init_cvtnum(&bsize, &ssize); bsoft = bhard = isoft = ihard = rtbsoft = rtbhard = 0; while ((c = getopt(argc, argv, "dgpu")) != EOF) { switch (c) { case 'd': flags |= DEFAULTS_FLAG; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; default: return command_usage(&limit_cmd); } } /* * In the usual case, we need at least 2 more arguments - * one (or more) limits and a user name/id. * For setting defaults (-d) we don't want a user name/id. */ if (flags & DEFAULTS_FLAG) { if (argc < optind + 1) return command_usage(&limit_cmd); endoptions = 1; } else if (argc < optind + 2) { return command_usage(&limit_cmd); } else { endoptions = 2; } /* * Extract limit values from remaining optional arguments. */ while (argc > optind + endoptions - 1) { char *s = argv[optind++]; if (extractb(s, "bsoft=", 5, bsize, ssize, &bsoft)) mask |= FS_DQ_BSOFT; else if (extractb(s, "bhard=", 5, bsize, ssize, &bhard)) mask |= FS_DQ_BHARD; else if (extracti(s, "isoft=", 5, &isoft)) mask |= FS_DQ_ISOFT; else if (extracti(s, "ihard=", 5, &ihard)) mask |= FS_DQ_IHARD; else if (extractb(s, "rtbsoft=", 7, bsize, ssize, &rtbsoft)) mask |= FS_DQ_RTBSOFT; else if (extractb(s, "rtbhard=", 7, bsize, ssize, &rtbhard)) mask |= FS_DQ_RTBHARD; else { exitcode = 1; fprintf(stderr, _("%s: unrecognised argument %s\n"), progname, s); return 0; } } if (!mask) { exitcode = 1; fprintf(stderr, _("%s: cannot find any valid arguments\n"), progname); return 0; } name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++]; if (!type) { type = XFS_USER_QUOTA; } else if (type != XFS_GROUP_QUOTA && type != XFS_PROJ_QUOTA && type != XFS_USER_QUOTA) { return command_usage(&limit_cmd); } switch (type) { case XFS_USER_QUOTA: set_user_limits(name, type, mask, &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); break; case XFS_GROUP_QUOTA: set_group_limits(name, type, mask, &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); break; case XFS_PROJ_QUOTA: set_project_limits(name, type, mask, &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); break; } return 0; } /* * Iterate through input file, restoring the limits. * File format is as follows: * fs = * bsoft bhard isoft ihard [rtbsoft rtbhard] */ static void restore_file( FILE *fp, uint type) { char buffer[512]; char devbuffer[512]; char *dev = NULL; uint mask; int cnt; __uint32_t id; __uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard; while (fgets(buffer, sizeof(buffer), fp) != NULL) { if (strncmp("fs = ", buffer, 5) == 0) { dev = strncpy(devbuffer, buffer+5, sizeof(devbuffer)); dev[strlen(dev) - 1] = '\0'; continue; } rtbsoft = rtbhard = 0; cnt = sscanf(buffer, "%u %llu %llu %llu %llu %llu %llu\n", &id, (unsigned long long *)&bsoft, (unsigned long long *)&bhard, (unsigned long long *)&isoft, (unsigned long long *)&ihard, (unsigned long long *)&rtbsoft, (unsigned long long *)&rtbhard); if (cnt == 5 || cnt == 7) { mask = FS_DQ_ISOFT|FS_DQ_IHARD|FS_DQ_BSOFT|FS_DQ_BHARD; if (cnt == 7) mask |= FS_DQ_RTBSOFT|FS_DQ_RTBHARD; set_limits(id, type, mask, dev, &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); } } } static int restore_f( int argc, char **argv) { FILE *fp = stdin; char *fname = NULL; int c, type = 0; while ((c = getopt(argc, argv, "f:gpu")) != EOF) { switch (c) { case 'f': fname = optarg; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; default: return command_usage(&restore_cmd); } } if (argc < optind) return command_usage(&restore_cmd); if (!type) { type = XFS_USER_QUOTA; } else if (type != XFS_GROUP_QUOTA && type != XFS_PROJ_QUOTA && type != XFS_USER_QUOTA) { return command_usage(&restore_cmd); } if (fname) { if ((fp = fopen(fname, "r")) == NULL) { exitcode = 1; fprintf(stderr, _("%s: fopen on %s failed: %s\n"), progname, fname, strerror(errno)); return 0; } } restore_file(fp, type); if (fname) fclose(fp); return 0; } static void set_timer( uint type, uint mask, char *dev, uint value) { fs_disk_quota_t d; memset(&d, 0, sizeof(d)); d.d_version = FS_DQUOT_VERSION; d.d_flags = type; d.d_fieldmask = mask; d.d_itimer = value; d.d_btimer = value; d.d_rtbtimer = value; if (xfsquotactl(XFS_SETQLIM, dev, type, 0, (void *)&d) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot set timer: %s\n"), progname, strerror(errno)); } } static int timer_f( int argc, char **argv) { uint value; int c, type = 0, mask = 0; while ((c = getopt(argc, argv, "bgipru")) != EOF) { switch (c) { case 'b': mask |= FS_DQ_BTIMER; break; case 'i': mask |= FS_DQ_ITIMER; break; case 'r': mask |= FS_DQ_RTBTIMER; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; default: return command_usage(&timer_cmd); } } if (argc != optind + 1) return command_usage(&timer_cmd); value = cvttime(argv[optind++]); if (!mask) mask = FS_DQ_TIMER_MASK; if (!type) { type = XFS_USER_QUOTA; } else if (type != XFS_GROUP_QUOTA && type != XFS_PROJ_QUOTA && type != XFS_USER_QUOTA) { return command_usage(&timer_cmd); } set_timer(type, mask, fs_path->fs_name, value); return 0; } static void set_warnings( __uint32_t id, uint type, uint mask, char *dev, uint value) { fs_disk_quota_t d; memset(&d, 0, sizeof(d)); d.d_version = FS_DQUOT_VERSION; d.d_id = id; d.d_flags = type; d.d_fieldmask = mask; d.d_iwarns = value; d.d_bwarns = value; d.d_rtbwarns = value; if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot set warnings: %s\n"), progname, strerror(errno)); } } static void set_user_warnings( char *name, uint type, uint mask, uint value) { uid_t uid = uid_from_string(name); if (uid == -1) { exitcode = 1; fprintf(stderr, _("%s: invalid user name: %s\n"), progname, name); } else set_warnings(uid, type, mask, fs_path->fs_name, value); } static void set_group_warnings( char *name, uint type, uint mask, uint value) { gid_t gid = gid_from_string(name); if (gid == -1) { exitcode = 1; fprintf(stderr, _("%s: invalid group name: %s\n"), progname, name); } else set_warnings(gid, type, mask, fs_path->fs_name, value); } static void set_project_warnings( char *name, uint type, uint mask, uint value) { prid_t prid = prid_from_string(name); if (prid == -1) { exitcode = 1; fprintf(stderr, _("%s: invalid project name: %s\n"), progname, name); } else set_warnings(prid, type, mask, fs_path->fs_name, value); } static int warn_f( int argc, char **argv) { char *name; uint value; int c, flags = 0, type = 0, mask = 0; while ((c = getopt(argc, argv, "bdgipru")) != EOF) { switch (c) { case 'd': flags |= DEFAULTS_FLAG; break; case 'b': mask |= FS_DQ_BWARNS; break; case 'i': mask |= FS_DQ_IWARNS; break; case 'r': mask |= FS_DQ_RTBWARNS; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; default: return command_usage(&warn_cmd); } } /* * In the usual case, we need at least 2 more arguments - * one (or more) value and a user name/id. * For setting defaults (-d) we don't want a user name/id. */ if (flags & DEFAULTS_FLAG) { if (argc != optind + 1) return command_usage(&warn_cmd); } else if (argc != optind + 2) { return command_usage(&warn_cmd); } value = atoi(argv[optind++]); name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++]; if (!mask) mask = FS_DQ_WARNS_MASK; if (!type) { type = XFS_USER_QUOTA; } else if (type != XFS_GROUP_QUOTA && type != XFS_PROJ_QUOTA && type != XFS_USER_QUOTA) { return command_usage(&warn_cmd); } switch (type) { case XFS_USER_QUOTA: set_user_warnings(name, type, mask, value); break; case XFS_GROUP_QUOTA: set_group_warnings(name, type, mask, value); break; case XFS_PROJ_QUOTA: set_project_warnings(name, type, mask, value); break; } return 0; } void edit_init(void) { limit_cmd.name = "limit"; limit_cmd.cfunc = limit_f; limit_cmd.argmin = 2; limit_cmd.argmax = -1; limit_cmd.args = \ _("[-g|-p|-u] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name"); limit_cmd.oneline = _("modify quota limits"); limit_cmd.help = limit_help; limit_cmd.flags = CMD_FLAG_FOREIGN_OK; restore_cmd.name = "restore"; restore_cmd.cfunc = restore_f; restore_cmd.argmin = 0; restore_cmd.argmax = -1; restore_cmd.args = _("[-g|-p|-u] [-f file]"); restore_cmd.oneline = _("restore quota limits from a backup file"); restore_cmd.flags = CMD_FLAG_FOREIGN_OK; timer_cmd.name = "timer"; timer_cmd.cfunc = timer_f; timer_cmd.argmin = 2; timer_cmd.argmax = -1; timer_cmd.args = _("[-bir] [-g|-p|-u] value"); timer_cmd.oneline = _("set quota enforcement timeouts"); timer_cmd.help = timer_help; timer_cmd.flags = CMD_FLAG_FOREIGN_OK; warn_cmd.name = "warn"; warn_cmd.cfunc = warn_f; warn_cmd.argmin = 2; warn_cmd.argmax = -1; warn_cmd.args = _("[-bir] [-g|-p|-u] value -d|id|name"); warn_cmd.oneline = _("get/set enforcement warning counter"); warn_cmd.help = warn_help; if (expert) { add_command(&limit_cmd); add_command(&restore_cmd); add_command(&timer_cmd); add_command(&warn_cmd); } } xfsprogs-4.9.0+nmu1ubuntu2/quota/free.c0000644000000000000000000002305313063067172014714 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "command.h" #include "init.h" #include "quota.h" static cmdinfo_t free_cmd; static void free_help(void) { printf(_( "\n" " reports the number of free disk blocks and inodes\n" "\n" " This command reports the number of total, used, and available disk blocks.\n" " It can optionally report the same set of numbers for inodes and realtime\n" " disk blocks, and will report on all known XFS filesystem mount points and\n" " project quota paths by default (see 'print' command for a list).\n" " -b -- report the block count values\n" " -i -- report the inode count values\n" " -r -- report the realtime block count values\n" " -h -- report in a human-readable format\n" " -N -- suppress the header from the output\n" "\n")); } /* * The data and realtime block counts returned (count, used, and * free) are all in basic block units. */ static int mount_free_space_data( struct fs_path *mount, __uint64_t *bcount, __uint64_t *bused, __uint64_t *bfree, __uint64_t *icount, __uint64_t *iused, __uint64_t *ifree, __uint64_t *rcount, __uint64_t *rused, __uint64_t *rfree) { struct xfs_fsop_counts fscounts; struct xfs_fsop_geom fsgeo; struct statfs st; __uint64_t logsize, count, free; int fd; if ((fd = open(mount->fs_dir, O_RDONLY)) < 0) { exitcode = 1; fprintf(stderr, "%s: cannot open %s: %s\n", progname, mount->fs_dir, strerror(errno)); return 0; } if (platform_fstatfs(fd, &st) < 0) { perror("fstatfs"); close(fd); return 0; } if (!(mount->fs_flags & FS_FOREIGN)) { if ((xfsctl(mount->fs_dir, fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) { perror("XFS_IOC_FSGEOMETRY_V1"); close(fd); return 0; } if ((xfsctl(mount->fs_dir, fd, XFS_IOC_FSCOUNTS, &fscounts)) < 0) { perror("XFS_IOC_FSCOUNTS"); close(fd); return 0; } logsize = fsgeo.logstart ? fsgeo.logblocks : 0; count = (fsgeo.datablocks - logsize) * fsgeo.blocksize; free = fscounts.freedata * fsgeo.blocksize; *bcount = BTOBB(count); *bfree = BTOBB(free); *bused = BTOBB(count - free); count = fsgeo.rtextents * fsgeo.rtextsize * fsgeo.blocksize; free = fscounts.freertx * fsgeo.rtextsize * fsgeo.blocksize; *rcount = BTOBB(count); *rfree = BTOBB(free); *rused = BTOBB(count - free); } else { count = st.f_blocks * st.f_bsize; free = st.f_bfree * st.f_bsize; *bcount = BTOBB(count); *bfree = BTOBB(free); *bused = BTOBB(count - free); *rcount = BTOBB(0); *rfree = BTOBB(0); *rused = BTOBB(0); } *icount = st.f_files; *ifree = st.f_ffree; *iused = st.f_files - st.f_ffree; close(fd); return 1; } /* * The data and realtime block counts returned (count, used, and * free) are all in basic block units. */ static int projects_free_space_data( struct fs_path *path, __uint64_t *bcount, __uint64_t *bused, __uint64_t *bfree, __uint64_t *icount, __uint64_t *iused, __uint64_t *ifree, __uint64_t *rcount, __uint64_t *rused, __uint64_t *rfree) { fs_quota_stat_t qfs; fs_disk_quota_t d; struct fsxattr fsx; uint type = XFS_PROJ_QUOTA; char *dev = path->fs_name; int fd; if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, &qfs) < 0 || !(qfs.qs_flags & XFS_QUOTA_PDQ_ACCT)) return 0; if ((fd = open(path->fs_dir, O_RDONLY)) < 0) { exitcode = 1; fprintf(stderr, "%s: cannot open %s: %s\n", progname, path->fs_dir, strerror(errno)); return 0; } if ((xfsctl(path->fs_dir, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { exitcode = 1; perror("FS_IOC_FSGETXATTR"); close(fd); return 0; } if (!(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT)) { exitcode = 1; fprintf(stderr, _("%s: project quota flag not set on %s\n"), progname, path->fs_dir); close(fd); return 0; } if (path->fs_prid != fsx.fsx_projid) { exitcode = 1; fprintf(stderr, _("%s: project ID %u (%s) doesn't match ID %u (%s)\n"), progname, path->fs_prid, projects_file, fsx.fsx_projid, path->fs_dir); close(fd); return 0; } xfsquotactl(XFS_QSYNC, dev, type, fsx.fsx_projid, NULL); if (xfsquotactl(XFS_GETQUOTA, dev, type, fsx.fsx_projid, &d) < 0) { perror("XFS_GETQUOTA"); close(fd); return 0; } /* If no softlimit is set for any of blk/ino/rt, get actual usage */ if (!d.d_blk_softlimit || !d.d_ino_softlimit || !d.d_rtb_softlimit) { mount_free_space_data(path, bcount, bused, bfree, icount, iused, ifree, rcount, rused, rfree); } if (d.d_blk_softlimit) { *bcount = d.d_blk_softlimit; *bfree = (d.d_blk_softlimit - d.d_bcount); } *bused = d.d_bcount; if (d.d_ino_softlimit) { *icount = d.d_ino_softlimit; *ifree = (d.d_ino_softlimit - d.d_icount); } *iused = d.d_icount; if (d.d_rtb_softlimit) { *rcount = d.d_rtb_softlimit; *rfree = (d.d_rtb_softlimit - d.d_rtbcount); } *rused = d.d_rtbcount; close(fd); return 1; } static int free_space( FILE *fp, uint form, fs_path_t *path, uint flags) { __uint64_t bcount, bused, bfree; __uint64_t icount, iused, ifree; __uint64_t rcount, rused, rfree; char a[8], s[8], u[8], p[8]; int count; count = (path->fs_flags & FS_PROJECT_PATH) ? projects_free_space_data(path, &bcount, &bused, &bfree, &icount, &iused, &ifree, &rcount, &rused, &rfree) : mount_free_space_data(path, &bcount, &bused, &bfree, &icount, &iused, &ifree, &rcount, &rused, &rfree); if (!count) return 0; if (!(flags & NO_HEADER_FLAG)) { fprintf(fp, (flags & HUMAN_FLAG) ? _("Filesystem ") : _("Filesystem ")); if (form & (XFS_BLOCK_QUOTA|XFS_RTBLOCK_QUOTA)) fprintf(fp, (flags & HUMAN_FLAG) ? _(" Size Used Avail Use%%") : _(" 1K-blocks Used Available Use%%")); else if (form & XFS_INODE_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? _(" Inodes Used Free Use%%") : _(" Inodes IUsed IFree IUse%%")); fprintf(fp, _(" Pathname\n")); } if (flags & HUMAN_FLAG) { count = fprintf(fp, "%-12s", path->fs_name); if (count > 13) fprintf(fp, "\n%12s", " "); } else { count = fprintf(fp, "%-19s", path->fs_name); if (count > 20) fprintf(fp, "\n%19s", " "); } if (form & XFS_BLOCK_QUOTA) { if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %3s%%", bbs_to_string(bcount, s, sizeof(s)), bbs_to_string(bused, u, sizeof(u)), bbs_to_string(bfree, a, sizeof(a)), pct_to_string(bused, bcount, p, sizeof(p))); else fprintf(fp, " %10llu %10llu %10llu %3s%%", (unsigned long long)bcount >> 1, (unsigned long long)bused >> 1, (unsigned long long)bfree >> 1, pct_to_string(bused, bcount, p, sizeof(p))); } else if (form & XFS_INODE_QUOTA) { if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %3s%%", num_to_string(icount, s, sizeof(s)), num_to_string(iused, u, sizeof(u)), num_to_string(ifree, a, sizeof(a)), pct_to_string(iused, icount, p, sizeof(p))); else fprintf(fp, " %10llu %10llu %10llu %3s%%", (unsigned long long)icount, (unsigned long long)iused, (unsigned long long)ifree, pct_to_string(iused, icount, p, sizeof(p))); } else if (form & XFS_RTBLOCK_QUOTA) { if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %3s%%", bbs_to_string(rcount, s, sizeof(s)), bbs_to_string(rused, u, sizeof(u)), bbs_to_string(rfree, a, sizeof(a)), pct_to_string(rused, rcount, p, sizeof(p))); else fprintf(fp, " %10llu %10llu %10llu %3s%%", (unsigned long long)rcount >> 1, (unsigned long long)rused >> 1, (unsigned long long)rfree >> 1, pct_to_string(rused, rcount, p, sizeof(p))); } fprintf(fp, " %s\n", path->fs_dir); return 1; } static void free_space_list( FILE *fp, uint form, char *dir, uint flags) { fs_cursor_t cursor; fs_path_t *path; fs_cursor_initialise(dir, 0, &cursor); while ((path = fs_cursor_next_entry(&cursor))) { if (free_space(fp, form, path, flags)) flags |= NO_HEADER_FLAG; } } static int free_f( int argc, char **argv) { FILE *fp = NULL; char *fname = NULL; int c, flags = 0, form = 0; while ((c = getopt(argc, argv, "bf:hNir")) != EOF) { switch (c) { case 'f': fname = optarg; break; case 'b': form |= XFS_BLOCK_QUOTA; break; case 'i': form |= XFS_INODE_QUOTA; break; case 'r': form |= XFS_RTBLOCK_QUOTA; break; case 'h': flags |= HUMAN_FLAG; break; case 'N': flags |= NO_HEADER_FLAG; break; default: return command_usage(&free_cmd); } } if (!form) form = XFS_BLOCK_QUOTA; if ((fp = fopen_write_secure(fname)) == NULL) return 0; if (argc == optind) free_space_list(fp, form, NULL, flags); else while (argc > optind) free_space_list(fp, form, argv[optind++], flags); if (fname) fclose(fp); return 0; } void free_init(void) { free_cmd.name = "df"; free_cmd.altname = "free"; free_cmd.cfunc = free_f; free_cmd.argmin = 0; free_cmd.argmax = -1; free_cmd.args = _("[-bir] [-hN] [-f file]"); free_cmd.oneline = _("show free and used counts for blocks and inodes"); free_cmd.help = free_help; free_cmd.flags = CMD_FLAG_FOREIGN_OK; add_command(&free_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/quota/freebsd.c0000644000000000000000000000153713063067172015410 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "quota.h" int xfsquotactl( int command, const char *device, uint type, uint id, void *addr) { errno = -ENOSYS; return -1; } xfsprogs-4.9.0+nmu1ubuntu2/quota/init.c0000644000000000000000000001041513063067172014734 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "path.h" #include "command.h" #include "input.h" #include "init.h" char *progname; int exitcode; int expert; bool foreign_allowed = false; static char **projopts; /* table of project names (cmdline) */ static int nprojopts; /* number of entries in name table. */ static void add_project_opt( char *optarg) { nprojopts++; projopts = realloc(projopts, sizeof(char*) * nprojopts); if (!projopts) { perror("realloc"); exit(1); } projopts[nprojopts - 1] = optarg; } static void usage(void) { fprintf(stderr, _("Usage: %s [-V] [-x] [-f] [-p prog] [-c cmd]... [-d project]... [path]\n"), progname); exit(1); } void init_cvtnum( unsigned int *blocksize, unsigned int *sectsize) { *blocksize = 4096; *sectsize = 512; } static void init_commands(void) { edit_init(); free_init(); help_init(); path_init(); project_init(); quot_init(); quota_init(); quit_init(); report_init(); state_init(); } static int init_args_command( int index) { if (index >= fs_count) return 0; do { fs_path = &fs_table[index++]; /* skip project quota entries */ if ((fs_path->fs_flags & FS_PROJECT_PATH)) continue; /* only consider foreign filesystems if told so */ if (!foreign_allowed && (fs_path->fs_flags & FS_FOREIGN)) continue; /* We can use this one */ break; } while (index < fs_count); if (fs_path->fs_flags & FS_PROJECT_PATH) return 0; if (!foreign_allowed && (fs_path->fs_flags & FS_FOREIGN)) return 0; if (index > fs_count) return 0; return index; } static int init_check_command( const cmdinfo_t *ct) { if (!fs_path) return 1; /* Always run commands that are valid for all fs types. */ if (ct->flags & CMD_ALL_FSTYPES) return 1; /* If it's an XFS filesystem, always run the command. */ if (!(fs_path->fs_flags & FS_FOREIGN)) return 1; /* If the user specified foreign filesystems are ok (-f), run cmd. */ if (foreign_allowed && (ct->flags & CMD_FLAG_FOREIGN_OK)) return 1; /* If cmd not allowed on foreign fs, regardless of -f flag, skip it. */ if (!(ct->flags & CMD_FLAG_FOREIGN_OK)) { fprintf(stderr, _("%s: command is for XFS filesystems only\n"), ct->name); return 0; } /* foreign fs, but cmd only allowed via -f flag. Skip it. */ fprintf(stderr, _("%s: foreign filesystem. Invoke xfs_quota with -f to enable.\n"), ct->name); return 0; } static void init( int argc, char **argv) { int c; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((c = getopt(argc, argv, "c:d:D:fP:p:t:xV")) != EOF) { switch (c) { case 'c': /* commands */ add_user_command(optarg); break; case 'd': add_project_opt(optarg); break; case 'f': foreign_allowed = true; break; case 't': mtab_file = optarg; break; case 'D': projects_file = optarg; break; case 'P': projid_file = optarg; break; case 'p': progname = optarg; break; case 'x': expert++; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); default: usage(); } } fs_table_initialise(argc - optind, &argv[optind], nprojopts, projopts); free(projopts); init_commands(); add_args_command(init_args_command); add_check_command(init_check_command); /* * Ensure that global commands don't end up with an invalid path pointer * by setting the default device at the first specified on the CLI */ if (argc != optind) fs_path = fs_table_lookup(argv[optind], FS_MOUNT_POINT); else fs_path = &fs_table[0]; } int main( int argc, char **argv) { init(argc, argv); command_loop(); return exitcode; } xfsprogs-4.9.0+nmu1ubuntu2/quota/init.h0000644000000000000000000000223313063067172014740 0ustar /* * Copyright (c) 2003-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ extern char *progname; extern int exitcode; extern int expert; extern bool foreign_allowed; extern void edit_init(void); extern void free_init(void); extern void path_init(void); extern void project_init(void); extern void quot_init(void); extern void quota_init(void); extern void report_init(void); extern void state_init(void); extern void init_cvtnum(unsigned int *, unsigned int *); #define CMD_ALL_FSTYPES (1<<0) /* command is always available */ xfsprogs-4.9.0+nmu1ubuntu2/quota/irix.c0000644000000000000000000000304513063067172014745 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "quota.h" #include static int xcommand_to_qcommand( uint command, uint type) { switch (command) { case XFS_QUOTAON: return Q_XQUOTAON; case XFS_QUOTAOFF: return Q_XQUOTAOFF; case XFS_GETQUOTA: if (type == XFS_GROUP_QUOTA) return Q_XGETGQUOTA; if (type == XFS_PROJ_QUOTA) return Q_XGETPQUOTA; return Q_XGETQUOTA; case XFS_SETQLIM: if (type == XFS_GROUP_QUOTA) return Q_XSETGQLIM; if (type == XFS_PROJ_QUOTA) return Q_XSETPQLIM; return Q_XSETQLIM; case XFS_GETQSTAT: return Q_XGETQSTAT; case XFS_QUOTARM: return Q_XQUOTARM; case XFS_QSYNC: return Q_SYNC; } return 0; } int xfsquotactl( int command, const char *device, uint type, uint id, void *addr) { int qcommand; qcommand = xcommand_to_qcommand(command, type); return quotactl(qcommand, (char *)device, id, addr); } xfsprogs-4.9.0+nmu1ubuntu2/quota/linux.c0000644000000000000000000000327613063067172015137 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "quota.h" #include #ifndef PRJQUOTA #define PRJQUOTA 2 #endif static int xtype_to_qtype( uint type) { switch (type) { case XFS_USER_QUOTA: return USRQUOTA; case XFS_GROUP_QUOTA: return GRPQUOTA; case XFS_PROJ_QUOTA: return PRJQUOTA; } return 0; } static int xcommand_to_qcommand( uint command) { switch (command) { case XFS_QUOTAON: return Q_XQUOTAON; case XFS_QUOTAOFF: return Q_XQUOTAOFF; case XFS_GETQUOTA: return Q_XGETQUOTA; case XFS_GETNEXTQUOTA: return Q_XGETNEXTQUOTA; case XFS_SETQLIM: return Q_XSETQLIM; case XFS_GETQSTAT: return Q_XGETQSTAT; case XFS_GETQSTATV: return Q_XGETQSTATV; case XFS_QUOTARM: return Q_XQUOTARM; case XFS_QSYNC: return Q_XQUOTASYNC; } return 0; } int xfsquotactl( int command, const char *device, uint type, uint id, void *addr) { int qcommand, qtype; qtype = xtype_to_qtype(type); qcommand = xcommand_to_qcommand(command); return quotactl(QCMD(qcommand, qtype), device, id, addr); } xfsprogs-4.9.0+nmu1ubuntu2/quota/path.c0000644000000000000000000000731513063067172014732 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "quota.h" static cmdinfo_t path_cmd; static cmdinfo_t print_cmd; static void printpath( struct fs_path *path, int index, int number, int braces) { fs_quota_stat_t qstat; fs_project_t *prj; int c; if (index == 0) { printf(_("%s%sFilesystem Pathname\n"), number ? _(" ") : "", foreign_allowed ? _(" ") : ""); } if (number) printf(_("%c%03d%c "), braces? '[':' ', index, braces? ']':' '); if (foreign_allowed) printf("%s", (path->fs_flags & FS_FOREIGN) ? "(F) " : " "); printf(_("%-19s %s"), path->fs_dir, path->fs_name); if (path->fs_flags & FS_PROJECT_PATH) { prj = getprprid(path->fs_prid); printf(_(" (project %u"), path->fs_prid); if (prj) printf(_(", %s"), prj->pr_name); printf(")"); } else if (xfsquotactl(XFS_GETQSTAT, path->fs_name, 0, 0, (void *)&qstat) == 0 && qstat.qs_flags) { c = 0; printf(" ("); if (qstat.qs_flags & XFS_QUOTA_UDQ_ENFD) c = printf("uquota"); else if (qstat.qs_flags & XFS_QUOTA_UDQ_ACCT) c = printf("uqnoenforce"); if (qstat.qs_flags & XFS_QUOTA_GDQ_ENFD) c = printf("%sgquota", c ? ", " : ""); else if (qstat.qs_flags & XFS_QUOTA_GDQ_ACCT) c = printf("%sgqnoenforce", c ? ", " : ""); if (qstat.qs_flags & XFS_QUOTA_PDQ_ENFD) printf("%spquota", c ? ", " : ""); else if (qstat.qs_flags & XFS_QUOTA_PDQ_ACCT) printf("%spqnoenforce", c ? ", " : ""); printf(")"); } printf("\n"); } static int pathlist_f(void) { int i; struct fs_path *path; for (i = 0; i < fs_count; i++) { path = &fs_table[i]; /* Table is ordered xfs first, then foreign */ if (path->fs_flags & FS_FOREIGN && !foreign_allowed) break; printpath(path, i, 1, path == fs_path); } return 0; } static int print_f( int argc, char **argv) { int i; struct fs_path *path; for (i = 0; i < fs_count; i++) { path = &fs_table[i]; if (path->fs_flags & FS_FOREIGN && !foreign_allowed) break; printpath(path, i, 0, 0); } return 0; } static int path_f( int argc, char **argv) { int i; int max = foreign_allowed ? fs_count : xfs_fs_count; if (fs_count == 0) { printf(_("No paths are available\n")); return 0; } if (argc <= 1) return pathlist_f(); i = atoi(argv[1]); if (i < 0 || i >= max) { printf(_("value %d is out of range (0-%d)\n"), i, max - 1); } else { fs_path = &fs_table[i]; pathlist_f(); } return 0; } void path_init(void) { path_cmd.name = "path"; path_cmd.altname = "paths"; path_cmd.args = _("[N]"); path_cmd.cfunc = path_f; path_cmd.argmin = 0; path_cmd.argmax = 1; path_cmd.flags = CMD_FLAG_GLOBAL | CMD_FLAG_FOREIGN_OK; path_cmd.oneline = _("set current path, or show the list of paths"); print_cmd.name = "print"; print_cmd.altname = "p"; print_cmd.cfunc = print_f; print_cmd.argmin = 0; print_cmd.argmax = 0; print_cmd.flags = CMD_FLAG_GLOBAL | CMD_FLAG_FOREIGN_OK; print_cmd.oneline = _("list known mount points and projects"); if (expert) add_command(&path_cmd); add_command(&print_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/quota/project.c0000644000000000000000000002323713063067172015445 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" #include "input.h" #include "init.h" #include "quota.h" static cmdinfo_t project_cmd; static prid_t prid; static int recurse_depth = -1; enum { CHECK_PROJECT = 0x1, SETUP_PROJECT = 0x2, CLEAR_PROJECT = 0x4, }; #define EXCLUDED_FILE_TYPES(x) \ (S_ISCHR((x)) \ || S_ISBLK((x)) \ || S_ISFIFO((x)) \ || S_ISLNK((x)) \ || S_ISSOCK((x))) static void project_help(void) { printf(_( "\n" " list projects or setup a project tree for tree quota management\n" "\n" " Example:\n" " 'project -c logfiles'\n" " (match project 'logfiles' to a directory, and setup the directory tree)\n" "\n" " Without arguments, report all projects found in the /etc/projects file.\n" " The project quota mechanism in XFS can be used to implement a form of\n" " directory tree quota, where a specified directory and all of the files\n" " and subdirectories below it (i.e. a tree) can be restricted to using a\n" " subset of the available space in the filesystem.\n" "\n" " A managed tree must be setup initially using the -c option with a project.\n" " The specified project name or identifier is matched to one or more trees\n" " defined in /etc/projects, and these trees are then recursively descended\n" " to mark the affected inodes as being part of that tree - which sets inode\n" " flags and the project identifier on every file.\n" " Once this has been done, new files created in the tree will automatically\n" " be accounted to the tree based on their project identifier. An attempt to\n" " create a hard link to a file in the tree will only succeed if the project\n" " identifier matches the project identifier for the tree. The xfs_io utility\n" " can be used to set the project ID for an arbitrary file, but this can only\n" " be done by a privileged user.\n" "\n" " A previously setup tree can be cleared from project quota control through\n" " use of the -C option, which will recursively descend the tree, clearing\n" " the affected inodes from project quota control.\n" "\n" " The -c option can be used to check whether a tree is setup, it reports\n" " nothing if the tree is correct, otherwise it reports the paths of inodes\n" " which do not have the project ID of the rest of the tree, or if the inode\n" " flag is not set.\n" "\n" " The -p option can be used to manually specify project path without\n" " need to create /etc/projects file. This option can be used multiple times\n" " to specify multiple paths. When using this option only one projid/name can\n" " be specified at command line. Note that /etc/projects is also used if exists.\n" "\n" " The -d option allows to descend at most levels of directories\n" " below the command line arguments. -d 0 means only apply the actions\n" " to the top level of the projects. -d -1 means no recursion limit (default).\n" "\n" " The /etc/projid and /etc/projects file formats are simple, and described\n" " on the xfs_quota man page.\n" "\n")); } static int check_project( const char *path, const struct stat *stat, int flag, struct FTW *data) { struct fsxattr fsx; int fd; if (recurse_depth >= 0 && data->level > recurse_depth) return -1; if (flag == FTW_NS ){ exitcode = 1; fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path); return 0; } if (EXCLUDED_FILE_TYPES(stat->st_mode)) { fprintf(stderr, _("%s: skipping special file %s\n"), progname, path); return 0; } if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) { exitcode = 1; fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); } else if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot get flags on %s: %s\n"), progname, path, strerror(errno)); } else { if (fsx.fsx_projid != prid) printf(_("%s - project identifier is not set" " (inode=%u, tree=%u)\n"), path, fsx.fsx_projid, (unsigned int)prid); if (!(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT)) printf(_("%s - project inheritance flag is not set\n"), path); } if (fd != -1) close(fd); return 0; } static int clear_project( const char *path, const struct stat *stat, int flag, struct FTW *data) { struct fsxattr fsx; int fd; if (recurse_depth >= 0 && data->level > recurse_depth) return -1; if (flag == FTW_NS ){ exitcode = 1; fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path); return 0; } if (EXCLUDED_FILE_TYPES(stat->st_mode)) { fprintf(stderr, _("%s: skipping special file %s\n"), progname, path); return 0; } if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) { exitcode = 1; fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); return 0; } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot get flags on %s: %s\n"), progname, path, strerror(errno)); close(fd); return 0; } fsx.fsx_projid = 0; fsx.fsx_xflags &= ~FS_XFLAG_PROJINHERIT; if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot clear project on %s: %s\n"), progname, path, strerror(errno)); } close(fd); return 0; } static int setup_project( const char *path, const struct stat *stat, int flag, struct FTW *data) { struct fsxattr fsx; int fd; if (recurse_depth >= 0 && data->level > recurse_depth) return -1; if (flag == FTW_NS ){ exitcode = 1; fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path); return 0; } if (EXCLUDED_FILE_TYPES(stat->st_mode)) { fprintf(stderr, _("%s: skipping special file %s\n"), progname, path); return 0; } if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) { exitcode = 1; fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); return 0; } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot get flags on %s: %s\n"), progname, path, strerror(errno)); close(fd); return 0; } fsx.fsx_projid = prid; fsx.fsx_xflags |= FS_XFLAG_PROJINHERIT; if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) { exitcode = 1; fprintf(stderr, _("%s: cannot set project on %s: %s\n"), progname, path, strerror(errno)); } close(fd); return 0; } static void project_operations( char *project, char *dir, int type) { switch (type) { case CHECK_PROJECT: printf(_("Checking project %s (path %s)...\n"), project, dir); nftw(dir, check_project, 100, FTW_PHYS|FTW_MOUNT); break; case SETUP_PROJECT: printf(_("Setting up project %s (path %s)...\n"), project, dir); nftw(dir, setup_project, 100, FTW_PHYS|FTW_MOUNT); break; case CLEAR_PROJECT: printf(_("Clearing project %s (path %s)...\n"), project, dir); nftw(dir, clear_project, 100, FTW_PHYS|FTW_MOUNT); break; } } static void project( char *project, int type) { fs_cursor_t cursor; fs_path_t *path; int count = 0; fs_cursor_initialise(NULL, FS_PROJECT_PATH, &cursor); while ((path = fs_cursor_next_entry(&cursor))) { if (prid != path->fs_prid && path->fs_prid != -1) continue; project_operations(project, path->fs_dir, type); count++; } printf(_("Processed %d (%s and cmdline) paths for project %s with " "recursion depth %s (%d).\n"), count, projects_file, project, recurse_depth < 0 ? _("infinite") : _("limited"), recurse_depth); } static int project_f( int argc, char **argv) { int c, type = 0, ispath = 0; while ((c = getopt(argc, argv, "cd:p:sC")) != EOF) { switch (c) { case 'c': type = CHECK_PROJECT; break; case 'd': recurse_depth = atoi(optarg); if (recurse_depth < 0) recurse_depth = -1; break; case 'p': ispath = 1; fs_table_insert_project_path(optarg, -1); break; case 's': type = SETUP_PROJECT; break; case 'C': type = CLEAR_PROJECT; break; default: return command_usage(&project_cmd); } } if (argc == optind) return command_usage(&project_cmd); /* no options - just check the given projects */ if (!type) type = CHECK_PROJECT; setprfiles(); if (!ispath && access(projects_file, F_OK) != 0) { exitcode = 1; fprintf(stderr, _("projects file \"%s\" doesn't exist\n"), projects_file); return 0; } if (ispath && argc - optind > 1) { exitcode = 1; fprintf(stderr, _("%s: only one projid/name can be specified " "when using -p , %d found.\n"), progname, argc - optind); return 0; } while (argc > optind) { prid = prid_from_string(argv[optind]); if (prid == -1) { exitcode = 1; fprintf(stderr, _("%s - no such project in %s " "or invalid project number\n"), argv[optind], projects_file); } else project(argv[optind], type); optind++; } return 0; } void project_init(void) { project_cmd.name = "project"; project_cmd.altname = "tree"; project_cmd.cfunc = project_f; project_cmd.args = _("[-c|-s|-C|-d |-p ] project ..."); project_cmd.argmin = 1; project_cmd.argmax = -1; project_cmd.oneline = _("check, setup or clear project quota trees"); project_cmd.help = project_help; project_cmd.flags = CMD_FLAG_FOREIGN_OK; if (expert) add_command(&project_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/quota/quot.c0000644000000000000000000002225513063067172014766 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "command.h" #include #include #include #include "init.h" #include "quota.h" typedef struct du { struct du *next; __uint64_t blocks; __uint64_t blocks30; __uint64_t blocks60; __uint64_t blocks90; __uint64_t nfiles; __uint32_t id; } du_t; #define TSIZE 500 static __uint64_t sizes[TSIZE]; static __uint64_t overflow; #define NDU 60000 #define DUHASH 8209 static du_t du[3][NDU]; static du_t *duhash[3][DUHASH]; static int ndu[3]; /* #usr/grp/prj */ #define NBSTAT 4069 static time_t now; static cmdinfo_t quot_cmd; static void quot_help(void) { printf(_( "\n" " display a summary of filesystem ownership\n" "\n" " -a -- summarise for all local XFS filesystem mount points\n" " -c -- display three columns giving file size in kilobytes, number of files\n" " of that size, and cumulative total of kilobytes in that size or\n" " smaller file. The last row is used as an overflow bucket and is the\n" " total of all files greater than 500 kilobytes.\n" " -v -- display three columns containing the number of kilobytes not\n" " accessed in the last 30, 60, and 90 days.\n" " -g -- display group summary\n" " -p -- display project summary\n" " -u -- display user summary\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n")); } static void quot_bulkstat_add( xfs_bstat_t *p, uint flags) { du_t *dp; du_t **hp; __uint64_t size; __uint32_t i, id; if ((p->bs_mode & S_IFMT) == 0) return; size = howmany((p->bs_blocks * p->bs_blksize), 0x400ULL); if (flags & HISTOGRAM_FLAG) { if (!(S_ISDIR(p->bs_mode) || S_ISREG(p->bs_mode))) return; if (size >= TSIZE) { overflow += size; size = TSIZE - 1; } sizes[(int)size]++; return; } for (i = 0; i < 3; i++) { id = (i == 0) ? p->bs_uid : ((i == 1) ? p->bs_gid : bstat_get_projid(p)); hp = &duhash[i][id % DUHASH]; for (dp = *hp; dp; dp = dp->next) if (dp->id == id) break; if (dp == NULL) { if (ndu[i] >= NDU) return; dp = &du[i][(ndu[i]++)]; dp->next = *hp; *hp = dp; dp->id = id; dp->nfiles = 0; dp->blocks = 0; dp->blocks30 = 0; dp->blocks60 = 0; dp->blocks90 = 0; } dp->blocks += size; if (now - p->bs_atime.tv_sec > 30 * (60*60*24)) dp->blocks30 += size; if (now - p->bs_atime.tv_sec > 60 * (60*60*24)) dp->blocks60 += size; if (now - p->bs_atime.tv_sec > 90 * (60*60*24)) dp->blocks90 += size; dp->nfiles++; } } static void quot_bulkstat_mount( char *fsdir, uint flags) { xfs_fsop_bulkreq_t bulkreq; xfs_bstat_t *buf; __u64 last = 0; __s32 count; int i, sts, fsfd; du_t **dp; /* * Initialize tables between checks; because of the qsort * in report() the hash tables must be rebuilt each time. */ for (sts = 0; sts < TSIZE; sts++) sizes[sts] = 0; overflow = 0; for (i = 0; i < 3; i++) for (dp = duhash[i]; dp < &duhash[i][DUHASH]; dp++) *dp = NULL; ndu[0] = ndu[1] = ndu[2] = 0; fsfd = open(fsdir, O_RDONLY); if (fsfd < 0) { perror(fsdir); return; } buf = (xfs_bstat_t *)calloc(NBSTAT, sizeof(xfs_bstat_t)); if (!buf) { perror("calloc"); close(fsfd); return; } bulkreq.lastip = &last; bulkreq.icount = NBSTAT; bulkreq.ubuffer = buf; bulkreq.ocount = &count; while ((sts = xfsctl(fsdir, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) { if (count == 0) break; for (i = 0; i < count; i++) quot_bulkstat_add(&buf[i], flags); } if (sts < 0) perror("XFS_IOC_FSBULKSTAT"), free(buf); close(fsfd); } static int qcompare( du_t *p1, du_t *p2) { if (p1->blocks > p2->blocks) return -1; if (p1->blocks < p2->blocks) return 1; if (p1->id > p2->id) return 1; else if (p1->id < p2->id) return -1; return 0; } typedef char *(*idtoname_t)(__uint32_t); static void quot_report_mount_any_type( FILE *fp, du_t *dp, int count, idtoname_t names, uint form, uint type, fs_path_t *mount, uint flags) { char *cp; fprintf(fp, _("%s (%s) %s:\n"), mount->fs_name, mount->fs_dir, type_to_string(type)); qsort(dp, count, sizeof(dp[0]), (int (*)(const void *, const void *))qcompare); for (; dp < &dp[count]; dp++) { if (dp->blocks == 0) return; fprintf(fp, "%8llu ", (unsigned long long) dp->blocks); if (form & XFS_INODE_QUOTA) fprintf(fp, "%8llu ", (unsigned long long) dp->nfiles); if (!(flags & NO_LOOKUP_FLAG) && ((cp = (names)(dp->id)) != NULL)) fprintf(fp, "%-8.8s", cp); else fprintf(fp, "#%-7d", dp->id); if (flags & VERBOSE_FLAG) fprintf(fp, " %8llu %8llu %8llu", (unsigned long long) dp->blocks30, (unsigned long long) dp->blocks60, (unsigned long long) dp->blocks90); fputc('\n', fp); } } static void quot_report_mount( FILE *fp, uint form, uint type, fs_path_t *mount, uint flags) { switch (type) { case XFS_GROUP_QUOTA: quot_report_mount_any_type(fp, du[1], ndu[1], gid_to_name, form, type, mount, flags); break; case XFS_PROJ_QUOTA: quot_report_mount_any_type(fp, du[2], ndu[2], prid_to_name, form, type, mount, flags); break; case XFS_USER_QUOTA: quot_report_mount_any_type(fp, du[0], ndu[0], uid_to_name, form, type, mount, flags); } } static void quot_report( FILE *fp, uint form, uint type, char *dir, uint flags) { fs_cursor_t cursor; fs_path_t *mount; now = time(NULL); fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) { quot_bulkstat_mount(mount->fs_dir, flags); quot_report_mount(fp, form, type, mount, flags); } } static void quot_histogram_mount( FILE *fp, fs_path_t *mount, uint flags) { __uint64_t t = 0; int i; fprintf(fp, _("%s (%s):\n"), mount->fs_name, mount->fs_dir); for (i = 0; i < TSIZE - 1; i++) if (sizes[i] > 0) { t += sizes[i] * i; fprintf(fp, _("%d\t%llu\t%llu\n"), i, (unsigned long long) sizes[i], (unsigned long long) t); } fprintf(fp, _("%d\t%llu\t%llu\n"), TSIZE - 1, (unsigned long long) sizes[TSIZE - 1], (unsigned long long) (overflow + t)); } static void quot_histogram( FILE *fp, char *dir, uint flags) { fs_cursor_t cursor; fs_path_t *mount; fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) { quot_bulkstat_mount(mount->fs_dir, flags); quot_histogram_mount(fp, mount, flags); } } static void quot_any_type( FILE *fp, uint form, uint type, char *dir, uint flags) { if (flags & HISTOGRAM_FLAG) quot_histogram(fp, dir, flags); else quot_report(fp, form, type, dir, flags); } static int quot_f( int argc, char **argv) { FILE *fp = NULL; char *fname = NULL; int c, flags = 0, type = 0, form = 0; while ((c = getopt(argc, argv, "abcf:ghinpruv")) != EOF) { switch (c) { case 'f': fname = optarg; break; case 'b': form |= XFS_BLOCK_QUOTA; break; case 'i': form |= XFS_INODE_QUOTA; break; case 'r': form |= XFS_RTBLOCK_QUOTA; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; case 'a': flags |= ALL_MOUNTS_FLAG; break; case 'c': flags |= HISTOGRAM_FLAG; break; case 'n': flags |= NO_LOOKUP_FLAG; break; case 'v': flags |= VERBOSE_FLAG; break; default: return command_usage("_cmd); } } if (!form) form = XFS_BLOCK_QUOTA; if (!type) { type = XFS_USER_QUOTA; } else if (type != XFS_GROUP_QUOTA && type != XFS_PROJ_QUOTA && type != XFS_USER_QUOTA) { return command_usage("_cmd); } if ((fp = fopen_write_secure(fname)) == NULL) return 0; if (argc == optind) { if (flags & ALL_MOUNTS_FLAG) quot_any_type(fp, form, type, NULL, flags); else if (fs_path->fs_flags & FS_MOUNT_POINT) quot_any_type(fp, form, type, fs_path->fs_dir, flags); } else while (argc > optind) { quot_any_type(fp, form, type, argv[optind++], flags); } if (fname) fclose(fp); return 0; } void quot_init(void) { quot_cmd.name = "quot"; quot_cmd.cfunc = quot_f; quot_cmd.argmin = 0; quot_cmd.argmax = -1; quot_cmd.args = _("[-bir] [-g|-p|-u] [-acv] [-f file]"); quot_cmd.oneline = _("summarize filesystem ownership"); quot_cmd.help = quot_help; if (expert) add_command("_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/quota/quota.c0000644000000000000000000002513013063067172015122 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "command.h" #include #include #include #include "init.h" #include "quota.h" static cmdinfo_t quota_cmd; static void quota_help(void) { printf(_( "\n" " display usage and quota information\n" "\n" " -g -- display group quota information\n" " -p -- display project quota information\n" " -u -- display user quota information\n" " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the initial header\n" " -v -- increase verbosity in reporting (also dumps zero values)\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" "\n")); } static int quota_mount( FILE *fp, __uint32_t id, char *name, uint form, uint type, fs_path_t *mount, uint flags) { fs_disk_quota_t d; char *dev = mount->fs_name; char c[8], h[8], s[8]; uint qflags; int count; xfsquotactl(XFS_QSYNC, dev, type, 0, NULL); if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0) return 0; if (!(flags & VERBOSE_FLAG)) { count = 0; if ((form & XFS_BLOCK_QUOTA) && d.d_bcount) count++; if ((form & XFS_INODE_QUOTA) && d.d_icount) count++; if ((form & XFS_RTBLOCK_QUOTA) && d.d_rtbcount) count++; if (!count) return 0; } if (!(flags & NO_HEADER_FLAG)) { fprintf(fp, _("Disk quotas for %s %s (%u)\nFilesystem%s"), type_to_string(type), name, id, (flags & HUMAN_FLAG) ? " " : " "); if (form & XFS_BLOCK_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? _(" Blocks Quota Limit Warn/Time ") : _(" Blocks Quota Limit Warn/Time ")); if (form & XFS_INODE_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? _(" Files Quota Limit Warn/Time ") : _(" Files Quota Limit Warn/Time ")); if (form & XFS_RTBLOCK_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? _("Realtime Quota Limit Warn/Time ") : _(" Realtime Quota Limit Warn/Time ")); fputs("Mounted on\n", fp); } if (flags & HUMAN_FLAG) { count = fprintf(fp, "%-12s", dev); if (count > 13) fprintf(fp, "\n%12s", " "); } else { count = fprintf(fp, "%-19s", dev); if (count > 20) fprintf(fp, "\n%19s", " "); } if (form & XFS_BLOCK_QUOTA) { qflags = (flags & HUMAN_FLAG); if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit) qflags |= LIMIT_FLAG; if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit) qflags |= QUOTA_FLAG; if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %02d %8s ", bbs_to_string(d.d_bcount, c, sizeof(c)), bbs_to_string(d.d_blk_softlimit, s, sizeof(s)), bbs_to_string(d.d_blk_hardlimit, h, sizeof(h)), d.d_bwarns, time_to_string(d.d_btimer, qflags)); else fprintf(fp, " %10llu %10llu %10llu %02d %9s ", (unsigned long long)d.d_bcount >> 1, (unsigned long long)d.d_blk_softlimit >> 1, (unsigned long long)d.d_blk_hardlimit >> 1, d.d_bwarns, time_to_string(d.d_btimer, qflags)); } if (form & XFS_INODE_QUOTA) { qflags = (flags & HUMAN_FLAG); if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit) qflags |= LIMIT_FLAG; if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit) qflags |= QUOTA_FLAG; if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %02d %8s ", num_to_string(d.d_icount, c, sizeof(c)), num_to_string(d.d_ino_softlimit, s, sizeof(s)), num_to_string(d.d_ino_hardlimit, h, sizeof(h)), d.d_iwarns, time_to_string(d.d_itimer, qflags)); else fprintf(fp, " %10llu %10llu %10llu %02d %9s ", (unsigned long long)d.d_icount, (unsigned long long)d.d_ino_softlimit, (unsigned long long)d.d_ino_hardlimit, d.d_iwarns, time_to_string(d.d_itimer, qflags)); } if (form & XFS_RTBLOCK_QUOTA) { qflags = (flags & HUMAN_FLAG); if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit) qflags |= LIMIT_FLAG; if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit) qflags |= QUOTA_FLAG; if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %02d %8s ", bbs_to_string(d.d_rtbcount, c, sizeof(c)), bbs_to_string(d.d_rtb_softlimit, s, sizeof(s)), bbs_to_string(d.d_rtb_hardlimit, h, sizeof(h)), d.d_rtbwarns, time_to_string(d.d_rtbtimer, qflags)); else fprintf(fp, " %10llu %10llu %10llu %02d %9s ", (unsigned long long)d.d_rtbcount >> 1, (unsigned long long)d.d_rtb_softlimit >> 1, (unsigned long long)d.d_rtb_hardlimit >> 1, d.d_rtbwarns, time_to_string(d.d_rtbtimer, qflags)); } fprintf(fp, "%s\n", mount->fs_dir); return 1; } static void quota( FILE *fp, __uint32_t id, char *name, uint form, uint type, uint flags) { fs_cursor_t cursor; fs_path_t *path; fs_cursor_initialise(NULL, FS_MOUNT_POINT, &cursor); while ((path = fs_cursor_next_entry(&cursor))) { if (quota_mount(fp, id, name, form, type, path, flags)) flags |= NO_HEADER_FLAG; } } static char * getusername( uid_t uid, int numeric) { static char buffer[32]; if (!numeric) { struct passwd *u = getpwuid(uid); if (u) return u->pw_name; } snprintf(buffer, sizeof(buffer), "#%u", uid); return &buffer[0]; } static void quota_user_type( FILE *fp, char *name, uint form, uint type, uint flags) { struct passwd *u; uid_t id; if (name) { if (isdigits_only(name)) { id = atoi(name); name = getusername(id, flags & NO_LOOKUP_FLAG); } else if ((u = getpwnam(name))) { id = u->pw_uid; name = u->pw_name; } else { exitcode = 1; fprintf(stderr, _("%s: cannot find user %s\n"), progname, name); return; } } else { id = getuid(); name = getusername(id, flags & NO_LOOKUP_FLAG); } quota(fp, id, name, form, type, flags); } static char * getgroupname( gid_t gid, int numeric) { static char buffer[32]; if (!numeric) { struct group *g = getgrgid(gid); if (g) return g->gr_name; } snprintf(buffer, sizeof(buffer), "#%u", gid); return &buffer[0]; } static void quota_group_type( FILE *fp, char *name, uint form, uint type, uint flags) { struct group *g; gid_t gid, *gids = NULL; int i, ngroups, dofree = 0; if (name) { if (isdigits_only(name)) { gid = atoi(name); name = getgroupname(gid, flags & NO_LOOKUP_FLAG); } else { if ((g = getgrnam(name))) { gid = g->gr_gid; name = g->gr_name; } else { exitcode = 1; fprintf(stderr, _("%s: cannot find group %s\n"), progname, name); return; } } gids = &gid; ngroups = 1; } else { if ( ((ngroups = sysconf(_SC_NGROUPS_MAX)) < 0) || ((gids = malloc(ngroups * sizeof(gid_t))) == NULL) || ((ngroups = getgroups(ngroups, gids)) < 0)) { /* something failed. Fall back to 1 group */ free(gids); gid = getgid(); gids = &gid; ngroups = 1; } else { /* It all worked, and we allocated memory */ dofree = 1; } } for (i = 0; i < ngroups; i++, name = NULL) { if (!name) name = getgroupname(gids[i], flags & NO_LOOKUP_FLAG); quota(fp, gids[i], name, form, type, flags); } if (dofree) free(gids); } static char * getprojectname( prid_t prid, int numeric) { static char buffer[32]; if (!numeric) { fs_project_t *p = getprprid(prid); if (p) return p->pr_name; } snprintf(buffer, sizeof(buffer), "#%u", (unsigned int)prid); return &buffer[0]; } static void quota_proj_type( FILE *fp, char *name, uint form, uint type, uint flags) { fs_project_t *p; prid_t id; if (!name) { exitcode = 1; fprintf(stderr, _("%s: must specify a project name/ID\n"), progname); return; } if (isdigits_only(name)) { id = atoi(name); name = getprojectname(id, flags & NO_LOOKUP_FLAG); } else if ((p = getprnam(name))) { id = p->pr_prid; name = p->pr_name; } else { exitcode = 1; fprintf(stderr, _("%s: cannot find project %s\n"), progname, name); return; } quota(fp, id, name, form, type, flags); } static void quota_any_type( FILE *fp, char *name, uint form, uint type, uint flags) { switch (type) { case XFS_USER_QUOTA: quota_user_type(fp, name, form, type, flags); break; case XFS_GROUP_QUOTA: quota_group_type(fp, name, form, type, flags); break; case XFS_PROJ_QUOTA: quota_proj_type(fp, name, form, type, flags); break; } } static int quota_f( int argc, char **argv) { FILE *fp = NULL; char *fname = NULL; int c, flags = 0, type = 0, form = 0; while ((c = getopt(argc, argv, "bf:ghnNipruv")) != EOF) { switch (c) { case 'f': fname = optarg; break; case 'b': form |= XFS_BLOCK_QUOTA; break; case 'i': form |= XFS_INODE_QUOTA; break; case 'r': form |= XFS_RTBLOCK_QUOTA; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; case 'h': flags |= HUMAN_FLAG; break; case 'n': flags |= NO_LOOKUP_FLAG; break; case 'N': flags |= NO_HEADER_FLAG; break; case 'v': flags |= VERBOSE_FLAG; break; default: return command_usage("a_cmd); } } if (!form) form = XFS_BLOCK_QUOTA; if (!type) { type = XFS_USER_QUOTA; } else if (type != XFS_GROUP_QUOTA && type != XFS_PROJ_QUOTA && type != XFS_USER_QUOTA) { return command_usage("a_cmd); } if ((fp = fopen_write_secure(fname)) == NULL) return 0; if (argc == optind) quota_any_type(fp, NULL, form, type, flags); else while (argc > optind) quota_any_type(fp, argv[optind++], form, type, flags); if (fname) fclose(fp); return 0; } void quota_init(void) { quota_cmd.name = "quota"; quota_cmd.altname = "l"; quota_cmd.cfunc = quota_f; quota_cmd.argmin = 0; quota_cmd.argmax = -1; quota_cmd.args = _("[-bir] [-g|-p|-u] [-hnNv] [-f file] [id|name]..."); quota_cmd.oneline = _("show usage and limits"); quota_cmd.help = quota_help; quota_cmd.flags = CMD_FLAG_FOREIGN_OK; add_command("a_cmd); } xfsprogs-4.9.0+nmu1ubuntu2/quota/quota.h0000644000000000000000000000561313063067172015133 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xqm.h" #include "path.h" #include "project.h" #include /* * Different forms of XFS quota */ enum { XFS_BLOCK_QUOTA = 0x1, XFS_INODE_QUOTA = 0x2, XFS_RTBLOCK_QUOTA = 0x4, }; /* * System call definitions mapping to platform-specific quotactl */ extern int xfsquotactl(int __cmd, const char *__device, uint __type, uint __id, void * __addr); enum { XFS_QUOTAON, /* enable accounting/enforcement */ XFS_QUOTAOFF, /* disable accounting/enforcement */ XFS_GETQUOTA, /* get disk limits and usage */ XFS_SETQLIM, /* set disk limits */ XFS_GETQSTAT, /* get quota subsystem status */ XFS_QUOTARM, /* free disk space used by dquots */ XFS_QSYNC, /* flush delayed allocate space */ XFS_GETQSTATV, /* newer version of quota stats */ XFS_GETNEXTQUOTA, /* get disk limits and usage */ }; /* * Utility routines */ extern char *type_to_string(uint __type); extern char *form_to_string(uint __form); extern char *time_to_string(time_t __time, uint __flags); extern char *bbs_to_string(__uint64_t __v, char *__c, uint __size); extern char *num_to_string(__uint64_t __v, char *__c, uint __size); extern char *pct_to_string(__uint64_t __v, __uint64_t __t, char *__c, uint __s); extern FILE *fopen_write_secure(char *__filename); /* * Various utility routine flags */ enum { NO_HEADER_FLAG = 0x0001, /* don't print header */ VERBOSE_FLAG = 0x0002, /* increase verbosity */ HUMAN_FLAG = 0x0004, /* human-readable values */ QUOTA_FLAG = 0x0008, /* uid/gid/prid over-quota (soft) */ LIMIT_FLAG = 0x0010, /* uid/gid/prid over-limit (hard) */ ALL_MOUNTS_FLAG = 0x0020, /* iterate over every mounted xfs */ TERSE_FLAG = 0x0040, /* decrease verbosity */ HISTOGRAM_FLAG = 0x0080, /* histogram format output */ DEFAULTS_FLAG = 0x0100, /* use value as a default */ ABSOLUTE_FLAG = 0x0200, /* absolute time, not related to now */ NO_LOOKUP_FLAG = 0x0400, /* skip name lookups, just report ID */ GETNEXTQUOTA_FLAG = 0x0800, /* use getnextquota quotactl */ }; /* * Identifier (uid/gid/prid) cache routines */ #define NMAX 32 extern char *uid_to_name(__uint32_t __uid); extern char *gid_to_name(__uint32_t __gid); extern char *prid_to_name(__uint32_t __prid); extern bool isdigits_only(const char *); xfsprogs-4.9.0+nmu1ubuntu2/quota/report.c0000644000000000000000000004544113063067172015313 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "command.h" #include #include #include #include #include "init.h" #include "quota.h" static cmdinfo_t dump_cmd; static cmdinfo_t report_cmd; static void dump_help(void) { dump_cmd.args = _("[-g|-p|-u] [-f file]"); dump_cmd.oneline = _("dump quota information for backup utilities"); printf(_( "\n" " create a backup file which contains quota limits information\n" " -g -- dump out group quota limits\n" " -p -- dump out project quota limits\n" " -u -- dump out user quota limits (default)\n" " -f -- write the dump out to the specified file\n" "\n")); } static void report_help(void) { report_cmd.args = _("[-bir] [-gpu] [-ahntlLNU] [-f file]"); report_cmd.oneline = _("report filesystem quota information"); printf(_( "\n" " report used space and inodes, and quota limits, for a filesystem\n" " Example:\n" " 'report -igh'\n" " (reports inode usage for all groups, in an easy-to-read format)\n" " This command is the equivalent of the traditional repquota command, which\n" " prints a summary of the disk usage and quotas for the current filesystem,\n" " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" " -n -- skip identifier-to-name translations, just report IDs\n" " -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -L -- lower ID bound to report on\n" " -U -- upper ID bound to report on\n" " -l -- look up names for IDs in lower-upper range\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" " -u -- report user usage and quota information\n" " -b -- report blocks-used information only\n" " -i -- report inodes-used information only\n" " -r -- report realtime-blocks-used information only\n" "\n")); } static int dump_file( FILE *fp, uint id, uint *oid, uint type, char *dev, int flags) { fs_disk_quota_t d; int cmd; if (flags & GETNEXTQUOTA_FLAG) cmd = XFS_GETNEXTQUOTA; else cmd = XFS_GETQUOTA; /* Fall back silently if XFS_GETNEXTQUOTA fails, warn on XFS_GETQUOTA */ if (xfsquotactl(cmd, dev, type, id, (void *)&d) < 0) { if (errno != ENOENT && errno != ENOSYS && errno != ESRCH && cmd == XFS_GETQUOTA) perror("XFS_GETQUOTA"); return 0; } if (oid) { *oid = d.d_id; /* Did kernelspace wrap? */ if (*oid < id) return 0; } if (!d.d_blk_softlimit && !d.d_blk_hardlimit && !d.d_ino_softlimit && !d.d_ino_hardlimit && !d.d_rtb_softlimit && !d.d_rtb_hardlimit) return 1; fprintf(fp, "fs = %s\n", dev); /* this branch is for backward compatibility reasons */ if (d.d_rtb_softlimit || d.d_rtb_hardlimit) fprintf(fp, "%-10d %7llu %7llu %7llu %7llu %7llu %7llu\n", d.d_id, (unsigned long long)d.d_blk_softlimit, (unsigned long long)d.d_blk_hardlimit, (unsigned long long)d.d_ino_softlimit, (unsigned long long)d.d_ino_hardlimit, (unsigned long long)d.d_rtb_softlimit, (unsigned long long)d.d_rtb_hardlimit); else fprintf(fp, "%-10d %7llu %7llu %7llu %7llu\n", d.d_id, (unsigned long long)d.d_blk_softlimit, (unsigned long long)d.d_blk_hardlimit, (unsigned long long)d.d_ino_softlimit, (unsigned long long)d.d_ino_hardlimit); return 1; } static void dump_limits_any_type( FILE *fp, uint type, char *dir, uint lower, uint upper) { fs_path_t *mount; uint id = 0, oid; if ((mount = fs_table_lookup(dir, FS_MOUNT_POINT)) == NULL) { exitcode = 1; fprintf(stderr, "%s: cannot find mount point %s\n", progname, dir); return; } /* Range was specified; query everything in it */ if (upper) { for (id = lower; id <= upper; id++) dump_file(fp, id, NULL, type, mount->fs_name, 0); return; } /* Use GETNEXTQUOTA if it's available */ if (dump_file(fp, id, &oid, type, mount->fs_name, GETNEXTQUOTA_FLAG)) { id = oid + 1; while (dump_file(fp, id, &oid, type, mount->fs_name, GETNEXTQUOTA_FLAG)) id = oid + 1; return; } /* Otherwise fall back to iterating over each uid/gid/prjid */ switch (type) { case XFS_GROUP_QUOTA: { struct group *g; setgrent(); while ((g = getgrent()) != NULL) dump_file(fp, g->gr_gid, NULL, type, mount->fs_name, 0); endgrent(); break; } case XFS_PROJ_QUOTA: { struct fs_project *p; setprent(); while ((p = getprent()) != NULL) dump_file(fp, p->pr_prid, NULL, type, mount->fs_name, 0); endprent(); break; } case XFS_USER_QUOTA: { struct passwd *u; setpwent(); while ((u = getpwent()) != NULL) dump_file(fp, u->pw_uid, NULL, type, mount->fs_name, 0); endpwent(); break; } } } static int dump_f( int argc, char **argv) { FILE *fp; char *fname = NULL; uint lower = 0, upper = 0; int c, type = 0; while ((c = getopt(argc, argv, "f:gpuL:U:")) != EOF) { switch(c) { case 'f': fname = optarg; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; case 'L': lower = (uint)atoi(optarg); break; case 'U': upper = (uint)atoi(optarg); break; default: return command_usage(&dump_cmd); } } if (argc != optind) return command_usage(&dump_cmd); if (!type) { type = XFS_USER_QUOTA; } else if (type != XFS_GROUP_QUOTA && type != XFS_PROJ_QUOTA && type != XFS_USER_QUOTA) { return command_usage(&dump_cmd); } if ((fp = fopen_write_secure(fname)) == NULL) return 0; dump_limits_any_type(fp, type, fs_path->fs_dir, lower, upper); if (fname) fclose(fp); return 0; } static void report_header( FILE *fp, uint form, uint type, fs_path_t *mount, int flags) { char *typename = type_to_string(type); char scratch[64]; uint i, count; if (flags & NO_HEADER_FLAG) return; /* line 1 */ fprintf(fp, _("%s quota on %s (%s)\n"), typename, mount->fs_dir, mount->fs_name); /* line 2 */ for (i = 0; i < 10; i++) fputc(' ', fp); if (form & XFS_BLOCK_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? "%13c %s %13c" : "%20c %s %20c", ' ', form_to_string(XFS_BLOCK_QUOTA), ' '); if (form & XFS_INODE_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? "%13c %s %13c" : "%20c %s %20c", ' ', form_to_string(XFS_INODE_QUOTA), ' '); if (form & XFS_RTBLOCK_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? "%9c %s %9c" : "%15c %s %15c", ' ', form_to_string(XFS_RTBLOCK_QUOTA), ' '); fputc('\n', fp); /* line 3 */ snprintf(scratch, sizeof(scratch), "%s ID", typename); fprintf(fp, "%-10s ", scratch); if (form & XFS_BLOCK_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? _(" Used Soft Hard Warn/Grace ") : _(" Used Soft Hard Warn/Grace ")); if (form & XFS_INODE_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? _(" Used Soft Hard Warn/Grace ") : _(" Used Soft Hard Warn/ Grace ")); if (form & XFS_RTBLOCK_QUOTA) fprintf(fp, (flags & HUMAN_FLAG) ? _(" Used Soft Hard Warn/Grace ") : _(" Used Soft Hard Warn/Grace ")); fputc('\n', fp); /* line 4 */ for (i = 0; i < 10; i++) fputc('-', fp); fputc(' ', fp); count = (flags & HUMAN_FLAG) ? 33 : 50; if (form & XFS_BLOCK_QUOTA) { for (i = 0; i < count; i++) fputc('-', fp); fputc(' ', fp); } if (form & XFS_INODE_QUOTA) { for (i = 0; i < count; i++) fputc('-', fp); fputc(' ', fp); } if (form & XFS_RTBLOCK_QUOTA) { for (i = 0; i < count; i++) fputc('-', fp); fputc(' ', fp); } fputc('\n', fp); } static int report_mount( FILE *fp, __uint32_t id, char *name, __uint32_t *oid, uint form, uint type, fs_path_t *mount, uint flags) { fs_disk_quota_t d; char *dev = mount->fs_name; char c[8], h[8], s[8]; uint qflags; int count; int cmd; if (flags & GETNEXTQUOTA_FLAG) cmd = XFS_GETNEXTQUOTA; else cmd = XFS_GETQUOTA; /* Fall back silently if XFS_GETNEXTQUOTA fails, warn on XFS_GETQUOTA*/ if (xfsquotactl(cmd, dev, type, id, (void *)&d) < 0) { if (errno != ENOENT && errno != ENOSYS && errno != ESRCH && cmd == XFS_GETQUOTA) perror("XFS_GETQUOTA"); return 0; } if (oid) { *oid = d.d_id; /* Did kernelspace wrap? */ if (* oid < id) return 0; } if (flags & TERSE_FLAG) { count = 0; if ((form & XFS_BLOCK_QUOTA) && d.d_bcount) count++; if ((form & XFS_INODE_QUOTA) && d.d_icount) count++; if ((form & XFS_RTBLOCK_QUOTA) && d.d_rtbcount) count++; if (!count) return 0; } if (!(flags & NO_HEADER_FLAG)) report_header(fp, form, type, mount, flags); if (flags & NO_LOOKUP_FLAG) { fprintf(fp, "#%-10u", d.d_id); } else { if (name == NULL) { if (type == XFS_USER_QUOTA) { struct passwd *u = getpwuid(d.d_id); if (u) name = u->pw_name; } else if (type == XFS_GROUP_QUOTA) { struct group *g = getgrgid(d.d_id); if (g) name = g->gr_name; } else if (type == XFS_PROJ_QUOTA) { fs_project_t *p = getprprid(d.d_id); if (p) name = p->pr_name; } } /* If no name is found, print the id #num instead of (null) */ if (name != NULL) fprintf(fp, "%-10s", name); else fprintf(fp, "#%-9u", d.d_id); } if (form & XFS_BLOCK_QUOTA) { qflags = (flags & HUMAN_FLAG); if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit) qflags |= LIMIT_FLAG; if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit) qflags |= QUOTA_FLAG; if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %02d %8s", bbs_to_string(d.d_bcount, c, sizeof(c)), bbs_to_string(d.d_blk_softlimit, s, sizeof(s)), bbs_to_string(d.d_blk_hardlimit, h, sizeof(h)), d.d_bwarns, time_to_string(d.d_btimer, qflags)); else fprintf(fp, " %10llu %10llu %10llu %02d %9s", (unsigned long long)d.d_bcount >> 1, (unsigned long long)d.d_blk_softlimit >> 1, (unsigned long long)d.d_blk_hardlimit >> 1, d.d_bwarns, time_to_string(d.d_btimer, qflags)); } if (form & XFS_INODE_QUOTA) { qflags = (flags & HUMAN_FLAG); if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit) qflags |= LIMIT_FLAG; if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit) qflags |= QUOTA_FLAG; if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %02d %8s", num_to_string(d.d_icount, c, sizeof(c)), num_to_string(d.d_ino_softlimit, s, sizeof(s)), num_to_string(d.d_ino_hardlimit, h, sizeof(h)), d.d_iwarns, time_to_string(d.d_itimer, qflags)); else fprintf(fp, " %10llu %10llu %10llu %02d %9s", (unsigned long long)d.d_icount, (unsigned long long)d.d_ino_softlimit, (unsigned long long)d.d_ino_hardlimit, d.d_iwarns, time_to_string(d.d_itimer, qflags)); } if (form & XFS_RTBLOCK_QUOTA) { qflags = (flags & HUMAN_FLAG); if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit) qflags |= LIMIT_FLAG; if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit) qflags |= QUOTA_FLAG; if (flags & HUMAN_FLAG) fprintf(fp, " %6s %6s %6s %02d %8s", bbs_to_string(d.d_rtbcount, c, sizeof(c)), bbs_to_string(d.d_rtb_softlimit, s, sizeof(s)), bbs_to_string(d.d_rtb_hardlimit, h, sizeof(h)), d.d_rtbwarns, time_to_string(d.d_rtbtimer, qflags)); else fprintf(fp, " %10llu %10llu %10llu %02d %9s", (unsigned long long)d.d_rtbcount >> 1, (unsigned long long)d.d_rtb_softlimit >> 1, (unsigned long long)d.d_rtb_hardlimit >> 1, d.d_rtbwarns, time_to_string(d.d_rtbtimer, qflags)); } fputc('\n', fp); return 1; } static void report_user_mount( FILE *fp, uint form, fs_path_t *mount, uint lower, uint upper, uint flags) { struct passwd *u; uint id = 0, oid; if (upper) { /* identifier range specified */ for (id = lower; id <= upper; id++) { if (report_mount(fp, id, NULL, NULL, form, XFS_USER_QUOTA, mount, flags)) flags |= NO_HEADER_FLAG; } } else if (report_mount(fp, id, NULL, &oid, form, XFS_USER_QUOTA, mount, flags|GETNEXTQUOTA_FLAG)) { id = oid + 1; flags |= GETNEXTQUOTA_FLAG; flags |= NO_HEADER_FLAG; while (report_mount(fp, id, NULL, &oid, form, XFS_USER_QUOTA, mount, flags)) { id = oid + 1; } } else { setpwent(); while ((u = getpwent()) != NULL) { if (report_mount(fp, u->pw_uid, u->pw_name, NULL, form, XFS_USER_QUOTA, mount, flags)) flags |= NO_HEADER_FLAG; } endpwent(); } if (flags & NO_HEADER_FLAG) fputc('\n', fp); } static void report_group_mount( FILE *fp, uint form, fs_path_t *mount, uint lower, uint upper, uint flags) { struct group *g; uint id = 0, oid; if (upper) { /* identifier range specified */ for (id = lower; id <= upper; id++) { if (report_mount(fp, id, NULL, NULL, form, XFS_GROUP_QUOTA, mount, flags)) flags |= NO_HEADER_FLAG; } } else if (report_mount(fp, id, NULL, &oid, form, XFS_GROUP_QUOTA, mount, flags|GETNEXTQUOTA_FLAG)) { id = oid + 1; flags |= GETNEXTQUOTA_FLAG; flags |= NO_HEADER_FLAG; while (report_mount(fp, id, NULL, &oid, form, XFS_GROUP_QUOTA, mount, flags)) { id = oid + 1; } } else { setgrent(); while ((g = getgrent()) != NULL) { if (report_mount(fp, g->gr_gid, g->gr_name, NULL, form, XFS_GROUP_QUOTA, mount, flags)) flags |= NO_HEADER_FLAG; } } if (flags & NO_HEADER_FLAG) fputc('\n', fp); endgrent(); } static void report_project_mount( FILE *fp, uint form, fs_path_t *mount, uint lower, uint upper, uint flags) { fs_project_t *p; uint id = 0, oid; if (upper) { /* identifier range specified */ for (id = lower; id <= upper; id++) { if (report_mount(fp, id, NULL, NULL, form, XFS_PROJ_QUOTA, mount, flags)) flags |= NO_HEADER_FLAG; } } else if (report_mount(fp, id, NULL, &oid, form, XFS_PROJ_QUOTA, mount, flags|GETNEXTQUOTA_FLAG)) { id = oid + 1; flags |= GETNEXTQUOTA_FLAG; flags |= NO_HEADER_FLAG; while (report_mount(fp, id, NULL, &oid, form, XFS_PROJ_QUOTA, mount, flags)) { id = oid + 1; } } else { if (!getprprid(0)) { /* * Print default project quota, even if projid 0 * isn't defined */ if (report_mount(fp, 0, NULL, NULL, form, XFS_PROJ_QUOTA, mount, flags)) flags |= NO_HEADER_FLAG; } setprent(); while ((p = getprent()) != NULL) { if (report_mount(fp, p->pr_prid, p->pr_name, NULL, form, XFS_PROJ_QUOTA, mount, flags)) flags |= NO_HEADER_FLAG; } endprent(); } if (flags & NO_HEADER_FLAG) fputc('\n', fp); } static void report_any_type( FILE *fp, uint form, uint type, char *dir, uint lower, uint upper, uint flags) { fs_cursor_t cursor; fs_path_t *mount; if (type & XFS_USER_QUOTA) { fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) { if (!foreign_allowed && (mount->fs_flags & FS_FOREIGN)) continue; if (xfsquotactl(XFS_QSYNC, mount->fs_name, XFS_USER_QUOTA, 0, NULL) < 0 && errno != ENOENT && errno != ENOSYS) perror("XFS_QSYNC user quota"); report_user_mount(fp, form, mount, lower, upper, flags); } } if (type & XFS_GROUP_QUOTA) { fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) { if (!foreign_allowed && (mount->fs_flags & FS_FOREIGN)) continue; if (xfsquotactl(XFS_QSYNC, mount->fs_name, XFS_GROUP_QUOTA, 0, NULL) < 0 && errno != ENOENT && errno != ENOSYS) perror("XFS_QSYNC group quota"); report_group_mount(fp, form, mount, lower, upper, flags); } } if (type & XFS_PROJ_QUOTA) { fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) { if (!foreign_allowed && (mount->fs_flags & FS_FOREIGN)) continue; if (xfsquotactl(XFS_QSYNC, mount->fs_name, XFS_PROJ_QUOTA, 0, NULL) < 0 && errno != ENOENT && errno != ENOSYS) perror("XFS_QSYNC proj quota"); report_project_mount(fp, form, mount, lower, upper, flags); } } } static int report_f( int argc, char **argv) { FILE *fp = NULL; char *fname = NULL; uint lower = 0, upper = 0; bool lookup = false; int c, flags = 0, type = 0, form = 0; while ((c = getopt(argc, argv, "abdf:ghilL:NnprtuU:")) != EOF) { switch (c) { case 'f': fname = optarg; break; case 'b': form |= XFS_BLOCK_QUOTA; break; case 'i': form |= XFS_INODE_QUOTA; break; case 'r': form |= XFS_RTBLOCK_QUOTA; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; case 'a': flags |= ALL_MOUNTS_FLAG; break; case 'h': flags |= HUMAN_FLAG; break; case 'n': flags |= NO_LOOKUP_FLAG; break; case 'N': flags |= NO_HEADER_FLAG; break; case 't': flags |= TERSE_FLAG; break; case 'L': lower = (uint)atoi(optarg); flags |= NO_LOOKUP_FLAG; break; case 'U': upper = (uint)atoi(optarg); flags |= NO_LOOKUP_FLAG; break; case 'l': lookup = true; break; default: return command_usage(&report_cmd); } } if (!form) form = XFS_BLOCK_QUOTA; if (!type) type = XFS_USER_QUOTA | XFS_GROUP_QUOTA | XFS_PROJ_QUOTA; if (lookup) flags &= ~NO_LOOKUP_FLAG; if ((fp = fopen_write_secure(fname)) == NULL) return 0; if (argc == optind) { if (flags & ALL_MOUNTS_FLAG) report_any_type(fp, form, type, NULL, lower, upper, flags); else if (fs_path && (fs_path->fs_flags & FS_MOUNT_POINT)) report_any_type(fp, form, type, fs_path->fs_dir, lower, upper, flags); } else while (argc > optind) { report_any_type(fp, form, type, argv[optind++], lower, upper, flags); } if (fname) fclose(fp); return 0; } void report_init(void) { dump_cmd.name = "dump"; dump_cmd.cfunc = dump_f; dump_cmd.argmin = 0; dump_cmd.argmax = -1; dump_cmd.args = _("[-g|-p|-u] [-f file]"); dump_cmd.oneline = _("dump quota information for backup utilities"); dump_cmd.help = dump_help; dump_cmd.flags = CMD_FLAG_FOREIGN_OK; report_cmd.name = "report"; report_cmd.altname = "repquota"; report_cmd.cfunc = report_f; report_cmd.argmin = 0; report_cmd.argmax = -1; report_cmd.args = _("[-bir] [-gpu] [-ahnt] [-f file]"); report_cmd.oneline = _("report filesystem quota information"); report_cmd.help = report_help; report_cmd.flags = CMD_FLAG_GLOBAL | CMD_FLAG_FOREIGN_OK; if (expert) { add_command(&dump_cmd); add_command(&report_cmd); } } xfsprogs-4.9.0+nmu1ubuntu2/quota/state.c0000644000000000000000000003624413063067172015121 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "command.h" #include "init.h" #include "quota.h" static cmdinfo_t off_cmd; static cmdinfo_t state_cmd; static cmdinfo_t enable_cmd; static cmdinfo_t disable_cmd; static cmdinfo_t remove_cmd; static void off_help(void) { printf(_( "\n" " turn filesystem quota off, both accounting and enforcement\n" "\n" " Example:\n" " 'off -uv' (switch off user quota on the current filesystem)\n" " This command is the equivalent of the traditional quotaoff command,\n" " which disables quota completely on a mounted filesystem.\n" " Note that there is no 'on' command - for XFS filesystems (with the\n" " exception of the root filesystem on IRIX) quota can only be enabled\n" " at mount time, through the use of one of the quota mount options.\n" "\n" " The state command is useful for displaying the current state. Using\n" " the -v (verbose) option with the 'off' command will display the quota\n" " state for the affected filesystem once the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n")); } static void state_help(void) { printf(_( "\n" " query the state of quota on the current filesystem\n" "\n" " This is a verbose status command, reporting whether or not accounting\n" " and/or enforcement are enabled for a filesystem, which inodes are in\n" " use as the quota state inodes, and how many extents and blocks are\n" " presently being used to hold that information.\n" " The quota type is specified via -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n")); } static void enable_help(void) { printf(_( "\n" " enable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and has quota accounting enabled, but not\n" " quota enforcement, enforcement can be enabled with this command.\n" " With the -v (verbose) option, the status of the filesystem will be\n" " reported after the operation is complete.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n")); } static void disable_help(void) { printf(_( "\n" " disable quota enforcement on a filesystem\n" "\n" " If a filesystem is mounted and is currently enforcing quota, this\n" " provides a mechanism to switch off the enforcement, but continue to\n" " perform used space (and used inodes) accounting.\n" " The affected quota type is -g (groups), -p (projects) or -u (users).\n" "\n")); } static void remove_help(void) { printf(_( "\n" " remove any space being used by the quota subsystem\n" "\n" " Once quota has been switched 'off' on a filesystem, the space that\n" " was allocated to holding quota metadata can be freed via this command.\n" " The affected quota type is -g (groups), -p (projects) or -u (users)\n" " and defaults to user quota (multiple types can be specified).\n" "\n")); } static void state_qfilestat( FILE *fp, struct fs_path *mount, uint type, struct fs_qfilestatv *qfs, int accounting, int enforcing) { fprintf(fp, _("%s quota state on %s (%s)\n"), type_to_string(type), mount->fs_dir, mount->fs_name); fprintf(fp, _(" Accounting: %s\n"), accounting ? _("ON") : _("OFF")); fprintf(fp, _(" Enforcement: %s\n"), enforcing ? _("ON") : _("OFF")); if (qfs->qfs_ino != (__u64) -1) fprintf(fp, _(" Inode: #%llu (%llu blocks, %lu extents)\n"), (unsigned long long)qfs->qfs_ino, (unsigned long long)qfs->qfs_nblks, (unsigned long)qfs->qfs_nextents); else fprintf(fp, _(" Inode: N/A\n")); } static void state_timelimit( FILE *fp, uint form, __uint32_t timelimit) { fprintf(fp, _("%s grace time: %s\n"), form_to_string(form), time_to_string(timelimit, VERBOSE_FLAG | ABSOLUTE_FLAG)); } /* * fs_quota_stat holds a subset of fs_quota_statv; this copies * the smaller into the larger, leaving any not-present fields * empty. This is so the same reporting function can be used * for both XFS_GETQSTAT and XFS_GETQSTATV results. */ static void state_stat_to_statv( struct fs_quota_stat *s, struct fs_quota_statv *sv) { memset(sv, 0, sizeof(struct fs_quota_statv)); /* shared information */ sv->qs_version = s->qs_version; sv->qs_flags = s->qs_flags; sv->qs_incoredqs = s->qs_incoredqs; sv->qs_btimelimit = s->qs_btimelimit; sv->qs_itimelimit = s->qs_itimelimit; sv->qs_rtbtimelimit = s->qs_rtbtimelimit; sv->qs_bwarnlimit = s->qs_bwarnlimit; sv->qs_iwarnlimit = s->qs_iwarnlimit; /* Always room for uquota */ sv->qs_uquota.qfs_ino = s->qs_uquota.qfs_ino; sv->qs_uquota.qfs_nblks = s->qs_uquota.qfs_nblks; sv->qs_uquota.qfs_nextents = s->qs_uquota.qfs_nextents; /* * If we are here, XFS_GETQSTATV failed and XFS_GETQSTAT passed; * that is a very strong hint that we're on a kernel which predates * the on-disk pquota inode; both were added in v3.12. So, we do * some tricksy determination here. * gs_gquota may hold either group quota inode info, or project * quota if that is used instead; which one it actually holds depends * on the quota flags. (If neither is set, neither is used) */ if (s->qs_flags & XFS_QUOTA_GDQ_ACCT) { /* gs_gquota holds group quota info */ sv->qs_gquota.qfs_ino = s->qs_gquota.qfs_ino; sv->qs_gquota.qfs_nblks = s->qs_gquota.qfs_nblks; sv->qs_gquota.qfs_nextents = s->qs_gquota.qfs_nextents; } else if (s->qs_flags & XFS_QUOTA_PDQ_ACCT) { /* gs_gquota actually holds project quota info */ sv->qs_pquota.qfs_ino = s->qs_gquota.qfs_ino; sv->qs_pquota.qfs_nblks = s->qs_gquota.qfs_nblks; sv->qs_pquota.qfs_nextents = s->qs_gquota.qfs_nextents; } } static void state_quotafile_mount( FILE *fp, uint type, struct fs_path *mount, uint flags) { struct fs_quota_stat s; struct fs_quota_statv sv; char *dev = mount->fs_name; sv.qs_version = FS_QSTATV_VERSION1; if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)&sv) < 0) { if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)&s) < 0) { if (flags & VERBOSE_FLAG) fprintf(fp, _("%s quota are not enabled on %s\n"), type_to_string(type), dev); return; } state_stat_to_statv(&s, &sv); } if (type & XFS_USER_QUOTA) state_qfilestat(fp, mount, XFS_USER_QUOTA, &sv.qs_uquota, sv.qs_flags & XFS_QUOTA_UDQ_ACCT, sv.qs_flags & XFS_QUOTA_UDQ_ENFD); if (type & XFS_GROUP_QUOTA) state_qfilestat(fp, mount, XFS_GROUP_QUOTA, &sv.qs_gquota, sv.qs_flags & XFS_QUOTA_GDQ_ACCT, sv.qs_flags & XFS_QUOTA_GDQ_ENFD); if (type & XFS_PROJ_QUOTA) state_qfilestat(fp, mount, XFS_PROJ_QUOTA, &sv.qs_pquota, sv.qs_flags & XFS_QUOTA_PDQ_ACCT, sv.qs_flags & XFS_QUOTA_PDQ_ENFD); state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit); state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit); state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit); } static void state_quotafile( FILE *fp, uint type, char *dir, uint flags) { fs_cursor_t cursor; fs_path_t *mount; fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) state_quotafile_mount(fp, type, mount, flags); } static int state_f( int argc, char **argv) { FILE *fp = NULL; char *fname = NULL; int c, flags = 0, type = 0; while ((c = getopt(argc, argv, "af:gpuv")) != EOF) { switch (c) { case 'a': flags |= ALL_MOUNTS_FLAG; break; case 'f': fname = optarg; break; case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; case 'v': flags |= VERBOSE_FLAG; break; default: return command_usage(&state_cmd); } } if (argc != optind) return command_usage(&state_cmd); if ((fp = fopen_write_secure(fname)) == NULL) return 0; if (!type) type = XFS_USER_QUOTA | XFS_GROUP_QUOTA | XFS_PROJ_QUOTA; if (flags & ALL_MOUNTS_FLAG) state_quotafile(fp, type, NULL, flags); else if (fs_path && fs_path->fs_flags & FS_MOUNT_POINT) state_quotafile(fp, type, fs_path->fs_dir, flags); if (fname) fclose(fp); return 0; } static void enable_enforcement( char *dir, uint type, uint qflags, uint flags) { fs_path_t *mount; mount = fs_table_lookup(dir, FS_MOUNT_POINT); if (!mount) { exitcode = 1; fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); return; } dir = mount->fs_name; if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) perror("XFS_QUOTAON"); else if (flags & VERBOSE_FLAG) state_quotafile_mount(stdout, type, mount, flags); } static void disable_enforcement( char *dir, uint type, uint qflags, uint flags) { fs_path_t *mount; mount = fs_table_lookup(dir, FS_MOUNT_POINT); if (!mount) { exitcode = 1; fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); return; } dir = mount->fs_name; if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) perror("XFS_QUOTAOFF"); else if (flags & VERBOSE_FLAG) state_quotafile_mount(stdout, type, mount, flags); } static void quotaoff( char *dir, uint type, uint qflags, uint flags) { fs_path_t *mount; mount = fs_table_lookup(dir, FS_MOUNT_POINT); if (!mount) { exitcode = 1; fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); return; } dir = mount->fs_name; if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) perror("XFS_QUOTAOFF"); else if (flags & VERBOSE_FLAG) state_quotafile_mount(stdout, type, mount, flags); } static int remove_qtype_extents( char *dir, uint type) { int error = 0; if ((error = xfsquotactl(XFS_QUOTARM, dir, type, 0, (void *)&type)) < 0) perror("XFS_QUOTARM"); return error; } static void remove_extents( char *dir, uint type, uint flags) { fs_path_t *mount; mount = fs_table_lookup(dir, FS_MOUNT_POINT); if (!mount) { exitcode = 1; fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); return; } dir = mount->fs_name; if (type & XFS_USER_QUOTA) { if (remove_qtype_extents(dir, XFS_USER_QUOTA) < 0) return; } if (type & XFS_GROUP_QUOTA) { if (remove_qtype_extents(dir, XFS_GROUP_QUOTA) < 0) return; } else if (type & XFS_PROJ_QUOTA) { if (remove_qtype_extents(dir, XFS_PROJ_QUOTA) < 0) return; } if (flags & VERBOSE_FLAG) state_quotafile_mount(stdout, type, mount, flags); } static int enable_f( int argc, char **argv) { int c, flags = 0, qflags = 0, type = 0; while ((c = getopt(argc, argv, "gpuv")) != EOF) { switch (c) { case 'g': type |= XFS_GROUP_QUOTA; qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; break; case 'p': type |= XFS_PROJ_QUOTA; qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; break; case 'u': type |= XFS_USER_QUOTA; qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; break; case 'v': flags |= VERBOSE_FLAG; break; default: return command_usage(&enable_cmd); } } if (argc != optind) return command_usage(&enable_cmd); if (!type) { type |= XFS_USER_QUOTA; qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; } if (fs_path->fs_flags & FS_MOUNT_POINT) enable_enforcement(fs_path->fs_dir, type, qflags, flags); return 0; } static int disable_f( int argc, char **argv) { int c, flags = 0, qflags = 0, type = 0; while ((c = getopt(argc, argv, "gpuv")) != EOF) { switch (c) { case 'g': type |= XFS_GROUP_QUOTA; qflags |= XFS_QUOTA_GDQ_ENFD; break; case 'p': type |= XFS_PROJ_QUOTA; qflags |= XFS_QUOTA_PDQ_ENFD; break; case 'u': type |= XFS_USER_QUOTA; qflags |= XFS_QUOTA_UDQ_ENFD; break; case 'v': flags |= VERBOSE_FLAG; break; default: return command_usage(&disable_cmd); } } if (argc != optind) return command_usage(&disable_cmd); if (!type) { type |= XFS_USER_QUOTA; qflags |= XFS_QUOTA_UDQ_ENFD; } if (fs_path->fs_flags & FS_MOUNT_POINT) disable_enforcement(fs_path->fs_dir, type, qflags, flags); return 0; } static int off_f( int argc, char **argv) { int c, flags = 0, qflags = 0, type = 0; while ((c = getopt(argc, argv, "gpuv")) != EOF) { switch (c) { case 'g': type |= XFS_GROUP_QUOTA; qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; break; case 'p': type |= XFS_PROJ_QUOTA; qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; break; case 'u': type |= XFS_USER_QUOTA; qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; break; case 'v': flags |= VERBOSE_FLAG; break; default: return command_usage(&off_cmd); } } if (argc != optind) return command_usage(&off_cmd); if (!type) { type |= XFS_USER_QUOTA; qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; } if (fs_path->fs_flags & FS_MOUNT_POINT) quotaoff(fs_path->fs_dir, type, qflags, flags); return 0; } static int remove_f( int argc, char **argv) { int c, flags = 0, type = 0; while ((c = getopt(argc, argv, "gpuv")) != EOF) { switch (c) { case 'g': type |= XFS_GROUP_QUOTA; break; case 'p': type |= XFS_PROJ_QUOTA; break; case 'u': type |= XFS_USER_QUOTA; break; case 'v': flags |= VERBOSE_FLAG; break; default: return command_usage(&remove_cmd); } } if (argc != optind) return command_usage(&remove_cmd); if (!type) { type |= XFS_USER_QUOTA; } if (fs_path->fs_flags & FS_MOUNT_POINT) remove_extents(fs_path->fs_dir, type, flags); return 0; } void state_init(void) { off_cmd.name = "off"; off_cmd.cfunc = off_f; off_cmd.argmin = 0; off_cmd.argmax = -1; off_cmd.args = _("[-gpu] [-v]"); off_cmd.oneline = _("permanently switch quota off for a path"); off_cmd.help = off_help; state_cmd.name = "state"; state_cmd.cfunc = state_f; state_cmd.argmin = 0; state_cmd.argmax = -1; state_cmd.args = _("[-gpu] [-a] [-v] [-f file]"); state_cmd.oneline = _("get overall quota state information"); state_cmd.help = state_help; state_cmd.flags = CMD_FLAG_FOREIGN_OK; enable_cmd.name = "enable"; enable_cmd.cfunc = enable_f; enable_cmd.argmin = 0; enable_cmd.argmax = -1; enable_cmd.args = _("[-gpu] [-v]"); enable_cmd.oneline = _("enable quota enforcement"); enable_cmd.help = enable_help; disable_cmd.name = "disable"; disable_cmd.cfunc = disable_f; disable_cmd.argmin = 0; disable_cmd.argmax = -1; disable_cmd.args = _("[-gpu] [-v]"); disable_cmd.oneline = _("disable quota enforcement"); disable_cmd.help = disable_help; remove_cmd.name = "remove"; remove_cmd.cfunc = remove_f; remove_cmd.argmin = 0; remove_cmd.argmax = -1; remove_cmd.args = _("[-gpu] [-v]"); remove_cmd.oneline = _("remove quota extents from a filesystem"); remove_cmd.help = remove_help; if (expert) { add_command(&off_cmd); add_command(&state_cmd); add_command(&enable_cmd); add_command(&disable_cmd); add_command(&remove_cmd); } } xfsprogs-4.9.0+nmu1ubuntu2/quota/util.c0000644000000000000000000002500513063067172014747 0ustar /* * Copyright (c) 2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "init.h" #include "quota.h" #define SECONDS_IN_A_DAY (24 * 60 * 60) #define SECONDS_IN_A_HOUR (60 * 60) #define SECONDS_IN_A_MINUTE (60) char * time_to_string( time_t origin, uint flags) { static char timestamp[32]; time_t now, timer; uint days, hours, minutes, seconds; if (flags & ABSOLUTE_FLAG) { timer = origin; } else { time(&now); timer = MAX(origin - now, 0); } /* * If we are in verbose mode, or if less than a day remains, we * will show "X days hh:mm:ss" so the user knows the exact timer status. * * Otherwise, we round down to the nearest day - so we add 30s here * such that setting and reporting a limit in rapid succession will * show the limit which was just set, rather than immediately reporting * one day less. */ if ((timer > SECONDS_IN_A_DAY) && !(flags & VERBOSE_FLAG)) timer += 30; /* seconds */ days = timer / SECONDS_IN_A_DAY; if (days) timer %= SECONDS_IN_A_DAY; hours = timer / SECONDS_IN_A_HOUR; if (hours) timer %= SECONDS_IN_A_HOUR; minutes = timer / SECONDS_IN_A_MINUTE; seconds = timer % SECONDS_IN_A_MINUTE; if (flags & LIMIT_FLAG) { snprintf(timestamp, sizeof(timestamp), (flags & HUMAN_FLAG) ? _("[-none-]") : _("[--none--]")); } else if (origin == 0) { snprintf(timestamp, sizeof(timestamp), (flags & HUMAN_FLAG) ? _("[------]") : _("[--------]")); } else if ((hours == 0 && minutes == 0 && seconds == 0) || (!(flags & VERBOSE_FLAG) && days > 0)) { snprintf(timestamp, sizeof(timestamp), "[%u %s]", days, days == 1 ? _("day") : _("days")); } else if (flags & VERBOSE_FLAG) { snprintf(timestamp, sizeof(timestamp), "[%u %s %02u:%02u:%02u]", days, days == 1 ? _("day") : _("days"), hours, minutes, seconds); } else { /* non-verbose, less than a day remaining */ snprintf(timestamp, sizeof(timestamp), (flags & HUMAN_FLAG) ? "%02u:%02u:%02u" : "[%02u:%02u:%02u]", hours, minutes, seconds); } return timestamp; } static int round_snprintf( char *sp, size_t size, const char *fmt_round, const char *fmt_not_round, __uint64_t value, __uint64_t divisor) { double v = (double)value / divisor; value /= divisor; if (v == (double)value) return snprintf(sp, size, fmt_round, (uint)value); else return snprintf(sp, size, fmt_not_round, v); } /* Basic blocks (512) bytes are returned from quotactl */ #define BBS_TO_EXABYTES(bbs) ((__uint64_t)(bbs)>>51) #define BBS_TO_PETABYTES(bbs) ((__uint64_t)(bbs)>>41) #define BBS_TO_TERABYTES(bbs) ((__uint64_t)(bbs)>>31) #define BBS_TO_GIGABYTES(bbs) ((__uint64_t)(bbs)>>21) #define BBS_TO_MEGABYTES(bbs) ((__uint64_t)(bbs)>>11) #define BBS_TO_KILOBYTES(bbs) ((__uint64_t)(bbs)>>1) #define BBEXABYTE ((__uint64_t)1<<51) #define BBPETABYTE ((__uint64_t)1<<41) #define BBTERABYTE ((__uint64_t)1<<31) #define BBGIGABYTE ((__uint64_t)1<<21) #define BBMEGABYTE ((__uint64_t)1<<11) #define BBKILOBYTE ((__uint64_t)1<< 1) char * bbs_to_string( __uint64_t v, char *sp, uint size) { if (v == 0) snprintf(sp, size, "%4u", (uint)v); else if (BBS_TO_EXABYTES(v)) round_snprintf(sp, size, "%3uE", "%3.1fE", v, BBEXABYTE); else if (BBS_TO_PETABYTES(v)) round_snprintf(sp, size, "%3uP", "%3.1fP", v, BBPETABYTE); else if (BBS_TO_TERABYTES(v)) round_snprintf(sp, size, "%3uT", "%3.1fT", v, BBTERABYTE); else if (BBS_TO_GIGABYTES(v)) round_snprintf(sp, size, "%3uG", "%3.1fG", v, BBGIGABYTE); else if (BBS_TO_MEGABYTES(v)) round_snprintf(sp, size, "%3uM", "%3.1fM", v, BBMEGABYTE); else if (BBS_TO_KILOBYTES(v)) round_snprintf(sp, size, "%3uK", "%3.1fK", v, BBKILOBYTE); else snprintf(sp, size, "%4u", (uint)v << BBSHIFT); /* bytes */ return sp; } #define THOUSAND ((__uint64_t)1000) #define MILLION ((__uint64_t)1000*1000) #define BILLION ((__uint64_t)1000*1000*1000) #define TRILLION ((__uint64_t)1000*1000*1000*1000) #define GAZILLION ((__uint64_t)1000*1000*1000*1000*1000) #define RIDICULOUS ((__uint64_t)1000*1000*1000*1000*1000*1000) #define STOPALREADY ((__uint64_t)1000*1000*1000*1000*1000*1000*1000) char * num_to_string( __uint64_t v, char *sp, uint size) { if (v == 0) snprintf(sp, size, "%4u", (uint)v); else if (v > STOPALREADY) round_snprintf(sp, size, "%3us", "%3.1fs", v, STOPALREADY); else if (v > RIDICULOUS) round_snprintf(sp, size, "%3ur", "%3.1fr", v, RIDICULOUS); else if (v > GAZILLION) round_snprintf(sp, size, "%3ug", "%3.1fg", v, GAZILLION); else if (v > TRILLION) round_snprintf(sp, size, "%3ut", "%3.1ft", v, TRILLION); else if (v > BILLION) round_snprintf(sp, size, "%3ub", "%3.1fb", v, BILLION); else if (v > MILLION) round_snprintf(sp, size, "%3um", "%3.1fm", v, MILLION); else if (v > THOUSAND) round_snprintf(sp, size, "%3uk", "%3.1fk", v, THOUSAND); else snprintf(sp, size, "%4u", (uint)v); return sp; } char * pct_to_string( __uint64_t portion, __uint64_t whole, char *buf, uint size) { uint percent; percent = whole ? (uint) (100.0 * portion / whole + 0.5) : 0; if (snprintf(buf, size, "%3u", percent) < 0) return "???"; return buf; } char * form_to_string( uint form) { char *forms[] = { _("Blocks"), _("Inodes"), _("Realtime Blocks") }; if (form & XFS_BLOCK_QUOTA) return forms[0]; if (form & XFS_INODE_QUOTA) return forms[1]; if (form & XFS_RTBLOCK_QUOTA) return forms[2]; return NULL; } char * type_to_string( uint type) { char *types[] = { _("User"), _("Group"), _("Project") }; if (type & XFS_USER_QUOTA) return types[0]; if (type & XFS_GROUP_QUOTA) return types[1]; if (type & XFS_PROJ_QUOTA) return types[2]; return NULL; } /* * Identifier caches - user/group/project names/IDs */ #define NID 4096 #define IDMASK (NID-1) typedef struct { __uint32_t id; char name[NMAX+1]; } idcache_t; static idcache_t uidnc[NID]; static idcache_t gidnc[NID]; static idcache_t pidnc[NID]; static int uentriesleft = NID; static int gentriesleft = NID; static int pentriesleft = NID; static idcache_t * getnextpwent( __uint32_t id, int byid) { struct passwd *pw; static idcache_t idc; /* /etc/passwd */ if ((pw = byid? getpwuid(id) : getpwent()) == NULL) return NULL; idc.id = pw->pw_uid; strncpy(idc.name, pw->pw_name, NMAX); return &idc; } static idcache_t * getnextgrent( __uint32_t id, int byid) { struct group *gr; static idcache_t idc; if ((gr = byid? getgrgid(id) : getgrent()) == NULL) return NULL; idc.id = gr->gr_gid; strncpy(idc.name, gr->gr_name, NMAX); return &idc; } static idcache_t * getnextprent( __uint32_t id, int byid) { fs_project_t *pr; static idcache_t idc; if ((pr = byid? getprprid(id) : getprent()) == NULL) return NULL; idc.id = pr->pr_prid; strncpy(idc.name, pr->pr_name, NMAX); return &idc; } char * uid_to_name( __uint32_t id) { idcache_t *ncp, *idp; /* Check cache for name first */ ncp = &uidnc[id & IDMASK]; if (ncp->id == id && ncp->name[0]) return ncp->name; if (uentriesleft) { /* * Fill this cache while seaching for a name. * This lets us run through the file serially. */ if (uentriesleft == NID) setpwent(); while (((idp = getnextpwent(id, 0)) != NULL) && uentriesleft) { uentriesleft--; ncp = &uidnc[idp->id & IDMASK]; if (ncp->name[0] == '\0' || idp->id == id) memcpy(ncp, idp, sizeof(idcache_t)); if (idp->id == id) return ncp->name; } endpwent(); uentriesleft = 0; ncp = &uidnc[id & IDMASK]; } /* Not cached - do it the slow way & insert into cache */ if ((idp = getnextpwent(id, 1)) == NULL) return NULL; memcpy(ncp, idp, sizeof(idcache_t)); return ncp->name; } char * gid_to_name( __uint32_t id) { idcache_t *ncp, *idp; /* Check cache for name first */ ncp = &gidnc[id & IDMASK]; if (ncp->id == id && ncp->name[0]) return ncp->name; if (gentriesleft) { /* * Fill this cache while seaching for a name. * This lets us run through the file serially. */ if (gentriesleft == NID) setgrent(); while (((idp = getnextgrent(id, 0)) != NULL) && gentriesleft) { gentriesleft--; ncp = &gidnc[idp->id & IDMASK]; if (ncp->name[0] == '\0' || idp->id == id) memcpy(ncp, idp, sizeof(idcache_t)); if (idp->id == id) return ncp->name; } endgrent(); gentriesleft = 0; ncp = &gidnc[id & IDMASK]; } /* Not cached - do it the slow way & insert into cache */ if ((idp = getnextgrent(id, 1)) == NULL) return NULL; memcpy(ncp, idp, sizeof(idcache_t)); return ncp->name; } char * prid_to_name( __uint32_t id) { idcache_t *ncp, *idp; /* Check cache for name first */ ncp = &pidnc[id & IDMASK]; if (ncp->id == id && ncp->name[0]) return ncp->name; if (pentriesleft) { /* * Fill this cache while seaching for a name. * This lets us run through the file serially. */ if (pentriesleft == NID) setprent(); while (((idp = getnextprent(id, 0)) != NULL) && pentriesleft) { pentriesleft--; ncp = &pidnc[idp->id & IDMASK]; if (ncp->name[0] == '\0' || idp->id == id) memcpy(ncp, idp, sizeof(idcache_t)); if (idp->id == id) return ncp->name; } endprent(); pentriesleft = 0; ncp = &pidnc[id & IDMASK]; } /* Not cached - do it the slow way & insert into cache */ if ((idp = getnextprent(id, 1)) == NULL) return NULL; memcpy(ncp, idp, sizeof(idcache_t)); return ncp->name; } /* * Utility routine for opening an output file so that it can * be "securely" written to (i.e. without vulnerability to a * symlink attack). * * Returns NULL on failure, stdout on NULL input. */ FILE * fopen_write_secure( char *fname) { FILE *fp; int fd; if (!fname) return stdout; if ((fd = open(fname, O_CREAT|O_WRONLY|O_EXCL, 0600)) < 0) { exitcode = 1; fprintf(stderr, _("%s: open on %s failed: %s\n"), progname, fname, strerror(errno)); return NULL; } if ((fp = fdopen(fd, "w")) == NULL) { exitcode = 1; fprintf(stderr, _("%s: fdopen on %s failed: %s\n"), progname, fname, strerror(errno)); close(fd); return NULL; } return fp; } xfsprogs-4.9.0+nmu1ubuntu2/release.sh0000755000000000000000000000161113063067167014455 0ustar #!/bin/sh # # Automate generation of a new release # # Need to first update these files: # # VERSION (with new version number) # docs/CHANGES (with changelog and version/date string) # configure.ac (with new version string) # debian/changelog (with new release entry, only for release version) . ./VERSION version=${PKG_MAJOR}.${PKG_MINOR}.${PKG_REVISION} date=`date +"%-d %B %Y"` echo "Cleaning up" make realclean echo "Updating CHANGES" sed -e "s/${version}.*/${version} (${date})/" doc/CHANGES > doc/CHANGES.tmp && \ mv doc/CHANGES.tmp doc/CHANGES echo "Commiting CHANGES update to git" git commit -a -m "${version} release" echo "Tagging git repository" git tag -a -m "${version} release" v${version} echo "Making source tarball" make dist #echo "Sign the source tarball" #gpg --detach-sign xfsprogs-${version}.tar.gz echo "Done. Please remember to push out tags using \"git push --tags\"" xfsprogs-4.9.0+nmu1ubuntu2/repair/0000755000000000000000000000000013063067174013757 5ustar xfsprogs-4.9.0+nmu1ubuntu2/repair/Makefile0000644000000000000000000000304713063067172015421 0ustar # # Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LSRCFILES = README LTCOMMAND = xfs_repair HFILES = agheader.h attr_repair.h avl.h avl64.h bmap.h btree.h \ da_util.h dinode.h dir2.h err_protos.h globals.h incore.h protos.h \ rt.h progress.h scan.h versions.h prefetch.h rmap.h slab.h threads.h CFILES = agheader.c attr_repair.c avl.c avl64.c bmap.c btree.c \ da_util.c dino_chunks.c dinode.c dir2.c globals.c incore.c \ incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c \ progress.c prefetch.c rmap.c rt.c sb.c scan.c slab.c threads.c \ versions.c xfs_repair.c LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBXCMD) $(LIBUUID) \ $(LIBRT) $(LIBPTHREAD) $(LIBBLKID) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) $(LIBXCMD) LLDFLAGS = -static-libtool-libs default: depend $(LTCOMMAND) globals.o: globals.h include $(BUILDRULES) # # Tracing flags: # -DXR_INODE_TRACE inode processing # -DXR_DIR_TRACE directory processing # -DXR_DUP_TRACE duplicate extent processing # -DXR_BCNT_TRACE incore bcnt freespace btree building # -DXR_BLD_FREE_TRACE building on-disk freespace (bcnt/bno) btrees # -DXR_BLD_INO_TRACE building on-disk inode allocation btrees # -DXR_BLD_ADD_EXTENT track phase 5 block extent creation # -DXR_BCKPTR_DBG parent list debugging info # -DXR_PF_TRACE prefetch trace # #CFLAGS += ... install: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/repair/README0000644000000000000000000006670713063067172014655 0ustar A living document. The basic algorithm. TODO: (D == DONE) 0) Need to bring some sanity into the case of flags that can be set in the secondaries at mkfs time but reset or cleared in the primary later in the filesystem's life. 0) Clear the persistent read-only bit if set. Clear the shared bit if set and the version number is zero. This brings the filesystem back to a known state. 0) make sure that superblock geometry code checks the logstart value against whether or not we have an internal log. If we have an internal log and a logdev, that's ok. (Maybe we just aren't using it). If we have an external log (logstart == 0) but no logdev, that's right out. 0) write secondary superblock search code. Rewrite initial superblock parsing code to be less complicated. Just use variables to indicate primary, secondary, etc., and use a function to get the SB given a specific location or something. 2) For inode alignment, if the SB bit is set and the inode alignment size field in the SB is set, then believe that the fs inodes MUST be aligned and disallow any non-aligned inodes. Likewise, if the SB bit isn't set (or earlier version) and the inode alignment size field is zero, then never set the bit even if the inodes are aligned. Note that the bits and alignment values are replicated in the secondary superblocks. 0) add feature specification options to parse_arguments 0) add logic to add_inode_ref(), add_inode_reached() to detect nlink overflows in cases where the fs (or user had indicated fs) doesn't support new nlinks. 6) check to make sure that the inodes containing btree blocks with # recs < minrecs aren't legit -- e.g. the only descendant of a root block. 7) inode di_size value sanity checking -- should always be less than the biggest filebno offset mentioned in the bmaps. Doesn't have to be equal though since we're allowed to overallocate (it just wastes a little space). This is for both regular files and directories (have to modify the existing directory check). Add tracking of largest offset in bmap scanning code. Compare value against di_size. Should be >= di_size. Alternatively, you could pass the inode into down through the extent record processing layer and make the checks there. Add knowledge of quota inodes. size of quota inode is always zero. We should maintain that. 8) Basic quota stuff. Invariants if quota feature bit is set, the quota inodes if set, should point to disconnected, 0 len inodes. D - if quota inodes exist, the quota bits must be turned on. It's ok for the quota flags to be zeroed but they should be in a legal state (see xfs_quota.h). D - if the quota flags are non-zero, the corresponding quota inodes must exist. quota inodes are never deleted, only their space is freed. if quotas are being downgraded, then check quota inodes at the end of phase 3. If they haven't been cleared yet, clear them. Regardless, then clear sb flags (quota inode fields, quota flags, and quota bit). 5) look at verify_inode_chunk(). it's probably really broken. 9) Complicated quota stuff. Add code to bmap scan code to track used blocks. Add another pair of AVL trees to track user and project quota limits. Set AVL trees up at the beginning of phase 3. Quota inodes can be rebuilt or corrected later if damaged. D - 0) fix directory processing. phase 3, if an entry references a free inode, *don't* mark it used. wait for the rest of phase 3 processing to hit that inode. If it looks like it's in use, we'll mark in use then. If not, we'll clear it and mark the inode map. then in phase 4, you can depend on the inode map. should probably set the parent info in phase 4. So we have a check_dups flag. Maybe we should change the name of check_dir to discover_inodes. During phase 3 (discover_inodes == 1), uncertain inodes are added to list. During phase 4 (discover_inodes == 0), they aren't. And we never mark inodes in use from the directory code. During phase 4, we shouldn't complain about names with a leading '/' since we made those names in phase 3. Have to change dino_chunks.c (parent setting), dinode.c and dir.c. D - 0) make sure we don't screw up filesystems with real-time inodes. remember to initialize real-time map with all blocks XR_E_FREE. D - 4) check contents of symlinks as well as lengths in process_symlinks() in dinode.c. Right now, we only check lengths. D - 1) Feature mismatches -- for quotas and attributes, if the stuff exists in the filesystem, set the superblock version bits. D - 0) rewrite directory leaf block holemap comparison code. probably should just check the leaf block hole info against our incore bitmap. If the hole flag is not set, then we know that there can only be one hole and it has to be between the entry table and the top of heap. If the hole flag is set, then it's ok if the on-disk holemap doesn't describe everything as long as what it does describe doesn't conflict with reality. D - 0) rewrite setting nlinks handling -- for version 1 inodes, set both nlinks and onlinks (zero projid_lo/hi and pad) if we have to change anything. For version 2, I think we're ok. D - 0) Put awareness of quota inode into mark_standalone_inodes. D - 8) redo handling of superblocks with bad version numbers. need to bail out (without harming) fs's that have sbs that are newer than we are. D - 0) How do we handle feature mismatches between fs and superblock? For nlink, check each inode after you know it's good. If onlinks is 0 and nlinks is > 0 and it's a version 2 inode, then it really is a version 2 inode and the nlinks flag in the SB needs to be set. If it's a version 2 inode and the SB agrees but onlink is non-zero, then clear onlink. D - 3) keep cumulative counts of freeblocks, inodes, etc. to set in the superblock at the end of phase 5. Remember that agf freeblock counters don't include blocks used by the non-root levels of the freespace trees but that the sb free block counters include those. D - 0) Do parent setting in directory code (called by phase 3). actually, I put it in process_inode_set and propagated the parent up to it from the process_dinode/process_dir routines. seemed cleaner than pushing the irec down and letting them bang on it. D - 0) If we clear a file in phase 4, make sure that if it's a directory that the parent info is cleared also. D - 0) put inode tree flashover (call to add_ino_backptrs) into phase 5. D - 0) do set/get_inode_parent functions in incore_ino.c. also do is/set/ inode_processed. D - 0) do a versions.c to extract feature info and set global vars from the superblock version number and possibly feature bits D - 0) change longform_dir_entry_check + shortform_dir_entry_check to return a count of how many illegal '/' entries exist. if > 0, then process_dirstack needs to call prune_dir_entry with a hash value of 0 to delete the entries. D - 0) add the "processed" bitfield to the backptrs_t struct that gets attached after phase 4. D- ) Phase 6 !!! D - 0) look at usage of XFS_MAKE_IPTR(). It does the right arithmetic assuming you count your offsets from the beginning of the buffer. D - 0) look at references to XFS_INODES_PER_CHUNK. change the ones that really mean sizeof(__uint64_t)*NBBY to something else (like that only defined as a constant INOS_PER_IREC. this isn't as important since XFS_INODES_PER_CHUNK will never chang D - 0) look at junk_zerolen_dir_leaf_entries() to make sure it isn't hosing the freemap since it assumed that bytes between the end of the table and firstused didn't show up in the freemap when they actually do. D - 0) track down XFS_INO_TO_OFFSET() usage. I don't think I'm using it right. (e.g. I think it gives you the offset of an inode into a block but on small block filesystems, I may be reading in inodes in multiblock buffers and working from the start of the buffer plus I'm using it to get offsets into my ino_rec's which may not be a good idea since I use 64-inode ino_rec's whereas the offset macro works off blocksize). D - 0.0) put buffer -> dirblock conversion macros into xfs kernel code D - 0.2) put in sibling pointer checking and path fixup into bmap (long form) scan routines in scan.c D - 0.3) find out if bmap btrees with only root blocks are legal. I'm betting that they're not because they'd be extent inodes instead. If that's the case, rip some code out of process_btinode() Algorithm (XXX means not done yet): Phase 1 -- get a superblock and zero log get a superblock -- either read in primary or find a secondary (ag header), check ag headers To find secondary: Go for brute force and read in the filesystem N meg at a time looking for a superblock. as a slight optimization, we could maybe skip ahead some number of blocks to try and get towards the end of the first ag. After you find a secondary, try and find at least other ags as a verification that the secondary is a good superblock. XXX - Ugh. Have to take growfs'ed filesystems into account. The root superblock geometry info may not be right if recovery hasn't run or it's been trashed. The old ag's may or may not be right since the system could have crashed during growfs or the bwrite() to the superblocks could have failed and the buffer been reused. So we need to check to see if another ag exists beyond the "last" ag to see if a growfs happened. If not, then we know that the geometry info is good and treat the fs as a non-growfs'ed fs. If we do have inconsistencies, then the smaller geometry is the old fs and the larger the new. We can check the new superblocks to see if they're good. If not, then we know the system crashed at or soon after the growfs and we can choose to either accept the new geometry info or trash it and truncate the fs back to the old geometry parameters. Cross-check geometry information in secondary sb's with primary to ensure that it's correct. Use sim code to allow mount filesystems *without* reading in root inode. This sets up the xfs_mount_t structure and allows us to use XFS_* macros that we wouldn't otherwise be able to use. Note, I split phase 1 and 2 into separate pieces because I want to initialize the xfs_repair incore data structures after phase 1. parse superblock version and feature flags and set appropriate global vars to reflect the flags (attributes, quotas, etc.) Workaround for the mkfs "not zeroing the superblock buffer" bug. Determine what field is the last valid non-zero field in the superblock. The trick here is to be able to differentiate the last valid non-zero field in the primary superblock and secondaries because they may not be the same. Fields in the primary can be set as the filesystem gets upgraded but the upgrades won't touch the secondaries. This means that we need to find some number of secondaries and check them. So we do the checking here and the setting in phase2. Phase 2 -- check integrity of allocation group allocation structures zero the log if in no modify mode sanity check ag headers -- superblocks match, agi isn't trashed -- the agf and agfl don't really matter because we can just recreate them later. Zero part of the superblock buffer if necessary Walk the freeblock trees to get an initial idea of what the fs thinks is free. Files that disagree (claim free'd blocks) can be salvaged or deleted. If the btree is internally inconsistent, when in doubt, mark blocks free. If they're used, they'll be stolen back later. don't have to check sibling pointers for each level since we're going to regenerate all the trees anyway. Walk the inode allocation trees and make sure they're ok, otherwise the sim inode routines will probably just barf. mark inode allocation tree blocks and ag header blocks as used blocks. If the trees are corrupted, this phase will generate "uncertain" inode chunks. Those chunks go on a list and will have to verified later. Record the blocks that are used to detect corruption and multiply claimed blocks. These trees will be regenerated later. Mark the blocks containing inodes referenced by uncorrupted inode trees as being used by inodes. The other blocks will get marked when/if the inodes are verified. calculate root and realtime inode numbers from the filesystem geometry, fix up mount structure's incore superblock if they're wrong. ASSUMPTION: at end of phase 2, we've got superblocks and ag headers that are not garbage (some data in them like counters and the freeblock and inode trees may be inconsistent but the header is readable and otherwise makes sense). XXX if in no_modify mode, check for blocks claimed by one freespace btree and not the other Phase 3 -- traverse inodes to make the inodes, bmaps and freespace maps consistent. For each ag, use either the incore inode map or scan the ag for inodes. Let's use the incore inode map, now that we've made one up in phase2. If we lose the maps, we'll locate inodes when we traverse the directory heirarchy. If we lose both, we could scan the disk. Ugh. Maybe make that a command-line option that we support later. ASSUMPTION: we know if the ag allocation btrees are intact (phase 2) First - Walk and clear the ag unlinked lists. We'll process the inodes later. Check and make sure that the unlinked lists reference known inodes. If not, add to the list of uncertain inodes. Second, check the uncertain inode list generated in phase2 and above and get them into the inode tree if they're good. The incore inode cluster tree *always* has good clusters (alignment, etc.) in it. Third, make sure that the root inode is known. If not, and we know the inode number from the superblock, discover that inode and its chunk. Then, walk the incore inode-cluster tree. Maintain an in-core bitmap over the entire fs for block allocation. traverse each inode, make sure inode mode field matches free/allocated bit in the incore inode allocation tree. If there's a mismatch, assume that the inode is in use. - for each in-use inode, traverse each bmap/dir/attribute map or tree. Maintain a map (extent list?) for the current inode. - For each block marked as used, check to see if already known (referenced by another file or directory) and sanity check the contents of the block as well if possible (in the case of meta-blocks). - if the inode claims already used blocks, mark the blocks as multiply claimed (duplicate) and go on. the inode will be cleared in phase 4. - if metablocks are garbaged, clear the inode after traversing what you can of the bmap and proceed to next inode. We don't have to worry about trashing the maps or trees in cleared inodes because the blocks will show up as free in the ag freespace trees that we set up in phase 5. - clear the di_next_unlinked pointer -- all unlinked but active files go bye-bye. - All blocks start out unknown. We need the last state in case we run into a case where we need to step on a block to store filesystem meta-data and it turns out later that it's referenced by some inode's bmap. In that case, the inode loses because we've already trashed the block. This shouldn't happen in the first version unless some inode has a bogus bmap referencing blocks in the ag header but the 4th state will keep us from inadvertently doing something stupid in that case. - If inode is allocated, mark all blocks allocated to the current inode as allocated in the incore freespace bitmap. - If inode is good and a directory, scan through it to find leaf entries and discover any unknown inodes. For shortform, we correct what we can. If the directory is corrupt, we try and fix it in place. If it has zero good entries, then we blast it. All unknown inodes get put onto the uncertain inode list. This is safe because we only put inodes onto the list when we're processing known inodes so the uncertain inode list isn't in use. We fix only one problem -- an entry that has a mathematically invalid inode numbers in them. If that's the case, we replace the inode number with NULLFSINO and we'll fix up the entry in phase 6. That info may conflict with the inode information, but we'll straighten out any inconsistencies there in phase4 when we process the inodes again. Errors involving bogus forward/back links, zero-length entries make the directory get trashed. if an entry references a free inode, ignore that fact for now. wait for the rest of phase 3 processing to hit that inode. If it looks like it's in use, we'll mark in use then. If not, we'll clear it and mark the inode map. then in phase 4, you can depend on the inode map. Entries that point to non-existent or free inodes, and extra blocks in the directory will get fixed in place in a later pass. Entries that point to a quota inode are marked TBD. If the directory internally points to the same block twice, the directory gets blown away. Note that processing uncertain inodes can add more inodes to the uncertain list if they're directories. So we loop until the uncertain list is empty. During inode verification, if the inode blocks are unknown, mark then as in-use by inodes. XXX HEURISTIC -- if we blow an inode away that has space, assume that the freespace btree is now out of wack. If it was ok earlier, it's certain to be wrong now. And the odds of this space free cancelling out the existing error is so small I'm willing to ignore it. Should probably do this via a global var and complain about this later. Assumption: All known inodes are now marked as in-use or free. Any inodes that we haven't found by now are hosed (lost) since we can't reach them via either the inode btrees or via directory entries. Directories are semi-clean. All '.' entries are good. Root '..' entry is good if root inode exists. All entries referencing non-existent inodes, free inodes, etc. XXX verify that either quota inode is 0 or NULLFSINO or if sb quota flag is non zero, verify that quota inode is NULLFSINO or is referencing a used, but disconnected inode. XXX if in no_modify mode, check for unclaimed blocks - Phase 4 - Check for inodes referencing duplicate blocks At this point, all known duplicate blocks are marked in the block map. However, some of the claimed blocks in the bmap may in fact be free because they belong to inodes that have to be cleared either due to being a trashed directory or because it's the first inode to claim a block that was then claimed later. There's a similar problem with meta-data blocks that are referenced by inode bmaps that are going to be freed once the inode (or directory) gets cleared. So at this point, we collect the duplicate blocks into extents and put them into the duplicate extent list. Mark the ag header blocks as in use. We then process each inode twice -- the first time we check to see if the inode claims a duplicate extent and we do NOT set the block bitmap. If the inode claims a duplicate extent, we clear the inode. Since the bitmap hasn't been set, that automatically frees all blocks associated with the cleared inode. If the inode is ok, process it a second time and set the bitmap since we know that this inode will live. The unlinked list gets cleared in every inode at this point as well. We no longer need to preserve it since we've discovered every inode we're going to find from it. verify existence of root inode. if it exists, check for existence of "lost+found". If it exists, mark the entry to be deleted, and clear the inode. All the inodes that were connected to the lost+found will be reconnected later. XXX HEURISTIC -- if we blow an inode away that has space, assume that the freespace btree is now out of wack. If it was ok earlier, it's certain to be wrong now. And the odds of this space free cancelling out the existing error is so small I'm willing to ignore it. Should probably do this via a global var and complain about this later. Clear the quota inodes if the inode btree says that they're not in use. The space freed will get picked up by phase 5. XXX Clear the quota inodes if the filesystem is being downgraded. - Phase 5 - Build inode allocation trees, freespace trees and agfl's for each ag. After this, we should be able to unmount the filesystem and remount it for real. For each ag: (if no in no_modify mode) scan bitmap first to figure out number of extents. calculate space required for all trees. Start with inode trees. Setup the btree cursor which includes the list of preallocated blocks. As a by-product, this will delete the extents required for the inode tree from the incore extent tree. Calculate how many extents will be required to represent the remaining free extent tree on disk (twice, one for bybno and one for bycnt). You have to iterate on this because consuming extents can alter the number of blocks required to represent the remaining extents. If there's slop left over, you can put it in the agfl though. Then, manually build the trees, agi, agfs, and agfls. XXX if in no_modify mode, scan the on-disk inode allocation trees and compare against the incore versions. Don't have to scan the freespace trees because we caught the problems there in phase2 and phase3. But if we cleared any inodes with space during phases 3 or 4, now is the time to complain. XXX - Free duplicate extent lists. ??? Assumptions: at this point, sim code having to do with inode creation/modification/deletion and space allocation work because the inode maps, space maps, and bmaps for all files in the filesystem are good. The only structures that are screwed up are the directory contents, which means that lookup may not work for beans, the root inode which exists but may be completely bogus and the link counts on all inodes which may also be bogus. Free the bitmap, the freespace tree. Flash the incore inode tree over from parent list to having full backpointers. realtime processing, if any -- (Skip to below if running in no_modify mode). Generate the realtime bitmap from the incore realtime extent map and slam the info into the realtime bitmap inode. Generate summary info from the realtime extent map. XXX if in no_modify mode, compare contents of realtime bitmap inode to the incore realtime extent map. generate the summary info from the incore realtime extent map. compare against the contents of the realtime summary inode. complain if bad. reset superblock counters, sync version numbers - Phase 6 - directory traversal -- check reference counts, attach disconnected inodes, fix up bogus directories Assumptions: all on-disk space and inode trees are structurally sound. Incore and on-disk inode trees agree on whether an inode is in use. Directories are structurally sound. All hashvalues are monotonically increasing and interior nodes are correct so lookups work. All legal directory entries point to inodes that are in use and exist. Shortform directories are fine except that the links haven't been checked for conflicts (cycles, ".." being correct, etc.). Longform directories haven't been checked for those problems either PLUS longform directories may still contain entries beginning with '/'. No zero-length entries exist (they've been deleted or converted to '/'). Root directory may or may not exist. orphange may or may not exist. Contents of either may be completely bogus. Entries may point to free or non-existent inodes. At this we point, we may need new incore structures and may be able to trash an old one (like the filesystem block map) If '/' is trashed, then reinitialize it. If no realtime inodes, make them and if necessary, slam the summary info into the realtime summary inode. Ditto with the realtime bitmap inode. Make orphanage (lost+found ???). Traverse each directory from '/' (unless it was created). Check directory structure and each directory entry. If the entry is bogus (points to a non-existent or free inode, for example), mark that entry TBD. Maintain link counts on all inodes. Currently, traversal is depth-first. Mark every inode reached as "reached" (includes bumping up link counts). If a entry points to a directory but the parent (..) disagrees, then blow away the entry. if the directory being pointed to winds up disconnected, it'll be moved to the orphanage (and the link count incremented to account for the link and the reached bit set then). If an entry points to a directory that we've already reached, then some entry is bad and should be blown away. It's easiest to blow away the current entry plus since presumably the parent entry in the reached directory points to another directory, then it's far more likely that the current entry is bogus (otherwise the parent should point at it). If an entry points to a non-existent of free inode, blow the entry away. Every time a good entry is encountered update the link count for the inode that the entry points to. After traversal, scan incore inode map for directories not reached. Go to first one and try and find its root by following .. entries. Once at root, run traversal algorithm. When algorithm terminates, move subtree root inode to the orphanage. Repeat as necessary until all disconnected directories are attached. Move all disconnected inodes to orphanage. - Phase 7: reset reference counts if required. Now traverse the on-disk inodes again, and make sure on-disk reference counts are correct. Reset if necessary. SKIP all unused inodes -- that also makes us skip the orphanage inode which we think is unused but is really used. However, the ref counts on that should be right so that's ok. --- multiple TB xfs_repair modify above to work in a couple of AGs at a time. The bitmaps should span only the current set of AGs. The key it scan the inode bmaps and keep a list of inodes that span multiple AG sets and keep the list in a data structure that's keyed off AG set # as well as inode # and also has a bit to indicate whether or not the inode will be cleared. Then in each AG set, when doing duplicate extent processing, you have to process all multi-AG-set inodes that claim blocks in the current AG set. If there's a conflict, you mark clear the inode in the current AG and you mark the multi-AG inode as "to be cleared". After going through all AGs, you can clear the to-be-cleared multi-AG-set inodes and pull them off the list. When building up the AG freespace trees, you walk the bmaps of all multi-AG-set inodes that are in the AG-set and include blocks claimed in the AG by the inode as used. This probably involves adding a phase 3-0 which would have to check all the inodes to see which ones are multi-AG-set inodes and set up the multi-AG-set inode data structure. Plus the process_dinode routines may have to be altered just a bit to do the right thing if running in tera-byte mode (call out to routines that check the multi-AG-set inodes when appropriate). To make things go faster, phase 3-0 could probably run in parallel. It should be possible to run phases 2-5 in parallel as well once the appropriate synchronization is added to the incore routines and the static directory leaf block bitmap is changed to be on the stack. Phase 7 probably can be in parallel as well. By in parallel, I mean that assuming that an AG-set contains 4 AGs, you could run 4 threads, 1 per AG in parallel to process the AG set. I don't see how phase 6 can be run in parallel though. And running Phase 8 in parallel is just silly. xfsprogs-4.9.0+nmu1ubuntu2/repair/agheader.c0000644000000000000000000003326313063067172015670 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "globals.h" #include "agheader.h" #include "protos.h" #include "err_protos.h" /* * XXX (dgc): What is the point of all the check and repair here when phase 5 * recreates the AGF/AGI/AGFL completely from scratch? */ static int verify_set_agf(xfs_mount_t *mp, xfs_agf_t *agf, xfs_agnumber_t i) { xfs_rfsblock_t agblocks; int retval = 0; /* check common fields */ if (be32_to_cpu(agf->agf_magicnum) != XFS_AGF_MAGIC) { retval = XR_AG_AGF; do_warn(_("bad magic # 0x%x for agf %d\n"), be32_to_cpu(agf->agf_magicnum), i); if (!no_modify) agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); } if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum))) { retval = XR_AG_AGF; do_warn(_("bad version # %d for agf %d\n"), be32_to_cpu(agf->agf_versionnum), i); if (!no_modify) agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); } if (be32_to_cpu(agf->agf_seqno) != i) { retval = XR_AG_AGF; do_warn(_("bad sequence # %d for agf %d\n"), be32_to_cpu(agf->agf_seqno), i); if (!no_modify) agf->agf_seqno = cpu_to_be32(i); } if (be32_to_cpu(agf->agf_length) != mp->m_sb.sb_agblocks) { if (i != mp->m_sb.sb_agcount - 1) { retval = XR_AG_AGF; do_warn(_("bad length %d for agf %d, should be %d\n"), be32_to_cpu(agf->agf_length), i, mp->m_sb.sb_agblocks); if (!no_modify) agf->agf_length = cpu_to_be32(mp->m_sb.sb_agblocks); } else { agblocks = mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * i; if (be32_to_cpu(agf->agf_length) != agblocks) { retval = XR_AG_AGF; do_warn( _("bad length %d for agf %d, should be %" PRIu64 "\n"), be32_to_cpu(agf->agf_length), i, agblocks); if (!no_modify) agf->agf_length = cpu_to_be32(agblocks); } } } /* * check first/last AGF fields. if need be, lose the free * space in the AGFL, we'll reclaim it later. */ if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp)) { do_warn(_("flfirst %d in agf %d too large (max = %zu)\n"), be32_to_cpu(agf->agf_flfirst), i, XFS_AGFL_SIZE(mp) - 1); if (!no_modify) agf->agf_flfirst = cpu_to_be32(0); } if (be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) { do_warn(_("fllast %d in agf %d too large (max = %zu)\n"), be32_to_cpu(agf->agf_fllast), i, XFS_AGFL_SIZE(mp) - 1); if (!no_modify) agf->agf_fllast = cpu_to_be32(0); } /* don't check freespace btrees -- will be checked by caller */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return retval; if (platform_uuid_compare(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) { char uu[64]; retval = XR_AG_AGF; platform_uuid_unparse(&agf->agf_uuid, uu); do_warn(_("bad uuid %s for agf %d\n"), uu, i); if (!no_modify) platform_uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid); } return retval; } static int verify_set_agi(xfs_mount_t *mp, xfs_agi_t *agi, xfs_agnumber_t agno) { xfs_rfsblock_t agblocks; int retval = 0; /* check common fields */ if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) { retval = XR_AG_AGI; do_warn(_("bad magic # 0x%x for agi %d\n"), be32_to_cpu(agi->agi_magicnum), agno); if (!no_modify) agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); } if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) { retval = XR_AG_AGI; do_warn(_("bad version # %d for agi %d\n"), be32_to_cpu(agi->agi_versionnum), agno); if (!no_modify) agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); } if (be32_to_cpu(agi->agi_seqno) != agno) { retval = XR_AG_AGI; do_warn(_("bad sequence # %d for agi %d\n"), be32_to_cpu(agi->agi_seqno), agno); if (!no_modify) agi->agi_seqno = cpu_to_be32(agno); } if (be32_to_cpu(agi->agi_length) != mp->m_sb.sb_agblocks) { if (agno != mp->m_sb.sb_agcount - 1) { retval = XR_AG_AGI; do_warn(_("bad length # %d for agi %d, should be %d\n"), be32_to_cpu(agi->agi_length), agno, mp->m_sb.sb_agblocks); if (!no_modify) agi->agi_length = cpu_to_be32(mp->m_sb.sb_agblocks); } else { agblocks = mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno; if (be32_to_cpu(agi->agi_length) != agblocks) { retval = XR_AG_AGI; do_warn( _("bad length # %d for agi %d, should be %" PRIu64 "\n"), be32_to_cpu(agi->agi_length), agno, agblocks); if (!no_modify) agi->agi_length = cpu_to_be32(agblocks); } } } /* don't check inode btree -- will be checked by caller */ if (!xfs_sb_version_hascrc(&mp->m_sb)) return retval; if (platform_uuid_compare(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) { char uu[64]; retval = XR_AG_AGI; platform_uuid_unparse(&agi->agi_uuid, uu); do_warn(_("bad uuid %s for agi %d\n"), uu, agno); if (!no_modify) platform_uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid); } return retval; } /* * superblock comparison - compare arbitrary superblock with * filesystem mount-point superblock * * the verified fields include id and geometry. * * the inprogress fields, version numbers, and counters * are allowed to differ as well as all fields after the * counters to cope with the pre-6.5 mkfs non-zeroed * secondary superblock sectors. */ static int compare_sb(xfs_mount_t *mp, xfs_sb_t *sb) { fs_geometry_t fs_geo, sb_geo; get_sb_geometry(&fs_geo, &mp->m_sb); get_sb_geometry(&sb_geo, sb); if (memcmp(&fs_geo, &sb_geo, (char *) &fs_geo.sb_shared_vn - (char *) &fs_geo)) return(XR_SB_GEO_MISMATCH); return(XR_OK); } /* * Possible fields that may have been set at mkfs time, * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog. * The quota inode fields in the secondaries should be zero. * Likewise, the sb_flags and sb_shared_vn should also be * zero and the shared version bit should be cleared for * current mkfs's. * * And everything else in the buffer beyond either sb_width, * sb_dirblklog (v2 dirs), or sb_logsectsize can be zeroed. * * Note: contrary to the name, this routine is called for all * superblocks, not just the secondary superblocks. */ static int secondary_sb_whack( struct xfs_mount *mp, struct xfs_buf *sbuf, struct xfs_sb *sb, xfs_agnumber_t i) { struct xfs_dsb *dsb = XFS_BUF_TO_SBP(sbuf); int do_bzero = 0; int size; char *ip; int rval = 0;; uuid_t tmpuuid; rval = do_bzero = 0; /* * Check for garbage beyond the last valid field. * Use field addresses instead so this code will still * work against older filesystems when the superblock * gets rev'ed again with new fields appended. * * size is the size of data which is valid for this sb. */ if (xfs_sb_version_hasmetauuid(sb)) size = offsetof(xfs_sb_t, sb_meta_uuid) + sizeof(sb->sb_meta_uuid); else if (xfs_sb_version_hascrc(sb)) size = offsetof(xfs_sb_t, sb_lsn) + sizeof(sb->sb_lsn); else if (xfs_sb_version_hasmorebits(sb)) size = offsetof(xfs_sb_t, sb_bad_features2) + sizeof(sb->sb_bad_features2); else if (xfs_sb_version_haslogv2(sb)) size = offsetof(xfs_sb_t, sb_logsunit) + sizeof(sb->sb_logsunit); else if (xfs_sb_version_hassector(sb)) size = offsetof(xfs_sb_t, sb_logsectsize) + sizeof(sb->sb_logsectsize); else /* only support dirv2 or more recent */ size = offsetof(xfs_sb_t, sb_dirblklog) + sizeof(sb->sb_dirblklog); /* Check the buffer we read from disk for garbage outside size */ for (ip = XFS_BUF_PTR(sbuf) + size; ip < XFS_BUF_PTR(sbuf) + mp->m_sb.sb_sectsize; ip++) { if (*ip) { do_bzero = 1; break; } } if (do_bzero) { rval |= XR_AG_SB_SEC; if (!no_modify) { do_warn( _("zeroing unused portion of %s superblock (AG #%u)\n"), !i ? _("primary") : _("secondary"), i); /* * zero both the in-memory sb and the disk buffer, * because the former was read from disk and * may contain newer version fields that shouldn't * be set, and the latter is never updated past * the last field - just zap them both. */ memcpy(&tmpuuid, &sb->sb_meta_uuid, sizeof(uuid_t)); memset((void *)((intptr_t)sb + size), 0, mp->m_sb.sb_sectsize - size); memset(XFS_BUF_PTR(sbuf) + size, 0, mp->m_sb.sb_sectsize - size); /* Preserve meta_uuid so we don't fail uuid checks */ memcpy(&sb->sb_meta_uuid, &tmpuuid, sizeof(uuid_t)); } else do_warn( _("would zero unused portion of %s superblock (AG #%u)\n"), !i ? _("primary") : _("secondary"), i); } /* * now look for the fields we can manipulate directly. * if we did a zero and that zero could have included * the field in question, just silently reset it. otherwise, * complain. * * for now, just zero the flags field since only * the readonly flag is used */ if (sb->sb_flags) { if (!no_modify) sb->sb_flags = 0; if (!do_bzero) { rval |= XR_AG_SB; do_warn(_("bad flags field in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } /* * quota inodes and flags in secondary superblocks are never set by * mkfs. However, they could be set in a secondary if a fs with quotas * was growfs'ed since growfs copies the new primary into the * secondaries. * * Also, the in-core inode flags now have different meaning to the * on-disk flags, and so libxfs_sb_to_disk cannot directly write the * sb_gquotino/sb_pquotino fields without specific sb_qflags being set. * Hence we need to zero those fields directly in the sb buffer here. */ if (sb->sb_inprogress == 1 && sb->sb_uquotino != NULLFSINO) { if (!no_modify) sb->sb_uquotino = 0; if (!do_bzero) { rval |= XR_AG_SB; do_warn( _("non-null user quota inode field in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } if (sb->sb_inprogress == 1 && sb->sb_gquotino != NULLFSINO) { if (!no_modify) { sb->sb_gquotino = 0; dsb->sb_gquotino = 0; } if (!do_bzero) { rval |= XR_AG_SB; do_warn( _("non-null group quota inode field in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } /* * Note that sb_pquotino is not considered a valid sb field for pre-v5 * superblocks. If it is anything other than 0 it is considered garbage * data beyond the valid sb and explicitly zeroed above. */ if (xfs_sb_version_has_pquotino(&mp->m_sb) && sb->sb_inprogress == 1 && sb->sb_pquotino != NULLFSINO) { if (!no_modify) { sb->sb_pquotino = 0; dsb->sb_pquotino = 0; } if (!do_bzero) { rval |= XR_AG_SB; do_warn( _("non-null project quota inode field in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } if (sb->sb_inprogress == 1 && sb->sb_qflags) { if (!no_modify) sb->sb_qflags = 0; if (!do_bzero) { rval |= XR_AG_SB; do_warn(_("non-null quota flags in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } /* * if the secondaries agree on a stripe unit/width or inode * alignment, those fields ought to be valid since they are * written at mkfs time (and the corresponding sb version bits * are set). */ if (!xfs_sb_version_hasalign(sb) && sb->sb_inoalignmt != 0) { if (!no_modify) sb->sb_inoalignmt = 0; if (!do_bzero) { rval |= XR_AG_SB; do_warn( _("bad inode alignment field in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } if (!xfs_sb_version_hasdalign(sb) && (sb->sb_unit != 0 || sb->sb_width != 0)) { if (!no_modify) sb->sb_unit = sb->sb_width = 0; if (!do_bzero) { rval |= XR_AG_SB; do_warn( _("bad stripe unit/width fields in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } if (!xfs_sb_version_hassector(sb) && (sb->sb_sectsize != BBSIZE || sb->sb_sectlog != BBSHIFT || sb->sb_logsectsize != 0 || sb->sb_logsectlog != 0)) { if (!no_modify) { sb->sb_sectsize = BBSIZE; sb->sb_sectlog = BBSHIFT; sb->sb_logsectsize = 0; sb->sb_logsectlog = 0; } if (!do_bzero) { rval |= XR_AG_SB; do_warn( _("bad log/data device sector size fields in superblock %d\n"), i); } else rval |= XR_AG_SB_SEC; } return(rval); } /* * verify and reset the ag header if required. * * lower 4 bits of rval are set depending on what got modified. * (see agheader.h for more details) * * NOTE -- this routine does not tell the user that it has * altered things. Rather, it is up to the caller to do so * using the bits encoded into the return value. */ int verify_set_agheader(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb, xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i) { int rval = 0; int status = XR_OK; int status_sb = XR_OK; status = verify_sb(sbuf->b_addr, sb, (i == 0)); if (status != XR_OK) { do_warn(_("bad on-disk superblock %d - %s\n"), i, err_string(status)); } status_sb = compare_sb(mp, sb); if (status_sb != XR_OK) { do_warn(_("primary/secondary superblock %d conflict - %s\n"), i, err_string(status_sb)); } if (status != XR_OK || status_sb != XR_OK) { if (!no_modify) { *sb = mp->m_sb; /* * clear the more transient fields */ sb->sb_inprogress = 1; sb->sb_icount = 0; sb->sb_ifree = 0; sb->sb_fdblocks = 0; sb->sb_frextents = 0; sb->sb_qflags = 0; } rval |= XR_AG_SB; } rval |= secondary_sb_whack(mp, sbuf, sb, i); rval |= verify_set_agf(mp, agf, i); rval |= verify_set_agi(mp, agi, i); return(rval); } xfsprogs-4.9.0+nmu1ubuntu2/repair/agheader.h0000644000000000000000000000647213063067172015677 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ typedef struct fs_geometry { /* * these types should match the superblock types */ __uint32_t sb_blocksize; /* blocksize (bytes) */ xfs_rfsblock_t sb_dblocks; /* # data blocks */ xfs_rfsblock_t sb_rblocks; /* # realtime blocks */ xfs_rtblock_t sb_rextents; /* # realtime extents */ xfs_fsblock_t sb_logstart; /* starting log block # */ xfs_agblock_t sb_rextsize; /* realtime extent size (blocks )*/ xfs_agblock_t sb_agblocks; /* # of blocks per ag */ xfs_agnumber_t sb_agcount; /* # of ags */ xfs_extlen_t sb_rbmblocks; /* # of rt bitmap blocks */ xfs_extlen_t sb_logblocks; /* # of log blocks */ __uint16_t sb_sectsize; /* volume sector size (bytes) */ __uint16_t sb_inodesize; /* inode size (bytes) */ __uint8_t sb_imax_pct; /* max % of fs for inode space */ /* * these don't have to match the superblock types but are placed * before sb_shared_vn because these values don't have to be * checked manually. These variables will be set only on * filesystems with dependably good (fully initialized) * secondary superblock sectors, will be stamped in all * superblocks at mkfs time, and are features that cannot * be downgraded unless all superblocks in the filesystem * are rewritten. */ int sb_extflgbit; /* extent flag feature bit set */ /* * fields after this point have to be checked manually in compare_sb() */ __uint8_t sb_shared_vn; /* shared version number */ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ __uint32_t sb_unit; /* stripe or raid unit */ __uint32_t sb_width; /* stripe or width unit */ /* * these don't have to match, they track superblock properties * that could have been upgraded and/or downgraded during * run-time so that the primary superblock has them but the * secondaries do not. * Plus, they have associated data fields whose data fields may * be corrupt in cases where the filesystem was made on a * pre-6.5 campus alpha mkfs and the feature was enabled on * the filesystem later. */ int sb_ialignbit; /* sb has inode alignment bit set */ int sb_salignbit; /* sb has stripe alignment bit set */ int sb_sharedbit; /* sb has inode alignment bit set */ int sb_fully_zeroed; /* has zeroed secondary sb sectors */ } fs_geometry_t; typedef struct fs_geo_list { struct fs_geo_list *next; int refs; int index; fs_geometry_t geo; } fs_geo_list_t; /* * fields for sb_last_nonzero */ #define XR_SB_COUNTERS 0x0001 #define XR_SB_INOALIGN 0x0002 #define XR_SB_SALIGN 0x0004 /* * what got modified by verify_set_* routines */ #define XR_AG_SB 0x1 #define XR_AG_AGF 0x2 #define XR_AG_AGI 0x4 #define XR_AG_SB_SEC 0x8 xfsprogs-4.9.0+nmu1ubuntu2/repair/attr_repair.c0000644000000000000000000010751413063067172016445 0ustar /* * Copyright (c) 2000-2002,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "globals.h" #include "err_protos.h" #include "attr_repair.h" #include "dinode.h" #include "bmap.h" #include "protos.h" #include "dir2.h" #include "da_util.h" static int xfs_acl_valid(struct xfs_mount *mp, struct xfs_acl *daclp); static int xfs_mac_valid(xfs_mac_label_t *lp); /* * da node check/verify functions that the attribute tree relies on are first in * the file before the actual attribute code. This used to be shared with the * dir v1 code, but that format is no longer supported yb the userspace * utilities and hence is now specific to the attribute tree implementation. */ #define XR_DA_LEAF_MAPSIZE XFS_ATTR_LEAF_MAPSIZE typedef unsigned char da_freemap_t; /* * Allocate a freespace map for directory or attr leaf blocks (1 bit per byte) * 1 == used, 0 == free. */ static da_freemap_t * alloc_da_freemap(struct xfs_mount *mp) { return calloc(1, mp->m_sb.sb_blocksize / NBBY); } /* * Set the he range [start, stop) in the directory freemap. * * Returns 1 if there is a conflict or 0 if everything's good. * * Within a char, the lowest bit of the char represents the byte with * the smallest address */ static int set_da_freemap(xfs_mount_t *mp, da_freemap_t *map, int start, int stop) { const da_freemap_t mask = 0x1; int i; if (start > stop) { /* * allow == relation since [x, x) claims 1 byte */ do_warn(_("bad range claimed [%d, %d) in da block\n"), start, stop); return(1); } if (stop > mp->m_sb.sb_blocksize) { do_warn( _("byte range end [%d %d) in da block larger than blocksize %d\n"), start, stop, mp->m_sb.sb_blocksize); return(1); } for (i = start; i < stop; i ++) { if (map[i / NBBY] & (mask << i % NBBY)) { do_warn(_("multiply claimed byte %d in da block\n"), i); return(1); } map[i / NBBY] |= (mask << i % NBBY); } return(0); } /* * For attribute repair, there are 3 formats to worry about. First, is * shortform attributes which reside in the inode. Second is the leaf * form, and lastly the btree. Much of this models after the directory * structure so code resembles the directory repair cases. * For shortform case, if an attribute looks corrupt, it is removed. * If that leaves the shortform down to 0 attributes, it's okay and * will appear to just have a null attribute fork. Some checks are done * for validity of the value field based on what the security needs are. * Calls will be made to xfs_mac_valid or xfs_acl_valid routines if the * security attributes exist. They will be cleared if invalid. * No other values will be checked. The DMF folks do not have current * requirements, but may in the future. * * For leaf block attributes, it requires more processing. One sticky * point is that the attributes can be local (within the leaf) or * remote (outside the leaf in other blocks). Thinking of local only * if you get a bad attribute, and want to delete just one, it's a-okay * if it remains large enough to still be a leaf block attribute. Otherwise, * it may have to be converted to shortform. How to convert this and when * is an issue. This call is happening in Phase3. Phase5 will capture empty * blocks, but Phase6 allows you to use the libxfs library which knows * how to handle attributes in the kernel for converting formats. What we * could do is mark an attribute to be cleared now, but in phase6 somehow * have it cleared for real and then the format changed to shortform if * applicable. Since this requires more work than I anticipate can be * accomplished for the next release, we will instead just say any bad * attribute in the leaf block will make the entire attribute fork be * cleared. The simplest way to do that is to ignore the leaf format, and * call clear_dinode_attr to just make a shortform attribute fork with * zero entries. * * Another issue with handling repair on leaf attributes is the remote * blocks. To make sure that they look good and are not used multiple times * by the attribute fork, some mechanism to keep track of all them is necessary. * Do this in the future, time permitting. For now, note that there is no * check for remote blocks and their allocations. * * For btree formatted attributes, the model can follow directories. That * would mean go down the tree to the leftmost leaf. From there moving down * the links and processing each. They would call back up the tree, to verify * that the tree structure is okay. Any problems will result in the attribute * fork being emptied and put in shortform format. */ /* * This routine just checks what security needs are for attribute values * only called when root flag is set, otherwise these names could exist in * in user attribute land without a conflict. * If value is non-zero, then a remote attribute is being passed in */ static int valuecheck( struct xfs_mount *mp, char *namevalue, char *value, int namelen, int valuelen) { /* for proper alignment issues, get the structs and memmove the values */ xfs_mac_label_t macl; void *valuep; int clearit = 0; if ((namelen == SGI_ACL_FILE_SIZE && strncmp(namevalue, SGI_ACL_FILE, SGI_ACL_FILE_SIZE) == 0) || (namelen == SGI_ACL_DEFAULT_SIZE && strncmp(namevalue, SGI_ACL_DEFAULT, SGI_ACL_DEFAULT_SIZE) == 0)) { if (value == NULL) { valuep = malloc(valuelen); if (!valuep) do_error(_("No memory for ACL check!\n")); memcpy(valuep, namevalue + namelen, valuelen); } else valuep = value; if (xfs_acl_valid(mp, valuep) != 0) { clearit = 1; do_warn( _("entry contains illegal value in attribute named SGI_ACL_FILE " "or SGI_ACL_DEFAULT\n")); } if (valuep != value) free(valuep); } else if (strncmp(namevalue, SGI_MAC_FILE, SGI_MAC_FILE_SIZE) == 0) { if (value == NULL) { memset(&macl, 0, sizeof(xfs_mac_label_t)); memmove(&macl, namevalue+namelen, valuelen); valuep = &macl; } else valuep = value; if (xfs_mac_valid((xfs_mac_label_t *)valuep) != 1) { /* 1 is valid */ /* * if sysconf says MAC enabled, * temp = mac_from_text("msenhigh/mintlow", NULL) * copy it to value, update valuelen, totsize * This causes pushing up or down of all following * attributes, forcing a attribute format change!! * else clearit = 1; */ clearit = 1; do_warn( _("entry contains illegal value in attribute named SGI_MAC_LABEL\n")); } } else if (strncmp(namevalue, SGI_CAP_FILE, SGI_CAP_FILE_SIZE) == 0) { if ( valuelen != sizeof(xfs_cap_set_t)) { clearit = 1; do_warn( _("entry contains illegal value in attribute named SGI_CAP_FILE\n")); } } return(clearit); } /* * this routine validates the attributes in shortform format. * a non-zero return repair value means certain attributes are bogus * and were cleared if possible. Warnings do not generate error conditions * if you cannot modify the structures. repair is set to 1, if anything * was fixed. */ static int process_shortform_attr( struct xfs_mount *mp, xfs_ino_t ino, xfs_dinode_t *dip, int *repair) { xfs_attr_shortform_t *asf; xfs_attr_sf_entry_t *currententry, *nextentry, *tempentry; int i, junkit; int currentsize, remainingspace; *repair = 0; asf = (xfs_attr_shortform_t *) XFS_DFORK_APTR(dip); /* Assumption: hdr.totsize is less than a leaf block and was checked * by lclinode for valid sizes. Check the count though. */ if (asf->hdr.count == 0) /* then the total size should just be the header length */ if (be16_to_cpu(asf->hdr.totsize) != sizeof(xfs_attr_sf_hdr_t)) { /* whoops there's a discrepancy. Clear the hdr */ if (!no_modify) { do_warn( _("there are no attributes in the fork for inode %" PRIu64 "\n"), ino); asf->hdr.totsize = cpu_to_be16(sizeof(xfs_attr_sf_hdr_t)); *repair = 1; return(1); } else { do_warn( _("would junk the attribute fork since count is 0 for inode %" PRIu64 "\n"), ino); return(1); } } currentsize = sizeof(xfs_attr_sf_hdr_t); remainingspace = be16_to_cpu(asf->hdr.totsize) - currentsize; nextentry = &asf->list[0]; for (i = 0; i < asf->hdr.count; i++) { currententry = nextentry; junkit = 0; /* don't go off the end if the hdr.count was off */ if ((currentsize + (sizeof(xfs_attr_sf_entry_t) - 1)) > be16_to_cpu(asf->hdr.totsize)) break; /* get out and reset count and totSize */ /* if the namelen is 0, can't get to the rest of the entries */ if (currententry->namelen == 0) { do_warn(_("zero length name entry in attribute fork,")); if (!no_modify) { do_warn( _(" truncating attributes for inode %" PRIu64 " to %d\n"), ino, i); *repair = 1; break; /* and then update hdr fields */ } else { do_warn( _(" would truncate attributes for inode %" PRIu64 " to %d\n"), ino, i); break; } } else { /* It's okay to have a 0 length valuelen, but do a * rough check to make sure we haven't gone outside of * totsize. */ if (remainingspace < currententry->namelen || ((remainingspace - currententry-> namelen) < currententry->valuelen)) { do_warn( _("name or value attribute lengths are too large,\n")); if (!no_modify) { do_warn( _(" truncating attributes for inode %" PRIu64 " to %d\n"), ino, i); *repair = 1; break; /* and then update hdr fields */ } else { do_warn( _(" would truncate attributes for inode %" PRIu64 " to %d\n"), ino, i); break; } } } /* namecheck checks for / and null terminated for file names. * attributes names currently follow the same rules. */ if (namecheck((char *)¤tentry->nameval[0], currententry->namelen)) { do_warn( _("entry contains illegal character in shortform attribute name\n")); junkit = 1; } if (currententry->flags & XFS_ATTR_INCOMPLETE) { do_warn( _("entry has INCOMPLETE flag on in shortform attribute\n")); junkit = 1; } /* Only check values for root security attributes */ if (currententry->flags & XFS_ATTR_ROOT) junkit |= valuecheck(mp, (char *)¤tentry->nameval[0], NULL, currententry->namelen, currententry->valuelen); remainingspace = remainingspace - XFS_ATTR_SF_ENTSIZE(currententry); if (junkit) { if (!no_modify) { /* get rid of only this entry */ do_warn( _("removing attribute entry %d for inode %" PRIu64 "\n"), i, ino); tempentry = (xfs_attr_sf_entry_t *) ((intptr_t) currententry + XFS_ATTR_SF_ENTSIZE(currententry)); memmove(currententry,tempentry,remainingspace); asf->hdr.count -= 1; i--; /* no worries, it will wrap back to 0 */ *repair = 1; continue; /* go back up now */ } else { do_warn( _("would remove attribute entry %d for inode %" PRIu64 "\n"), i, ino); } } /* Let's get ready for the next entry... */ nextentry = (xfs_attr_sf_entry_t *)((intptr_t) nextentry + XFS_ATTR_SF_ENTSIZE(currententry)); currentsize = currentsize + XFS_ATTR_SF_ENTSIZE(currententry); } /* end the loop */ if (asf->hdr.count != i) { if (no_modify) { do_warn( _("would have corrected attribute entry count in inode %" PRIu64 " from %d to %d\n"), ino, asf->hdr.count, i); } else { do_warn( _("corrected attribute entry count in inode %" PRIu64 ", was %d, now %d\n"), ino, asf->hdr.count, i); asf->hdr.count = i; *repair = 1; } } /* ASSUMPTION: currentsize <= totsize */ if (be16_to_cpu(asf->hdr.totsize) != currentsize) { if (no_modify) { do_warn( _("would have corrected attribute totsize in inode %" PRIu64 " from %d to %d\n"), ino, be16_to_cpu(asf->hdr.totsize), currentsize); } else { do_warn( _("corrected attribute entry totsize in inode %" PRIu64 ", was %d, now %d\n"), ino, be16_to_cpu(asf->hdr.totsize), currentsize); asf->hdr.totsize = cpu_to_be16(currentsize); *repair = 1; } } return(*repair); } /* This routine brings in blocks from disk one by one and assembles them * in the value buffer. If get_bmapi gets smarter later to return an extent * or list of extents, that would be great. For now, we don't expect too * many blocks per remote value, so one by one is sufficient. */ static int rmtval_get(xfs_mount_t *mp, xfs_ino_t ino, blkmap_t *blkmap, xfs_dablk_t blocknum, int valuelen, char* value) { xfs_fsblock_t bno; xfs_buf_t *bp; int clearit = 0, i = 0, length = 0, amountdone = 0; int hdrsize = 0; if (xfs_sb_version_hascrc(&mp->m_sb)) hdrsize = sizeof(struct xfs_attr3_rmt_hdr); /* ASSUMPTION: valuelen is a valid number, so use it for looping */ /* Note that valuelen is not a multiple of blocksize */ while (amountdone < valuelen) { bno = blkmap_get(blkmap, blocknum + i); if (bno == NULLFSBLOCK) { do_warn( _("remote block for attributes of inode %" PRIu64 " is missing\n"), ino); clearit = 1; break; } bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), XFS_FSB_TO_BB(mp, 1), 0, &xfs_attr3_rmt_buf_ops); if (!bp) { do_warn( _("can't read remote block for attributes of inode %" PRIu64 "\n"), ino); clearit = 1; break; } if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) { do_warn( _("Corrupt remote block for attributes of inode %" PRIu64 "\n"), ino); clearit = 1; break; } ASSERT(mp->m_sb.sb_blocksize == XFS_BUF_COUNT(bp)); length = MIN(XFS_BUF_COUNT(bp) - hdrsize, valuelen - amountdone); memmove(value, bp->b_addr + hdrsize, length); amountdone += length; value += length; i++; libxfs_putbuf(bp); } return (clearit); } /* The block is read in. The magic number and forward / backward * links are checked by the caller process_leaf_attr. * If any problems occur the routine returns with non-zero. In * this case the next step is to clear the attribute fork, by * changing it to shortform and zeroing it out. Forkoff need not * be changed. */ static int process_leaf_attr_local( struct xfs_mount *mp, xfs_attr_leafblock_t *leaf, int i, xfs_attr_leaf_entry_t *entry, xfs_dahash_t last_hashval, xfs_dablk_t da_bno, xfs_ino_t ino) { xfs_attr_leaf_name_local_t *local; local = xfs_attr3_leaf_name_local(leaf, i); if (local->namelen == 0 || namecheck((char *)&local->nameval[0], local->namelen)) { do_warn( _("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"), i, da_bno, ino, local->namelen); return -1; } /* Check on the hash value. Checking order of values * is not necessary, since one wrong clears the whole * fork. If the ordering's wrong, it's caught here or * the kernel code has a bug with transaction logging * or attributes itself. Being paranoid, let's check * ordering anyway in case both the name value and the * hashvalue were wrong but matched. Unlikely, however. */ if (be32_to_cpu(entry->hashval) != libxfs_da_hashname( &local->nameval[0], local->namelen) || be32_to_cpu(entry->hashval) < last_hashval) { do_warn( _("bad hashvalue for attribute entry %d in attr block %u, inode %" PRIu64 "\n"), i, da_bno, ino); return -1; } /* Only check values for root security attributes */ if (entry->flags & XFS_ATTR_ROOT) { if (valuecheck(mp, (char *)&local->nameval[0], NULL, local->namelen, be16_to_cpu(local->valuelen))) { do_warn( _("bad security value for attribute entry %d in attr block %u, inode %" PRIu64 "\n"), i, da_bno, ino); return -1; } } return xfs_attr_leaf_entsize_local(local->namelen, be16_to_cpu(local->valuelen)); } static int process_leaf_attr_remote( xfs_attr_leafblock_t *leaf, int i, xfs_attr_leaf_entry_t *entry, xfs_dahash_t last_hashval, xfs_dablk_t da_bno, xfs_ino_t ino, xfs_mount_t *mp, blkmap_t *blkmap) { xfs_attr_leaf_name_remote_t *remotep; char* value; remotep = xfs_attr3_leaf_name_remote(leaf, i); if (remotep->namelen == 0 || namecheck((char *)&remotep->name[0], remotep->namelen) || be32_to_cpu(entry->hashval) != libxfs_da_hashname((unsigned char *)&remotep->name[0], remotep->namelen) || be32_to_cpu(entry->hashval) < last_hashval || be32_to_cpu(remotep->valueblk) == 0) { do_warn( _("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64 "\n"), i, da_bno, ino); return -1; } if (!(entry->flags & XFS_ATTR_ROOT)) goto out; value = malloc(be32_to_cpu(remotep->valuelen)); if (value == NULL) { do_warn( _("cannot malloc enough for remotevalue attribute for inode %" PRIu64 "\n"), ino); do_warn(_("SKIPPING this remote attribute\n")); goto out; } if (rmtval_get(mp, ino, blkmap, be32_to_cpu(remotep->valueblk), be32_to_cpu(remotep->valuelen), value)) { do_warn( _("remote attribute get failed for entry %d, inode %" PRIu64 "\n"), i, ino); goto bad_free_out; } if (valuecheck(mp, (char *)&remotep->name[0], value, remotep->namelen, be32_to_cpu(remotep->valuelen))) { do_warn( _("remote attribute value check failed for entry %d, inode %" PRIu64 "\n"), i, ino); goto bad_free_out; } free(value); out: return xfs_attr_leaf_entsize_remote(remotep->namelen); bad_free_out: free(value); return -1; } static int process_leaf_attr_block( xfs_mount_t *mp, xfs_attr_leafblock_t *leaf, xfs_dablk_t da_bno, xfs_ino_t ino, blkmap_t *blkmap, xfs_dahash_t last_hashval, xfs_dahash_t *current_hashval, int *repair) { xfs_attr_leaf_entry_t *entry; int i, start, stop, clearit, usedbs, firstb, thissize; da_freemap_t *attr_freemap; struct xfs_attr3_icleaf_hdr leafhdr; xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); clearit = usedbs = 0; firstb = mp->m_sb.sb_blocksize; stop = xfs_attr3_leaf_hdr_size(leaf); /* does the count look sorta valid? */ if (!leafhdr.count || leafhdr.count * sizeof(xfs_attr_leaf_entry_t) + stop > mp->m_sb.sb_blocksize) { do_warn( _("bad attribute count %d in attr block %u, inode %" PRIu64 "\n"), leafhdr.count, da_bno, ino); return 1; } attr_freemap = alloc_da_freemap(mp); (void) set_da_freemap(mp, attr_freemap, 0, stop); /* go thru each entry checking for problems */ for (i = 0, entry = xfs_attr3_leaf_entryp(leaf); i < leafhdr.count; i++, entry++) { /* check if index is within some boundary. */ if (be16_to_cpu(entry->nameidx) > mp->m_sb.sb_blocksize) { do_warn( _("bad attribute nameidx %d in attr block %u, inode %" PRIu64 "\n"), be16_to_cpu(entry->nameidx), da_bno, ino); clearit = 1; break; } if (entry->flags & XFS_ATTR_INCOMPLETE) { /* we are inconsistent state. get rid of us */ do_warn( _("attribute entry #%d in attr block %u, inode %" PRIu64 " is INCOMPLETE\n"), i, da_bno, ino); clearit = 1; break; } /* mark the entry used */ start = (intptr_t)entry - (intptr_t)leaf; stop = start + sizeof(xfs_attr_leaf_entry_t); if (set_da_freemap(mp, attr_freemap, start, stop)) { do_warn( _("attribute entry %d in attr block %u, inode %" PRIu64 " claims already used space\n"), i, da_bno, ino); clearit = 1; break; /* got an overlap */ } if (entry->flags & XFS_ATTR_LOCAL) thissize = process_leaf_attr_local(mp, leaf, i, entry, last_hashval, da_bno, ino); else thissize = process_leaf_attr_remote(leaf, i, entry, last_hashval, da_bno, ino, mp, blkmap); if (thissize < 0) { clearit = 1; break; } *current_hashval = last_hashval = be32_to_cpu(entry->hashval); if (set_da_freemap(mp, attr_freemap, be16_to_cpu(entry->nameidx), be16_to_cpu(entry->nameidx) + thissize)) { do_warn( _("attribute entry %d in attr block %u, inode %" PRIu64 " claims used space\n"), i, da_bno, ino); clearit = 1; break; /* got an overlap */ } usedbs += thissize; if (be16_to_cpu(entry->nameidx) < firstb) firstb = be16_to_cpu(entry->nameidx); } /* end the loop */ if (!clearit) { /* verify the header information is correct */ /* if the holes flag is set, don't reset first_used unless it's * pointing to used bytes. we're being conservative here * since the block will get compacted anyhow by the kernel. */ if ((leafhdr.holes == 0 && firstb != leafhdr.firstused) || leafhdr.firstused > firstb) { if (!no_modify) { do_warn( _("- resetting first used heap value from %d to %d in " "block %u of attribute fork of inode %" PRIu64 "\n"), leafhdr.firstused, firstb, da_bno, ino); leafhdr.firstused = firstb; *repair = 1; } else { do_warn( _("- would reset first used value from %d to %d in " "block %u of attribute fork of inode %" PRIu64 "\n"), leafhdr.firstused, firstb, da_bno, ino); } } if (usedbs != leafhdr.usedbytes) { if (!no_modify) { do_warn( _("- resetting usedbytes cnt from %d to %d in " "block %u of attribute fork of inode %" PRIu64 "\n"), leafhdr.usedbytes, usedbs, da_bno, ino); leafhdr.usedbytes = usedbs; *repair = 1; } else { do_warn( _("- would reset usedbytes cnt from %d to %d in " "block %u of attribute fork of %" PRIu64 "\n"), leafhdr.usedbytes, usedbs, da_bno, ino); } } /* there's a lot of work in process_leaf_dir_block to go thru * checking for holes and compacting if appropiate. I don't think * attributes need all that, so let's just leave the holes. If * we discover later that this is a good place to do compaction * we can add it then. */ } /* * If we're just going to zap the block, don't pretend like we * repaired it, because repairing the block stops the clear * operation. */ if (clearit) *repair = 0; if (*repair) xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo, leaf, &leafhdr); free(attr_freemap); return (clearit); /* and repair */ } /* * returns 0 if the attribute fork is ok, 1 if it has to be junked. */ static int process_leaf_attr_level(xfs_mount_t *mp, da_bt_cursor_t *da_cursor) { int repair; xfs_attr_leafblock_t *leaf; xfs_buf_t *bp; xfs_ino_t ino; xfs_fsblock_t dev_bno; xfs_dablk_t da_bno; xfs_dablk_t prev_bno; xfs_dahash_t current_hashval = 0; xfs_dahash_t greatest_hashval; struct xfs_attr3_icleaf_hdr leafhdr; da_bno = da_cursor->level[0].bno; ino = da_cursor->ino; prev_bno = 0; do { repair = 0; dev_bno = blkmap_get(da_cursor->blkmap, da_bno); /* * 0 is the root block and no block * pointer can point to the root block of the btree */ ASSERT(da_bno != 0); if (dev_bno == NULLFSBLOCK) { do_warn( _("can't map block %u for attribute fork for inode %" PRIu64 "\n"), da_bno, ino); goto error_out; } bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, dev_bno), XFS_FSB_TO_BB(mp, 1), 0, &xfs_attr3_leaf_buf_ops); if (!bp) { do_warn( _("can't read file block %u (fsbno %" PRIu64 ") for attribute fork of inode %" PRIu64 "\n"), da_bno, dev_bno, ino); goto error_out; } leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); /* check magic number for leaf directory btree block */ if (!(leafhdr.magic == XFS_ATTR_LEAF_MAGIC || leafhdr.magic == XFS_ATTR3_LEAF_MAGIC)) { do_warn( _("bad attribute leaf magic %#x for inode %" PRIu64 "\n"), leafhdr.magic, ino); libxfs_putbuf(bp); goto error_out; } /* * for each block, process the block, verify its path, * then get next block. update cursor values along the way */ if (process_leaf_attr_block(mp, leaf, da_bno, ino, da_cursor->blkmap, current_hashval, &greatest_hashval, &repair)) { libxfs_putbuf(bp); goto error_out; } /* * index can be set to hdr.count so match the * indexes of the interior blocks -- which at the * end of the block will point to 1 after the final * real entry in the block */ da_cursor->level[0].hashval = greatest_hashval; da_cursor->level[0].bp = bp; da_cursor->level[0].bno = da_bno; da_cursor->level[0].index = leafhdr.count; da_cursor->level[0].dirty = repair; if (leafhdr.back != prev_bno) { do_warn( _("bad sibling back pointer for block %u in attribute fork for inode %" PRIu64 "\n"), da_bno, ino); libxfs_putbuf(bp); goto error_out; } prev_bno = da_bno; da_bno = leafhdr.forw; if (da_bno != 0) { if (verify_da_path(mp, da_cursor, 0, XFS_ATTR_FORK)) { libxfs_putbuf(bp); goto error_out; } } current_hashval = greatest_hashval; /* * If block looks ok but CRC didn't match, make sure to * recompute it. */ if (!no_modify && bp->b_error == -EFSBADCRC) repair++; if (repair && !no_modify) libxfs_writebuf(bp, 0); else libxfs_putbuf(bp); } while (da_bno != 0); if (verify_final_da_path(mp, da_cursor, 0, XFS_ATTR_FORK)) { /* * verify the final path up (right-hand-side) if still ok */ do_warn( _("bad hash path in attribute fork for inode %" PRIu64 "\n"), da_cursor->ino); goto error_out; } /* releases all buffers holding interior btree blocks */ release_da_cursor(mp, da_cursor, 0); return(0); error_out: /* release all buffers holding interior btree blocks */ err_release_da_cursor(mp, da_cursor, 0); return(1); } /* * a node directory is a true btree -- where the attribute fork * has gotten big enough that it is represented as a non-trivial (e.g. * has more than just a block) btree. * * Note that if we run into any problems, we will trash the attribute fork. * * returns 0 if things are ok, 1 if bad * Note this code has been based off process_node_dir. */ static int process_node_attr( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, blkmap_t *blkmap) { xfs_dablk_t bno; int error = 0; da_bt_cursor_t da_cursor; /* * try again -- traverse down left-side of tree until we hit * the left-most leaf block setting up the btree cursor along * the way. Then walk the leaf blocks left-to-right, calling * a parent-verification routine each time we traverse a block. */ memset(&da_cursor, 0, sizeof(da_bt_cursor_t)); da_cursor.active = 0; da_cursor.ino = ino; da_cursor.dip = dip; da_cursor.greatest_bno = 0; da_cursor.blkmap = blkmap; /* * now process interior node. don't have any buffers held in this path. */ error = traverse_int_dablock(mp, &da_cursor, &bno, XFS_ATTR_FORK); if (error == 0) return(1); /* 0 means unsuccessful */ /* * now pass cursor and bno into leaf-block processing routine * the leaf dir level routine checks the interior paths * up to the root including the final right-most path. */ return (process_leaf_attr_level(mp, &da_cursor)); } /* check v5 metadata */ static int __check_attr_header( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino) { struct xfs_da3_blkinfo *info = bp->b_addr; if (info->hdr.magic != cpu_to_be16(XFS_ATTR3_LEAF_MAGIC) && info->hdr.magic != cpu_to_be16(XFS_DA3_NODE_MAGIC)) return 0; /* verify owner */ if (be64_to_cpu(info->owner) != ino) { do_warn( _("expected owner inode %" PRIu64 ", got %llu, attr block %" PRIu64 "\n"), ino, be64_to_cpu(info->owner), bp->b_bn); return 1; } /* verify block number */ if (be64_to_cpu(info->blkno) != bp->b_bn) { do_warn( _("expected block %" PRIu64 ", got %llu, inode %" PRIu64 "attr block\n"), bp->b_bn, be64_to_cpu(info->blkno), ino); return 1; } /* verify uuid */ if (platform_uuid_compare(&info->uuid, &mp->m_sb.sb_meta_uuid) != 0) { do_warn( _("wrong FS UUID, inode %" PRIu64 " attr block %" PRIu64 "\n"), ino, bp->b_bn); return 1; } return 0; } /* * Start processing for a leaf or fuller btree. * A leaf directory is one where the attribute fork is too big for * the inode but is small enough to fit into one btree block * outside the inode. This code is modelled after process_leaf_dir_block. * * returns 0 if things are ok, 1 if bad (attributes needs to be junked) * repair is set, if anything was changed, but attributes can live thru it */ static int process_longform_attr( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, blkmap_t *blkmap, int *repair) /* out - 1 if something was fixed */ { xfs_attr_leafblock_t *leaf; xfs_fsblock_t bno; xfs_buf_t *bp; xfs_dahash_t next_hashval; int repairlinks = 0; struct xfs_attr3_icleaf_hdr leafhdr; int error; *repair = 0; bno = blkmap_get(blkmap, 0); if ( bno == NULLFSBLOCK ) { if (dip->di_aformat == XFS_DINODE_FMT_EXTENTS && be16_to_cpu(dip->di_anextents) == 0) return(0); /* the kernel can handle this state */ do_warn( _("block 0 of inode %" PRIu64 " attribute fork is missing\n"), ino); return(1); } /* FIX FOR bug 653709 -- EKN */ if (mp->m_sb.sb_agcount < XFS_FSB_TO_AGNO(mp, bno)) { do_warn( _("agno of attribute fork of inode %" PRIu64 " out of regular partition\n"), ino); return(1); } bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), XFS_FSB_TO_BB(mp, 1), 0, &xfs_da3_node_buf_ops); if (!bp) { do_warn( _("can't read block 0 of inode %" PRIu64 " attribute fork\n"), ino); return(1); } if (bp->b_error == -EFSBADCRC) (*repair)++; /* is this block sane? */ if (__check_attr_header(mp, bp, ino)) { *repair = 0; libxfs_putbuf(bp); return 1; } /* verify leaf block */ leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); /* check sibling pointers in leaf block or root block 0 before * we have to release the btree block */ if (leafhdr.forw != 0 || leafhdr.back != 0) { if (!no_modify) { do_warn( _("clearing forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"), ino); repairlinks = 1; leafhdr.forw = 0; leafhdr.back = 0; xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo, leaf, &leafhdr); } else { do_warn( _("would clear forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"), ino); } } /* * use magic number to tell us what type of attribute this is. * it's possible to have a node or leaf attribute in either an * extent format or btree format attribute fork. */ switch (leafhdr.magic) { case XFS_ATTR_LEAF_MAGIC: /* leaf-form attribute */ case XFS_ATTR3_LEAF_MAGIC: if (process_leaf_attr_block(mp, leaf, 0, ino, blkmap, 0, &next_hashval, repair)) { *repair = 0; /* the block is bad. lose the attribute fork. */ libxfs_putbuf(bp); return(1); } *repair = *repair || repairlinks; break; case XFS_DA_NODE_MAGIC: /* btree-form attribute */ case XFS_DA3_NODE_MAGIC: /* must do this now, to release block 0 before the traversal */ if ((*repair || repairlinks) && !no_modify) { *repair = 1; libxfs_writebuf(bp, 0); } else libxfs_putbuf(bp); error = process_node_attr(mp, ino, dip, blkmap); /* + repair */ if (error) *repair = 0; return error; default: do_warn( _("bad attribute leaf magic # %#x for dir ino %" PRIu64 "\n"), be16_to_cpu(leaf->hdr.info.magic), ino); libxfs_putbuf(bp); *repair = 0; return(1); } if (*repair && !no_modify) libxfs_writebuf(bp, 0); else libxfs_putbuf(bp); return(0); /* repair may be set */ } static int xfs_acl_from_disk( struct xfs_mount *mp, struct xfs_icacl **aclp, struct xfs_acl *dacl) { struct xfs_icacl *acl; struct xfs_icacl_entry *ace; struct xfs_acl_entry *dace; int count; int i; count = be32_to_cpu(dacl->acl_cnt); if (count > XFS_ACL_MAX_ENTRIES(mp)) { do_warn(_("Too many ACL entries, count %d\n"), count); *aclp = NULL; return EINVAL; } acl = malloc(sizeof(struct xfs_icacl) + count * sizeof(struct xfs_icacl_entry)); if (!acl) { do_warn(_("cannot malloc enough for ACL attribute\n")); do_warn(_("SKIPPING this ACL\n")); *aclp = NULL; return ENOMEM; } acl->acl_cnt = count; for (i = 0; i < count; i++) { ace = &acl->acl_entry[i]; dace = &dacl->acl_entry[i]; ace->ae_tag = be32_to_cpu(dace->ae_tag); ace->ae_id = be32_to_cpu(dace->ae_id); ace->ae_perm = be16_to_cpu(dace->ae_perm); } *aclp = acl; return 0; } /* * returns 1 if attributes got cleared * and 0 if things are ok. */ int process_attributes( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, blkmap_t *blkmap, int *repair) /* returned if we did repair */ { int err; __u8 aformat = dip->di_aformat; #ifdef DEBUG xfs_attr_shortform_t *asf; asf = (xfs_attr_shortform_t *) XFS_DFORK_APTR(dip); #endif if (aformat == XFS_DINODE_FMT_LOCAL) { ASSERT(be16_to_cpu(asf->hdr.totsize) <= XFS_DFORK_ASIZE(dip, mp)); err = process_shortform_attr(mp, ino, dip, repair); } else if (aformat == XFS_DINODE_FMT_EXTENTS || aformat == XFS_DINODE_FMT_BTREE) { err = process_longform_attr(mp, ino, dip, blkmap, repair); /* if err, convert this to shortform and clear it */ /* if repair and no error, it's taken care of */ } else { do_warn(_("illegal attribute format %d, ino %" PRIu64 "\n"), aformat, ino); err = 1; } return (err); /* and repair */ } /* * Validate an ACL */ static int xfs_acl_valid( struct xfs_mount *mp, struct xfs_acl *daclp) { struct xfs_icacl *aclp = NULL; struct xfs_icacl_entry *entry, *e; int user = 0, group = 0, other = 0, mask = 0, mask_required = 0; int i, j; if (daclp == NULL) goto acl_invalid; switch (xfs_acl_from_disk(mp, &aclp, daclp)) { case ENOMEM: return 0; case EINVAL: goto acl_invalid; default: break; } for (i = 0; i < aclp->acl_cnt; i++) { entry = &aclp->acl_entry[i]; if (entry->ae_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE)) goto acl_invalid; switch (entry->ae_tag) { case ACL_USER_OBJ: if (user++) goto acl_invalid; break; case ACL_GROUP_OBJ: if (group++) goto acl_invalid; break; case ACL_OTHER: if (other++) goto acl_invalid; break; case ACL_USER: case ACL_GROUP: for (j = i + 1; j < aclp->acl_cnt; j++) { e = &aclp->acl_entry[j]; if (e->ae_id == entry->ae_id && e->ae_tag == entry->ae_tag) goto acl_invalid; } mask_required++; break; case ACL_MASK: if (mask++) goto acl_invalid; break; default: goto acl_invalid; } } if (!user || !group || !other || (mask_required && !mask)) goto acl_invalid; free(aclp); return 0; acl_invalid: free(aclp); errno = EINVAL; return (-1); } /* * Check a category or division set to ensure that all values are in * ascending order and each division or category appears only once. */ static int __check_setvalue(const unsigned short *list, unsigned short count) { unsigned short i; for (i = 1; i < count ; i++) if (list[i] <= list[i-1]) return -1; return 0; } /* * xfs_mac_valid(lp) * Check the validity of a MAC label. */ static int xfs_mac_valid(xfs_mac_label_t *lp) { if (lp == NULL) return (0); /* * if the total category set and division set is greater than 250 * report error */ if ((lp->ml_catcount + lp->ml_divcount) > XFS_MAC_MAX_SETS) return(0); /* * check whether the msentype value is valid, and do they have * appropriate level, category association. */ switch (lp->ml_msen_type) { case XFS_MSEN_ADMIN_LABEL: case XFS_MSEN_EQUAL_LABEL: case XFS_MSEN_HIGH_LABEL: case XFS_MSEN_MLD_HIGH_LABEL: case XFS_MSEN_LOW_LABEL: case XFS_MSEN_MLD_LOW_LABEL: if (lp->ml_level != 0 || lp->ml_catcount > 0 ) return (0); break; case XFS_MSEN_TCSEC_LABEL: case XFS_MSEN_MLD_LABEL: if (lp->ml_catcount > 0 && __check_setvalue(lp->ml_list, lp->ml_catcount) == -1) return (0); break; case XFS_MSEN_UNKNOWN_LABEL: default: return (0); } /* * check whether the minttype value is valid, and do they have * appropriate grade, division association. */ switch (lp->ml_mint_type) { case XFS_MINT_BIBA_LABEL: if (lp->ml_divcount > 0 && __check_setvalue(lp->ml_list + lp->ml_catcount, lp->ml_divcount) == -1) return(0); break; case XFS_MINT_EQUAL_LABEL: case XFS_MINT_HIGH_LABEL: case XFS_MINT_LOW_LABEL: if (lp->ml_grade != 0 || lp->ml_divcount > 0 ) return(0); break; default: return(0); } return (1); } xfsprogs-4.9.0+nmu1ubuntu2/repair/attr_repair.h0000644000000000000000000000744013063067172016447 0ustar /* * Copyright (c) 2000-2002,2004-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XR_ATTRREPAIR_H #define _XR_ATTRREPAIR_H /* * Access Control Lists */ #define ACL_USER_OBJ 0x01 /* owner */ #define ACL_USER 0x02 /* additional users */ #define ACL_GROUP_OBJ 0x04 /* group */ #define ACL_GROUP 0x08 /* additional groups */ #define ACL_MASK 0x10 /* mask entry */ #define ACL_OTHER 0x20 /* other entry */ #define ACL_READ 04 #define ACL_WRITE 02 #define ACL_EXECUTE 01 typedef __uint16_t xfs_acl_perm_t; typedef __int32_t xfs_acl_type_t; typedef __int32_t xfs_acl_tag_t; typedef __int32_t xfs_acl_id_t; /* * "icacl" = in-core ACL. There is no equivalent in the XFS kernel code, * so they are magic names just for repair. The "acl" types are what the kernel * code uses for the on-disk format names, so use them here too for the on-disk * ACL format definitions. */ struct xfs_icacl_entry { xfs_acl_tag_t ae_tag; xfs_acl_id_t ae_id; xfs_acl_perm_t ae_perm; }; struct xfs_icacl { __int32_t acl_cnt; struct xfs_icacl_entry acl_entry[0]; }; /* * Mandatory Access Control Labels (IRIX) */ #define XFS_MAC_MAX_SETS 250 typedef struct xfs_mac_label { __uint8_t ml_msen_type; /* MSEN label type */ __uint8_t ml_mint_type; /* MINT label type */ __uint8_t ml_level; /* Hierarchical level */ __uint8_t ml_grade; /* Hierarchical grade */ __uint16_t ml_catcount; /* Category count */ __uint16_t ml_divcount; /* Division count */ /* Category set, then Division set */ __uint16_t ml_list[XFS_MAC_MAX_SETS]; } xfs_mac_label_t; /* MSEN label type names. Choose an upper case ASCII character. */ #define XFS_MSEN_ADMIN_LABEL 'A' /* Admin: lowavl_back; avlnode_t *forw = np->avl_forw; avlnode_t *nextino = np->avl_nextino; int bal = np->avl_balance; ASSERT(bal != AVL_BALANCE || (!back && !forw) || (back && forw)); ASSERT(bal != AVL_FORW || forw); ASSERT(bal != AVL_BACK || back); if (forw) { ASSERT(AVL_START(tree, np) < AVL_START(tree, forw)); ASSERT(np->avl_forw->avl_parent == np); ASSERT(back || bal == AVL_FORW); } else { ASSERT(bal != AVL_FORW); ASSERT(bal == AVL_BALANCE || back); ASSERT(bal == AVL_BACK || !back); } if (back) { ASSERT(AVL_START(tree, np) > AVL_START(tree, back)); ASSERT(np->avl_back->avl_parent == np); ASSERT(forw || bal == AVL_BACK); } else { ASSERT(bal != AVL_BACK); ASSERT(bal == AVL_BALANCE || forw); ASSERT(bal == AVL_FORW || !forw); } if (nextino == NULL) ASSERT(forw == NULL); else ASSERT(AVL_END(tree, np) <= AVL_START(tree, nextino)); } static void avl_checktree( avltree_desc_t *tree, avlnode_t *root) { avlnode_t *nlast, *nnext, *np; uintptr_t offset = 0; uintptr_t end; nlast = nnext = root; ASSERT(!nnext || nnext->avl_parent == NULL); while (nnext) { avl_checknode(tree, nnext); end = AVL_END(tree, nnext); if (end <= offset) { if ((np = nnext->avl_forw) && np != nlast) { nlast = nnext; nnext = np; } else { nlast = nnext; nnext = nnext->avl_parent; } continue; } nlast = nnext; if (np = nnext->avl_back) { if (AVL_END(tree, np) > offset) { nnext = np; continue; } } np = nnext; nnext = nnext->avl_forw; if (!nnext) nnext = np->avl_parent; offset = end; } } #else /* ! AVL_DEBUG */ #define avl_checktree(t,x) #endif /* AVL_DEBUG */ /* * Reset balance for np up through tree. * ``direction'' is the way that np's balance * is headed after the deletion of one of its children -- * e.g., deleting a avl_forw child sends avl_balance toward AVL_BACK. * Called only when deleting a node from the tree. */ static void retreat( avltree_desc_t *tree, avlnode_t *np, int direction) { avlnode_t **rootp = &tree->avl_root; avlnode_t *parent; avlnode_t *child; avlnode_t *tmp; int bal; do { ASSERT(direction == AVL_BACK || direction == AVL_FORW); if (np->avl_balance == AVL_BALANCE) { np->avl_balance = direction; return; } parent = np->avl_parent; /* * If balance is being restored, no local node * reorganization is necessary, but may be at * a higher node. Reset direction and continue. */ if (direction != np->avl_balance) { np->avl_balance = AVL_BALANCE; if (parent) { if (parent->avl_forw == np) direction = AVL_BACK; else direction = AVL_FORW; np = parent; continue; } return; } /* * Imbalance. If a avl_forw node was removed, direction * (and, by reduction, np->avl_balance) is/was AVL_BACK. */ if (np->avl_balance == AVL_BACK) { ASSERT(direction == AVL_BACK); child = np->avl_back; bal = child->avl_balance; if (bal != AVL_FORW) /* single LL */ { /* * np gets pushed down to lesser child's * avl_forw branch. * * np-> -D +B * / \ / \ * child-> B deleted A -D * / \ / * A C C */ #ifdef AVL_PRINT if (!(tree->avl_flags & AVLF_DUPLICITY)) cmn_err(CE_CONT, "!LL delete b 0x%x c 0x%x\n", np, child); #endif np->avl_back = child->avl_forw; if (child->avl_forw) child->avl_forw->avl_parent = np; child->avl_forw = np; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = child; direction = AVL_BACK; } else { ASSERT(parent->avl_back == np); parent->avl_back = child; direction = AVL_FORW; } } else { ASSERT(*rootp == np); *rootp = child; } np->avl_parent = child; child->avl_parent = parent; if (bal == AVL_BALANCE) { np->avl_balance = AVL_BACK; child->avl_balance = AVL_FORW; return; } else { np->avl_balance = AVL_BALANCE; child->avl_balance = AVL_BALANCE; np = parent; avl_checktree(tree, *rootp); continue; } } /* child->avl_balance == AVL_FORW double LR rotation * * child's avl_forw node gets promoted up, along with * its avl_forw subtree * * np-> -G C * / \ / \ * child-> +B H -B G * / \ \ / / \ * A +C deleted A D H * \ * D */ #ifdef AVL_PRINT if (!(tree->avl_flags & AVLF_DUPLICITY)) cmn_err(CE_CONT, "!LR delete b 0x%x c 0x%x t 0x%x\n", np, child, child->avl_forw); #endif tmp = child->avl_forw; bal = tmp->avl_balance; child->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = child; tmp->avl_back = child; child->avl_parent = tmp; np->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = np; tmp->avl_forw = np; if (bal == AVL_FORW) child->avl_balance = AVL_BACK; else child->avl_balance = AVL_BALANCE; if (bal == AVL_BACK) np->avl_balance = AVL_FORW; else np->avl_balance = AVL_BALANCE; goto next; } ASSERT(np->avl_balance == AVL_FORW && direction == AVL_FORW); child = np->avl_forw; bal = child->avl_balance; if (bal != AVL_BACK) /* single RR */ { /* * np gets pushed down to greater child's * avl_back branch. * * np-> +B -D * / \ / \ * deleted D <-child +B E * / \ \ * C E C */ #ifdef AVL_PRINT if (!(tree->avl_flags & AVLF_DUPLICITY)) cmn_err(CE_CONT, "!RR delete b 0x%x c 0x%x\n", np, child); #endif np->avl_forw = child->avl_back; if (child->avl_back) child->avl_back->avl_parent = np; child->avl_back = np; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = child; direction = AVL_BACK; } else { ASSERT(parent->avl_back == np); parent->avl_back = child; direction = AVL_FORW; } } else { ASSERT(*rootp == np); *rootp = child; } np->avl_parent = child; child->avl_parent = parent; if (bal == AVL_BALANCE) { np->avl_balance = AVL_FORW; child->avl_balance = AVL_BACK; return; } else { np->avl_balance = AVL_BALANCE; child->avl_balance = AVL_BALANCE; np = parent; avl_checktree(tree, *rootp); continue; } } /* child->avl_balance == AVL_BACK double RL rotation */ #ifdef AVL_PRINT if (!(tree->avl_flags & AVLF_DUPLICITY)) cmn_err(CE_CONT, "!RL delete b 0x%x c 0x%x t 0x%x\n", np, child, child->avl_back); #endif tmp = child->avl_back; bal = tmp->avl_balance; child->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = child; tmp->avl_forw = child; child->avl_parent = tmp; np->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = np; tmp->avl_back = np; if (bal == AVL_BACK) child->avl_balance = AVL_FORW; else child->avl_balance = AVL_BALANCE; if (bal == AVL_FORW) np->avl_balance = AVL_BACK; else np->avl_balance = AVL_BALANCE; next: np->avl_parent = tmp; tmp->avl_balance = AVL_BALANCE; tmp->avl_parent = parent; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = tmp; direction = AVL_BACK; } else { ASSERT(parent->avl_back == np); parent->avl_back = tmp; direction = AVL_FORW; } } else { ASSERT(*rootp == np); *rootp = tmp; return; } np = parent; avl_checktree(tree, *rootp); } while (np); } /* * Remove node from tree. * avl_delete does the local tree manipulations, * calls retreat() to rebalance tree up to its root. */ void avl_delete( avltree_desc_t *tree, avlnode_t *np) { avlnode_t *forw = np->avl_forw; avlnode_t *back = np->avl_back; avlnode_t *parent = np->avl_parent; avlnode_t *nnext; if (np->avl_back) { /* * a left child exits, then greatest left descendent's nextino * is pointing to np; make it point to np->nextino. */ nnext = np->avl_back; while (nnext) { if (!nnext->avl_forw) break; /* can't find anything bigger */ nnext = nnext->avl_forw; } } else if (np->avl_parent) { /* * find nearest ancestor with lesser value. That ancestor's * nextino is pointing to np; make it point to np->nextino */ nnext = np->avl_parent; while (nnext) { if (AVL_END(tree, nnext) <= AVL_END(tree, np)) break; nnext = nnext->avl_parent; } } else nnext = NULL; if (nnext) { ASSERT(nnext->avl_nextino == np); nnext->avl_nextino = np->avl_nextino; /* * Something preceeds np; np cannot be firstino. */ ASSERT(tree->avl_firstino != np); } else { /* * Nothing preceeding np; after deletion, np's nextino * is firstino of tree. */ ASSERT(tree->avl_firstino == np); tree->avl_firstino = np->avl_nextino; } /* * Degenerate cases... */ if (forw == NULL) { forw = back; goto attach; } if (back == NULL) { attach: if (forw) forw->avl_parent = parent; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = forw; retreat(tree, parent, AVL_BACK); } else { ASSERT(parent->avl_back == np); parent->avl_back = forw; retreat(tree, parent, AVL_FORW); } } else { ASSERT(tree->avl_root == np); tree->avl_root = forw; } avl_checktree(tree, tree->avl_root); return; } /* * Harder case: children on both sides. * If back's avl_forw pointer is null, just have back * inherit np's avl_forw tree, remove np from the tree * and adjust balance counters starting at back. * * np-> xI xH (befor retreat()) * / \ / \ * back-> H J G J * / / \ / \ * G ? ? ? ? * / \ * ? ? */ if ((forw = back->avl_forw) == NULL) { /* * AVL_FORW retreat below will set back's * balance to AVL_BACK. */ back->avl_balance = np->avl_balance; back->avl_forw = forw = np->avl_forw; forw->avl_parent = back; back->avl_parent = parent; if (parent) { if (parent->avl_forw == np) parent->avl_forw = back; else { ASSERT(parent->avl_back == np); parent->avl_back = back; } } else { ASSERT(tree->avl_root == np); tree->avl_root = back; } /* * back is taking np's place in the tree, and * has therefore lost a avl_back node (itself). */ retreat(tree, back, AVL_FORW); avl_checktree(tree, tree->avl_root); return; } /* * Hardest case: children on both sides, and back's * avl_forw pointer isn't null. Find the immediately * inferior buffer by following back's avl_forw line * to the end, then have it inherit np's avl_forw tree. * * np-> xI xH * / \ / \ * G J back-> G J (before retreat()) * / \ / \ * F ?... F ?1 * / \ * ? H <-forw * / * ?1 */ while ((back = forw->avl_forw)) forw = back; /* * Will be adjusted by retreat() below. */ forw->avl_balance = np->avl_balance; /* * forw inherits np's avl_forw... */ forw->avl_forw = np->avl_forw; np->avl_forw->avl_parent = forw; /* * ... forw's parent gets forw's avl_back... */ back = forw->avl_parent; back->avl_forw = forw->avl_back; if (forw->avl_back) forw->avl_back->avl_parent = back; /* * ... forw gets np's avl_back... */ forw->avl_back = np->avl_back; np->avl_back->avl_parent = forw; /* * ... and forw gets np's parent. */ forw->avl_parent = parent; if (parent) { if (parent->avl_forw == np) parent->avl_forw = forw; else parent->avl_back = forw; } else { ASSERT(tree->avl_root == np); tree->avl_root = forw; } /* * What used to be forw's parent is the starting * point for rebalancing. It has lost a avl_forw node. */ retreat(tree, back, AVL_BACK); avl_checktree(tree, tree->avl_root); } /* * avl_findanyrange: * * Given range r [start, end), find any range which is contained in r. * if checklen is non-zero, then only ranges of non-zero length are * considered in finding a match. */ avlnode_t * avl_findanyrange( avltree_desc_t *tree, uintptr_t start, uintptr_t end, int checklen) { avlnode_t *np = tree->avl_root; /* np = avl_findadjacent(tree, start, AVL_SUCCEED); */ while (np) { if (start < AVL_START(tree, np)) { if (np->avl_back) { np = np->avl_back; continue; } /* if we were to add node with start, would * have a growth of AVL_BACK */ /* if succeeding node is needed, this is it. */ break; } if (start >= AVL_END(tree, np)) { if (np->avl_forw) { np = np->avl_forw; continue; } /* if we were to add node with start, would * have a growth of AVL_FORW; */ /* we are looking for a succeeding node; * this is nextino. */ np = np->avl_nextino; break; } /* AVL_START(tree, np) <= start < AVL_END(tree, np) */ break; } if (np) { if (checklen == AVL_INCLUDE_ZEROLEN) { if (end <= AVL_START(tree, np)) { /* something follows start, but is * is entierly after the range (end) */ return(NULL); } /* np may stradle [start, end) */ return(np); } /* * find non-zero length region */ while (np && (AVL_END(tree, np) - AVL_START(tree, np) == 0) && (AVL_START(tree, np) < end)) np = np->avl_nextino; if ((np == NULL) || (AVL_START(tree, np) >= end)) return NULL; return(np); } /* * nothing succeeds start, all existing ranges are before start. */ return NULL; } /* * Returns a pointer to node which contains exact value. */ avlnode_t * avl_find( avltree_desc_t *tree, uintptr_t value) { avlnode_t *np = tree->avl_root; uintptr_t nvalue; while (np) { nvalue = AVL_START(tree, np); if (value < nvalue) { np = np->avl_back; continue; } if (value == nvalue) { return np; } np = np->avl_forw; } return NULL; } /* * Balance buffer AVL tree after attaching a new node to root. * Called only by avl_insert. */ static void avl_balance( avlnode_t **rootp, avlnode_t *np, int growth) { /* * At this point, np points to the node to which * a new node has been attached. All that remains is to * propagate avl_balance up the tree. */ for ( ; ; ) { avlnode_t *parent = np->avl_parent; avlnode_t *child; CERT(growth == AVL_BACK || growth == AVL_FORW); /* * If the buffer was already balanced, set avl_balance * to the new direction. Continue if there is a * parent after setting growth to reflect np's * relation to its parent. */ if (np->avl_balance == AVL_BALANCE) { np->avl_balance = growth; if (parent) { if (parent->avl_forw == np) growth = AVL_FORW; else { ASSERT(parent->avl_back == np); growth = AVL_BACK; } np = parent; continue; } break; } if (growth != np->avl_balance) { /* * Subtree is now balanced -- no net effect * in the size of the subtree, so leave. */ np->avl_balance = AVL_BALANCE; break; } if (growth == AVL_BACK) { child = np->avl_back; CERT(np->avl_balance == AVL_BACK && child); if (child->avl_balance == AVL_BACK) { /* single LL */ /* * ``A'' just got inserted; * np points to ``E'', child to ``C'', * and it is already AVL_BACK -- * child will get promoted to top of subtree. np-> -E C / \ / \ child-> -C F -B E / \ / / \ -B D A D F / A Note that child->avl_parent and avl_balance get set in common code. */ np->avl_parent = child; np->avl_balance = AVL_BALANCE; np->avl_back = child->avl_forw; if (child->avl_forw) child->avl_forw->avl_parent = np; child->avl_forw = np; } else { /* * double LR * * child's avl_forw node gets promoted to * the top of the subtree. np-> -E C / \ / \ child-> +B F -B E / \ / / \ A +C A D F \ D */ avlnode_t *tmp = child->avl_forw; CERT(child->avl_balance == AVL_FORW && tmp); child->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = child; tmp->avl_back = child; child->avl_parent = tmp; np->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = np; tmp->avl_forw = np; np->avl_parent = tmp; if (tmp->avl_balance == AVL_BACK) np->avl_balance = AVL_FORW; else np->avl_balance = AVL_BALANCE; if (tmp->avl_balance == AVL_FORW) child->avl_balance = AVL_BACK; else child->avl_balance = AVL_BALANCE; /* * Set child to point to tmp since it is * now the top of the subtree, and will * get attached to the subtree parent in * the common code below. */ child = tmp; } } else /* growth == AVL_BACK */ { /* * This code is the mirror image of AVL_FORW above. */ child = np->avl_forw; CERT(np->avl_balance == AVL_FORW && child); if (child->avl_balance == AVL_FORW) { /* single RR */ np->avl_parent = child; np->avl_balance = AVL_BALANCE; np->avl_forw = child->avl_back; if (child->avl_back) child->avl_back->avl_parent = np; child->avl_back = np; } else { /* * double RL */ avlnode_t *tmp = child->avl_back; ASSERT(child->avl_balance == AVL_BACK && tmp); child->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = child; tmp->avl_forw = child; child->avl_parent = tmp; np->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = np; tmp->avl_back = np; np->avl_parent = tmp; if (tmp->avl_balance == AVL_FORW) np->avl_balance = AVL_BACK; else np->avl_balance = AVL_BALANCE; if (tmp->avl_balance == AVL_BACK) child->avl_balance = AVL_FORW; else child->avl_balance = AVL_BALANCE; child = tmp; } } child->avl_parent = parent; child->avl_balance = AVL_BALANCE; if (parent) { if (parent->avl_back == np) parent->avl_back = child; else parent->avl_forw = child; } else { ASSERT(*rootp == np); *rootp = child; } break; } } static avlnode_t * avl_insert_find_growth( avltree_desc_t *tree, uintptr_t start, /* range start at start, */ uintptr_t end, /* exclusive */ int *growthp) /* OUT */ { avlnode_t *root = tree->avl_root; avlnode_t *np; np = root; ASSERT(np); /* caller ensures that there is atleast one node in tree */ for ( ; ; ) { CERT(np->avl_parent || root == np); CERT(!np->avl_parent || root != np); CERT(!(np->avl_back) || np->avl_back->avl_parent == np); CERT(!(np->avl_forw) || np->avl_forw->avl_parent == np); CERT(np->avl_balance != AVL_FORW || np->avl_forw); CERT(np->avl_balance != AVL_BACK || np->avl_back); CERT(np->avl_balance != AVL_BALANCE || np->avl_back == NULL || np->avl_forw); CERT(np->avl_balance != AVL_BALANCE || np->avl_forw == NULL || np->avl_back); if (AVL_START(tree, np) >= end) { if (np->avl_back) { np = np->avl_back; continue; } *growthp = AVL_BACK; break; } if (AVL_END(tree, np) <= start) { if (np->avl_forw) { np = np->avl_forw; continue; } *growthp = AVL_FORW; break; } /* found exact match -- let caller decide if it is an error */ return(NULL); } return(np); } static void avl_insert_grow( avltree_desc_t *tree, avlnode_t *parent, avlnode_t *newnode, int growth) { avlnode_t *nnext; uintptr_t start = AVL_START(tree, newnode); if (growth == AVL_BACK) { parent->avl_back = newnode; /* * we are growing to the left; previous in-order to newnode is * closest ancestor with lesser value. Before this * insertion, this ancestor will be pointing to * newnode's parent. After insertion, next in-order to newnode * is the parent. */ newnode->avl_nextino = parent; nnext = parent; while (nnext) { if (AVL_END(tree, nnext) <= start) break; nnext = nnext->avl_parent; } if (nnext) { /* * nnext will be null if newnode is * the least element, and hence very first in the list. */ ASSERT(nnext->avl_nextino == parent); nnext->avl_nextino = newnode; } } else { parent->avl_forw = newnode; newnode->avl_nextino = parent->avl_nextino; parent->avl_nextino = newnode; } } avlnode_t * avl_insert( avltree_desc_t *tree, avlnode_t *newnode) { avlnode_t *np; uintptr_t start = AVL_START(tree, newnode); uintptr_t end = AVL_END(tree, newnode); int growth; ASSERT(newnode); ASSERT(start <= end); /* * Clean all pointers for sanity; some will be reset as necessary. */ newnode->avl_nextino = NULL; newnode->avl_parent = NULL; newnode->avl_forw = NULL; newnode->avl_back = NULL; newnode->avl_balance = AVL_BALANCE; if ((np = tree->avl_root) == NULL) { /* degenerate case... */ tree->avl_root = newnode; tree->avl_firstino = newnode; return newnode; } if ((np = avl_insert_find_growth(tree, start, end, &growth)) == NULL) { if (start != end) { /* non-zero length range */ fprintf(stderr, _("avl_insert: Warning! duplicate range [%llu,%llu]\n"), (unsigned long long)start, (unsigned long long)end); } return(NULL); } avl_insert_grow(tree, np, newnode, growth); if (growth == AVL_BACK) { /* * Growing to left. if np was firstino, newnode will be firstino */ if (tree->avl_firstino == np) tree->avl_firstino = newnode; } #ifdef notneeded else if (growth == AVL_FORW) /* * Cannot possibly be firstino; there is somebody to our left. */ ; #endif newnode->avl_parent = np; CERT(np->avl_forw == newnode || np->avl_back == newnode); avl_balance(&tree->avl_root, np, growth); avl_checktree(tree, tree->avl_root); return newnode; } /* * * avl_insert_immediate(tree, afterp, newnode): * insert newnode immediately into tree immediately after afterp. * after insertion, newnode is right child of afterp. */ void avl_insert_immediate( avltree_desc_t *tree, avlnode_t *afterp, avlnode_t *newnode) { /* * Clean all pointers for sanity; some will be reset as necessary. */ newnode->avl_nextino = NULL; newnode->avl_parent = NULL; newnode->avl_forw = NULL; newnode->avl_back = NULL; newnode->avl_balance = AVL_BALANCE; if (afterp == NULL) { tree->avl_root = newnode; tree->avl_firstino = newnode; return; } ASSERT(afterp->avl_forw == NULL); avl_insert_grow(tree, afterp, newnode, AVL_FORW); /* grow to right */ CERT(afterp->avl_forw == newnode); avl_balance(&tree->avl_root, afterp, AVL_FORW); avl_checktree(tree, tree->avl_root); } /* * Returns first in order node */ avlnode_t * avl_firstino(avlnode_t *root) { avlnode_t *np; if ((np = root) == NULL) return NULL; while (np->avl_back) np = np->avl_back; return np; } /* * Returns last in order node */ avlnode_t * avl_lastino(avlnode_t *root) { avlnode_t *np; if ((np = root) == NULL) return NULL; while (np->avl_forw) np = np->avl_forw; return np; } void avl_init_tree(avltree_desc_t *tree, avlops_t *ops) { tree->avl_root = NULL; tree->avl_firstino = NULL; tree->avl_ops = ops; } #ifdef AVL_DEBUG static void avl_printnode(avltree_desc_t *tree, avlnode_t *np, int nl) { printf("[%d-%d]%c", AVL_START(tree, np), (AVL_END(tree, np) - 1), nl ? '\n' : ' '); } #endif #ifdef STAND_ALONE_DEBUG struct avl_debug_node { avlnode_t avl_node; xfs_off_t avl_start; unsigned int avl_size; } avlops_t avl_debug_ops = { avl_debug_start, avl_debug_end, } static uintptr_t avl_debug_start(avlnode_t *node) { return (uintptr_t)(struct avl_debug_node *)node->avl_start; } static uintptr_t avl_debug_end(avlnode_t *node) { return (uintptr_t) ((struct avl_debug_node *)node->avl_start + (struct avl_debug_node *)node->avl_size); } avl_debug_node freenodes[100]; avl_debug_node *freehead = &freenodes[0]; static avlnode_t * alloc_avl_debug_node() { freehead->avl_balance = AVL_BALANCE; freehead->avl_parent = freehead->avl_forw = freehead->avl_back = NULL; return(freehead++); } static void avl_print(avltree_desc_t *tree, avlnode_t *root, int depth) { int i; if (!root) return; if (root->avl_forw) avl_print(tree, root->avl_forw, depth+5); for (i = 0; i < depth; i++) putchar((int) ' '); avl_printnode(tree, root,1); if (root->avl_back) avl_print(tree, root->avl_back, depth+5); } main() { int i, j; avlnode_t *np; avltree_desc_t tree; char linebuf[256], cmd[256]; avl_init_tree(&tree, &avl_debug_ops); for (i = 100; i > 0; i = i - 10) { np = alloc__debug_avlnode(); ASSERT(np); np->avl_start = i; np->avl_size = 10; avl_insert(&tree, np); } avl_print(&tree, tree.avl_root, 0); for (np = tree.avl_firstino; np != NULL; np = np->avl_nextino) avl_printnode(&tree, np, 0); printf("\n"); while (1) { printf(_("Command [fpdir] : ")); fgets(linebuf, 256, stdin); if (feof(stdin)) break; cmd[0] = NULL; if (sscanf(linebuf, "%[fpdir]%d", cmd, &i) != 2) continue; switch (cmd[0]) { case 'd': case 'f': printf(_("end of range ? ")); fgets(linebuf, 256, stdin); j = atoi(linebuf); if (i == j) j = i+1; np = avl_findinrange(&tree,i,j); if (np) { avl_printnode(&tree, np, 1); if (cmd[0] == 'd') avl_delete(&tree, np); } else printf(_("Cannot find %d\n"), i); break; case 'p': avl_print(&tree, tree.avl_root, 0); for (np = tree.avl_firstino; np != NULL; np = np->avl_nextino) avl_printnode(&tree, np, 0); printf("\n"); break; case 'i': np = alloc_avlnode(); ASSERT(np); np->avl_start = i; printf(_("size of range ? ")); fgets(linebuf, 256, stdin); j = atoi(linebuf); np->avl_size = j; avl_insert(&tree, np); break; case 'r': { avlnode_t *b, *e, *t; int checklen; printf(_("End of range ? ")); fgets(linebuf, 256, stdin); j = atoi(linebuf); printf(_("checklen 0/1 ? ")); fgets(linebuf, 256, stdin); checklen = atoi(linebuf); b = avl_findanyrange(&tree, i, j, checklen); if (b) { printf(_("Found something\n")); t = b; while (t) { if (t != b && AVL_START(&tree, t) >= j) break; avl_printnode(&tree, t, 0); t = t->avl_nextino; } printf("\n"); } } } } } #endif /* * Given a tree, find value; will find return range enclosing value, * or range immediately succeeding value, * or range immediately preceeding value. */ avlnode_t * avl_findadjacent( avltree_desc_t *tree, uintptr_t value, int dir) { avlnode_t *np = tree->avl_root; while (np) { if (value < AVL_START(tree, np)) { if (np->avl_back) { np = np->avl_back; continue; } /* if we were to add node with value, would * have a growth of AVL_BACK */ if (dir == AVL_SUCCEED) { /* if succeeding node is needed, this is it. */ return(np); } if (dir == AVL_PRECEED) { /* * find nearest ancestor with lesser value. */ np = np->avl_parent; while (np) { if (AVL_END(tree, np) <= value) break; np = np->avl_parent; } return(np); } ASSERT(dir == AVL_SUCCEED || dir == AVL_PRECEED); break; } if (value >= AVL_END(tree, np)) { if (np->avl_forw) { np = np->avl_forw; continue; } /* if we were to add node with value, would * have a growth of AVL_FORW; */ if (dir == AVL_SUCCEED) { /* we are looking for a succeeding node; * this is nextino. */ return(np->avl_nextino); } if (dir == AVL_PRECEED) { /* looking for a preceeding node; this is it. */ return(np); } ASSERT(dir == AVL_SUCCEED || dir == AVL_PRECEED); } /* AVL_START(tree, np) <= value < AVL_END(tree, np) */ return(np); } return NULL; } /* * avl_findranges: * * Given range r [start, end), find all ranges in tree which are contained * in r. At return, startp and endp point to first and last of * a chain of elements which describe the contained ranges. Elements * in startp ... endp are in sort order, and can be accessed by * using avl_nextino. */ void avl_findranges( avltree_desc_t *tree, uintptr_t start, uintptr_t end, avlnode_t **startp, avlnode_t **endp) { avlnode_t *np; np = avl_findadjacent(tree, start, AVL_SUCCEED); if (np == NULL /* nothing succeding start */ || (np && (end <= AVL_START(tree, np)))) /* something follows start, but... is entirely after end */ { *startp = NULL; *endp = NULL; return; } *startp = np; /* see if end is in this region itself */ if (end <= AVL_END(tree, np) || np->avl_nextino == NULL || (np->avl_nextino && (end <= AVL_START(tree, np->avl_nextino)))) { *endp = np; return; } /* have to munge for end */ /* * note: have to look for (end - 1), since * findadjacent will look for exact value, and does not * care about the fact that end is actually one more * than the value actually being looked for; thus feed it one less. */ *endp = avl_findadjacent(tree, (end-1), AVL_PRECEED); ASSERT(*endp); } xfsprogs-4.9.0+nmu1ubuntu2/repair/avl.h0000644000000000000000000000614013063067173014712 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __SYS_AVL_H__ #define __SYS_AVL_H__ typedef struct avlnode { struct avlnode *avl_forw; /* pointer to right child (> parent) */ struct avlnode *avl_back; /* pointer to left child (< parent) */ struct avlnode *avl_parent; /* parent pointer */ struct avlnode *avl_nextino; /* next in-order; NULL terminated list*/ char avl_balance; /* tree balance */ } avlnode_t; /* * avl-tree operations */ typedef struct avlops { uintptr_t (*avl_start)(avlnode_t *); uintptr_t (*avl_end)(avlnode_t *); } avlops_t; #define AVL_START(tree, n) (*(tree)->avl_ops->avl_start)(n) #define AVL_END(tree, n) (*(tree)->avl_ops->avl_end)(n) /* * tree descriptor: * root points to the root of the tree. * firstino points to the first in the ordered list. */ typedef struct avltree_desc { avlnode_t *avl_root; avlnode_t *avl_firstino; avlops_t *avl_ops; short avl_flags; } avltree_desc_t; /* possible values for avl_balance */ #define AVL_BACK 1 #define AVL_BALANCE 0 #define AVL_FORW 2 /* possible values for avl_flags */ #define AVLF_DUPLICITY 0x0001 /* no warnings on insert dups */ /* * 'Exported' avl tree routines */ avlnode_t *avl_insert( avltree_desc_t *tree, avlnode_t *newnode); void avl_delete( avltree_desc_t *tree, avlnode_t *np); void avl_insert_immediate( avltree_desc_t *tree, avlnode_t *afterp, avlnode_t *newnode); void avl_init_tree( avltree_desc_t *tree, avlops_t *ops); static inline avlnode_t * avl_findrange( avltree_desc_t *tree, uintptr_t value) { avlnode_t *np = tree->avl_root; while (np) { if (value < AVL_START(tree, np)) { np = np->avl_back; continue; } if (value >= AVL_END(tree, np)) { np = np->avl_forw; continue; } ASSERT(AVL_START(tree, np) <= value && value < AVL_END(tree, np)); return np; } return NULL; } avlnode_t * avl_find( avltree_desc_t *tree, uintptr_t value); avlnode_t * avl_findanyrange( avltree_desc_t *tree, uintptr_t start, uintptr_t end, int checklen); avlnode_t * avl_findadjacent( avltree_desc_t *tree, uintptr_t value, int dir); void avl_findranges( avltree_desc_t *tree, uintptr_t start, uintptr_t end, avlnode_t **startp, avlnode_t **endp); avlnode_t * avl_firstino( avlnode_t *root); avlnode_t * avl_lastino( avlnode_t *root); #define AVL_PRECEED 0x1 #define AVL_SUCCEED 0x2 #define AVL_INCLUDE_ZEROLEN 0x0000 #define AVL_EXCLUDE_ZEROLEN 0x0001 #endif /* __SYS_AVL_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/repair/avl64.c0000644000000000000000000007350713063067173015072 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "libxfs.h" #include "avl64.h" #define CERT ASSERT #ifdef AVL_DEBUG static void avl64_checknode( avl64tree_desc_t *tree, avl64node_t *np) { avl64node_t *back = np->avl_back; avl64node_t *forw = np->avl_forw; avl64node_t *nextino = np->avl_nextino; int bal = np->avl_balance; ASSERT(bal != AVL_BALANCE || (!back && !forw) || (back && forw)); ASSERT(bal != AVL_FORW || forw); ASSERT(bal != AVL_BACK || back); if (forw) { ASSERT(AVL_START(tree, np) < AVL_START(tree, forw)); ASSERT(np->avl_forw->avl_parent == np); ASSERT(back || bal == AVL_FORW); } else { ASSERT(bal != AVL_FORW); ASSERT(bal == AVL_BALANCE || back); ASSERT(bal == AVL_BACK || !back); } if (back) { ASSERT(AVL_START(tree, np) > AVL_START(tree, back)); ASSERT(np->avl_back->avl_parent == np); ASSERT(forw || bal == AVL_BACK); } else { ASSERT(bal != AVL_BACK); ASSERT(bal == AVL_BALANCE || forw); ASSERT(bal == AVL_FORW || !forw); } if (nextino == NULL) ASSERT(forw == NULL); else ASSERT(AVL_END(tree, np) <= AVL_START(tree, nextino)); } static void avl64_checktree( avl64tree_desc_t *tree, avl64node_t *root) { avl64node_t *nlast, *nnext, *np; __uint64_t offset = 0; __uint64_t end; nlast = nnext = root; ASSERT(!nnext || nnext->avl_parent == NULL); while (nnext) { avl64_checknode(tree, nnext); end = AVL_END(tree, nnext); if (end <= offset) { if ((np = nnext->avl_forw) && np != nlast) { nlast = nnext; nnext = np; } else { nlast = nnext; nnext = nnext->avl_parent; } continue; } nlast = nnext; if (np = nnext->avl_back) { if (AVL_END(tree, np) > offset) { nnext = np; continue; } } np = nnext; nnext = nnext->avl_forw; if (!nnext) nnext = np->avl_parent; offset = end; } } #else /* ! AVL_DEBUG */ #define avl64_checktree(t,x) #endif /* AVL_DEBUG */ /* * Reset balance for np up through tree. * ``direction'' is the way that np's balance * is headed after the deletion of one of its children -- * e.g., deleting a avl_forw child sends avl_balance toward AVL_BACK. * Called only when deleting a node from the tree. */ static void retreat( avl64tree_desc_t *tree, avl64node_t *np, int direction) { avl64node_t **rootp = &tree->avl_root; avl64node_t *parent; avl64node_t *child; avl64node_t *tmp; int bal; do { ASSERT(direction == AVL_BACK || direction == AVL_FORW); if (np->avl_balance == AVL_BALANCE) { np->avl_balance = direction; return; } parent = np->avl_parent; /* * If balance is being restored, no local node * reorganization is necessary, but may be at * a higher node. Reset direction and continue. */ if (direction != np->avl_balance) { np->avl_balance = AVL_BALANCE; if (parent) { if (parent->avl_forw == np) direction = AVL_BACK; else direction = AVL_FORW; np = parent; continue; } return; } /* * Imbalance. If a avl_forw node was removed, direction * (and, by reduction, np->avl_balance) is/was AVL_BACK. */ if (np->avl_balance == AVL_BACK) { ASSERT(direction == AVL_BACK); child = np->avl_back; bal = child->avl_balance; if (bal != AVL_FORW) /* single LL */ { /* * np gets pushed down to lesser child's * avl_forw branch. * * np-> -D +B * / \ / \ * child-> B deleted A -D * / \ / * A C C cmn_err(CE_CONT, "!LL delete b 0x%x c 0x%x\n", np, child); */ np->avl_back = child->avl_forw; if (child->avl_forw) child->avl_forw->avl_parent = np; child->avl_forw = np; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = child; direction = AVL_BACK; } else { ASSERT(parent->avl_back == np); parent->avl_back = child; direction = AVL_FORW; } } else { ASSERT(*rootp == np); *rootp = child; } np->avl_parent = child; child->avl_parent = parent; if (bal == AVL_BALANCE) { np->avl_balance = AVL_BACK; child->avl_balance = AVL_FORW; return; } else { np->avl_balance = AVL_BALANCE; child->avl_balance = AVL_BALANCE; np = parent; avl64_checktree(tree, *rootp); continue; } } /* child->avl_balance == AVL_FORW double LR rotation * * child's avl_forw node gets promoted up, along with * its avl_forw subtree * * np-> -G C * / \ / \ * child-> +B H -B G * / \ \ / / \ * A +C deleted A D H * \ * D cmn_err(CE_CONT, "!LR delete b 0x%x c 0x%x t 0x%x\n", np, child, child->avl_forw); */ tmp = child->avl_forw; bal = tmp->avl_balance; child->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = child; tmp->avl_back = child; child->avl_parent = tmp; np->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = np; tmp->avl_forw = np; if (bal == AVL_FORW) child->avl_balance = AVL_BACK; else child->avl_balance = AVL_BALANCE; if (bal == AVL_BACK) np->avl_balance = AVL_FORW; else np->avl_balance = AVL_BALANCE; goto next; } ASSERT(np->avl_balance == AVL_FORW && direction == AVL_FORW); child = np->avl_forw; bal = child->avl_balance; if (bal != AVL_BACK) /* single RR */ { /* * np gets pushed down to greater child's * avl_back branch. * * np-> +B -D * / \ / \ * deleted D <-child +B E * / \ \ * C E C cmn_err(CE_CONT, "!RR delete b 0x%x c 0x%x\n", np, child); */ np->avl_forw = child->avl_back; if (child->avl_back) child->avl_back->avl_parent = np; child->avl_back = np; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = child; direction = AVL_BACK; } else { ASSERT(parent->avl_back == np); parent->avl_back = child; direction = AVL_FORW; } } else { ASSERT(*rootp == np); *rootp = child; } np->avl_parent = child; child->avl_parent = parent; if (bal == AVL_BALANCE) { np->avl_balance = AVL_FORW; child->avl_balance = AVL_BACK; return; } else { np->avl_balance = AVL_BALANCE; child->avl_balance = AVL_BALANCE; np = parent; avl64_checktree(tree, *rootp); continue; } } /* child->avl_balance == AVL_BACK double RL rotation cmn_err(CE_CONT, "!RL delete b 0x%x c 0x%x t 0x%x\n", np, child, child->avl_back); */ tmp = child->avl_back; bal = tmp->avl_balance; child->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = child; tmp->avl_forw = child; child->avl_parent = tmp; np->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = np; tmp->avl_back = np; if (bal == AVL_BACK) child->avl_balance = AVL_FORW; else child->avl_balance = AVL_BALANCE; if (bal == AVL_FORW) np->avl_balance = AVL_BACK; else np->avl_balance = AVL_BALANCE; next: np->avl_parent = tmp; tmp->avl_balance = AVL_BALANCE; tmp->avl_parent = parent; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = tmp; direction = AVL_BACK; } else { ASSERT(parent->avl_back == np); parent->avl_back = tmp; direction = AVL_FORW; } } else { ASSERT(*rootp == np); *rootp = tmp; return; } np = parent; avl64_checktree(tree, *rootp); } while (np); } /* * Remove node from tree. * avl_delete does the local tree manipulations, * calls retreat() to rebalance tree up to its root. */ void avl64_delete( avl64tree_desc_t *tree, avl64node_t *np) { avl64node_t *forw = np->avl_forw; avl64node_t *back = np->avl_back; avl64node_t *parent = np->avl_parent; avl64node_t *nnext; if (np->avl_back) { /* * a left child exits, then greatest left descendent's nextino * is pointing to np; make it point to np->nextino. */ nnext = np->avl_back; while (nnext) { if (!nnext->avl_forw) break; /* can't find anything bigger */ nnext = nnext->avl_forw; } } else if (np->avl_parent) { /* * find nearest ancestor with lesser value. That ancestor's * nextino is pointing to np; make it point to np->nextino */ nnext = np->avl_parent; while (nnext) { if (AVL_END(tree, nnext) <= AVL_END(tree, np)) break; nnext = nnext->avl_parent; } } else nnext = NULL; if (nnext) { ASSERT(nnext->avl_nextino == np); nnext->avl_nextino = np->avl_nextino; /* * Something preceeds np; np cannot be firstino. */ ASSERT(tree->avl_firstino != np); } else { /* * Nothing preceeding np; after deletion, np's nextino * is firstino of tree. */ ASSERT(tree->avl_firstino == np); tree->avl_firstino = np->avl_nextino; } /* * Degenerate cases... */ if (forw == NULL) { forw = back; goto attach; } if (back == NULL) { attach: if (forw) forw->avl_parent = parent; if (parent) { if (parent->avl_forw == np) { parent->avl_forw = forw; retreat(tree, parent, AVL_BACK); } else { ASSERT(parent->avl_back == np); parent->avl_back = forw; retreat(tree, parent, AVL_FORW); } } else { ASSERT(tree->avl_root == np); tree->avl_root = forw; } avl64_checktree(tree, tree->avl_root); return; } /* * Harder case: children on both sides. * If back's avl_forw pointer is null, just have back * inherit np's avl_forw tree, remove np from the tree * and adjust balance counters starting at back. * * np-> xI xH (befor retreat()) * / \ / \ * back-> H J G J * / / \ / \ * G ? ? ? ? * / \ * ? ? */ if ((forw = back->avl_forw) == NULL) { /* * AVL_FORW retreat below will set back's * balance to AVL_BACK. */ back->avl_balance = np->avl_balance; back->avl_forw = forw = np->avl_forw; forw->avl_parent = back; back->avl_parent = parent; if (parent) { if (parent->avl_forw == np) parent->avl_forw = back; else { ASSERT(parent->avl_back == np); parent->avl_back = back; } } else { ASSERT(tree->avl_root == np); tree->avl_root = back; } /* * back is taking np's place in the tree, and * has therefore lost a avl_back node (itself). */ retreat(tree, back, AVL_FORW); avl64_checktree(tree, tree->avl_root); return; } /* * Hardest case: children on both sides, and back's * avl_forw pointer isn't null. Find the immediately * inferior buffer by following back's avl_forw line * to the end, then have it inherit np's avl_forw tree. * * np-> xI xH * / \ / \ * G J back-> G J (before retreat()) * / \ / \ * F ?... F ?1 * / \ * ? H <-forw * / * ?1 */ while ((back = forw->avl_forw)) forw = back; /* * Will be adjusted by retreat() below. */ forw->avl_balance = np->avl_balance; /* * forw inherits np's avl_forw... */ forw->avl_forw = np->avl_forw; np->avl_forw->avl_parent = forw; /* * ... forw's parent gets forw's avl_back... */ back = forw->avl_parent; back->avl_forw = forw->avl_back; if (forw->avl_back) forw->avl_back->avl_parent = back; /* * ... forw gets np's avl_back... */ forw->avl_back = np->avl_back; np->avl_back->avl_parent = forw; /* * ... and forw gets np's parent. */ forw->avl_parent = parent; if (parent) { if (parent->avl_forw == np) parent->avl_forw = forw; else parent->avl_back = forw; } else { ASSERT(tree->avl_root == np); tree->avl_root = forw; } /* * What used to be forw's parent is the starting * point for rebalancing. It has lost a avl_forw node. */ retreat(tree, back, AVL_BACK); avl64_checktree(tree, tree->avl_root); } /* * avl_findanyrange: * * Given range r [start, end), find any range which is contained in r. * if checklen is non-zero, then only ranges of non-zero length are * considered in finding a match. */ avl64node_t * avl64_findanyrange( avl64tree_desc_t *tree, __uint64_t start, __uint64_t end, int checklen) { avl64node_t *np = tree->avl_root; /* np = avl64_findadjacent(tree, start, AVL_SUCCEED); */ while (np) { if (start < AVL_START(tree, np)) { if (np->avl_back) { np = np->avl_back; continue; } /* if we were to add node with start, would * have a growth of AVL_BACK */ /* if succeeding node is needed, this is it. */ break; } if (start >= AVL_END(tree, np)) { if (np->avl_forw) { np = np->avl_forw; continue; } /* if we were to add node with start, would * have a growth of AVL_FORW; */ /* we are looking for a succeeding node; * this is nextino. */ np = np->avl_nextino; break; } /* AVL_START(tree, np) <= start < AVL_END(tree, np) */ break; } if (np) { if (checklen == AVL_INCLUDE_ZEROLEN) { if (end <= AVL_START(tree, np)) { /* something follows start, but is * is entierly after the range (end) */ return(NULL); } /* np may stradle [start, end) */ return(np); } /* * find non-zero length region */ while (np && (AVL_END(tree, np) - AVL_START(tree, np) == 0) && (AVL_START(tree, np) < end)) np = np->avl_nextino; if ((np == NULL) || (AVL_START(tree, np) >= end)) return NULL; return(np); } /* * nothing succeeds start, all existing ranges are before start. */ return NULL; } /* * Returns a pointer to range which contains value. */ avl64node_t * avl64_findrange( avl64tree_desc_t *tree, __uint64_t value) { avl64node_t *np = tree->avl_root; while (np) { if (value < AVL_START(tree, np)) { np = np->avl_back; continue; } if (value >= AVL_END(tree, np)) { np = np->avl_forw; continue; } ASSERT(AVL_START(tree, np) <= value && value < AVL_END(tree, np)); return np; } return NULL; } /* * Returns a pointer to node which contains exact value. */ avl64node_t * avl64_find( avl64tree_desc_t *tree, __uint64_t value) { avl64node_t *np = tree->avl_root; __uint64_t nvalue; while (np) { nvalue = AVL_START(tree, np); if (value < nvalue) { np = np->avl_back; continue; } if (value == nvalue) { return np; } np = np->avl_forw; } return NULL; } /* * Balance buffer AVL tree after attaching a new node to root. * Called only by avl_insert. */ static void avl64_balance( avl64node_t **rootp, avl64node_t *np, int growth) { /* * At this point, np points to the node to which * a new node has been attached. All that remains is to * propagate avl_balance up the tree. */ for ( ; ; ) { avl64node_t *parent = np->avl_parent; avl64node_t *child; CERT(growth == AVL_BACK || growth == AVL_FORW); /* * If the buffer was already balanced, set avl_balance * to the new direction. Continue if there is a * parent after setting growth to reflect np's * relation to its parent. */ if (np->avl_balance == AVL_BALANCE) { np->avl_balance = growth; if (parent) { if (parent->avl_forw == np) growth = AVL_FORW; else { ASSERT(parent->avl_back == np); growth = AVL_BACK; } np = parent; continue; } break; } if (growth != np->avl_balance) { /* * Subtree is now balanced -- no net effect * in the size of the subtree, so leave. */ np->avl_balance = AVL_BALANCE; break; } if (growth == AVL_BACK) { child = np->avl_back; CERT(np->avl_balance == AVL_BACK && child); if (child->avl_balance == AVL_BACK) { /* single LL */ /* * ``A'' just got inserted; * np points to ``E'', child to ``C'', * and it is already AVL_BACK -- * child will get promoted to top of subtree. np-> -E C / \ / \ child-> -C F -B E / \ / / \ -B D A D F / A Note that child->avl_parent and avl_balance get set in common code. */ np->avl_parent = child; np->avl_balance = AVL_BALANCE; np->avl_back = child->avl_forw; if (child->avl_forw) child->avl_forw->avl_parent = np; child->avl_forw = np; } else { /* * double LR * * child's avl_forw node gets promoted to * the top of the subtree. np-> -E C / \ / \ child-> +B F -B E / \ / / \ A +C A D F \ D */ avl64node_t *tmp = child->avl_forw; CERT(child->avl_balance == AVL_FORW && tmp); child->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = child; tmp->avl_back = child; child->avl_parent = tmp; np->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = np; tmp->avl_forw = np; np->avl_parent = tmp; if (tmp->avl_balance == AVL_BACK) np->avl_balance = AVL_FORW; else np->avl_balance = AVL_BALANCE; if (tmp->avl_balance == AVL_FORW) child->avl_balance = AVL_BACK; else child->avl_balance = AVL_BALANCE; /* * Set child to point to tmp since it is * now the top of the subtree, and will * get attached to the subtree parent in * the common code below. */ child = tmp; } } else /* growth == AVL_BACK */ { /* * This code is the mirror image of AVL_FORW above. */ child = np->avl_forw; CERT(np->avl_balance == AVL_FORW && child); if (child->avl_balance == AVL_FORW) { /* single RR */ np->avl_parent = child; np->avl_balance = AVL_BALANCE; np->avl_forw = child->avl_back; if (child->avl_back) child->avl_back->avl_parent = np; child->avl_back = np; } else { /* * double RL */ avl64node_t *tmp = child->avl_back; ASSERT(child->avl_balance == AVL_BACK && tmp); child->avl_back = tmp->avl_forw; if (tmp->avl_forw) tmp->avl_forw->avl_parent = child; tmp->avl_forw = child; child->avl_parent = tmp; np->avl_forw = tmp->avl_back; if (tmp->avl_back) tmp->avl_back->avl_parent = np; tmp->avl_back = np; np->avl_parent = tmp; if (tmp->avl_balance == AVL_FORW) np->avl_balance = AVL_BACK; else np->avl_balance = AVL_BALANCE; if (tmp->avl_balance == AVL_BACK) child->avl_balance = AVL_FORW; else child->avl_balance = AVL_BALANCE; child = tmp; } } child->avl_parent = parent; child->avl_balance = AVL_BALANCE; if (parent) { if (parent->avl_back == np) parent->avl_back = child; else parent->avl_forw = child; } else { ASSERT(*rootp == np); *rootp = child; } break; } } static avl64node_t * avl64_insert_find_growth( avl64tree_desc_t *tree, __uint64_t start, /* range start at start, */ __uint64_t end, /* exclusive */ int *growthp) /* OUT */ { avl64node_t *root = tree->avl_root; avl64node_t *np; np = root; ASSERT(np); /* caller ensures that there is atleast one node in tree */ for ( ; ; ) { CERT(np->avl_parent || root == np); CERT(!np->avl_parent || root != np); CERT(!(np->avl_back) || np->avl_back->avl_parent == np); CERT(!(np->avl_forw) || np->avl_forw->avl_parent == np); CERT(np->avl_balance != AVL_FORW || np->avl_forw); CERT(np->avl_balance != AVL_BACK || np->avl_back); CERT(np->avl_balance != AVL_BALANCE || np->avl_back == NULL || np->avl_forw); CERT(np->avl_balance != AVL_BALANCE || np->avl_forw == NULL || np->avl_back); if (AVL_START(tree, np) >= end) { if (np->avl_back) { np = np->avl_back; continue; } *growthp = AVL_BACK; break; } if (AVL_END(tree, np) <= start) { if (np->avl_forw) { np = np->avl_forw; continue; } *growthp = AVL_FORW; break; } /* found exact match -- let caller decide if it is an error */ return(NULL); } return(np); } static void avl64_insert_grow( avl64tree_desc_t *tree, avl64node_t *parent, avl64node_t *newnode, int growth) { avl64node_t *nnext; __uint64_t start = AVL_START(tree, newnode); if (growth == AVL_BACK) { parent->avl_back = newnode; /* * we are growing to the left; previous in-order to newnode is * closest ancestor with lesser value. Before this * insertion, this ancestor will be pointing to * newnode's parent. After insertion, next in-order to newnode * is the parent. */ newnode->avl_nextino = parent; nnext = parent; while (nnext) { if (AVL_END(tree, nnext) <= start) break; nnext = nnext->avl_parent; } if (nnext) { /* * nnext will be null if newnode is * the least element, and hence very first in the list. */ ASSERT(nnext->avl_nextino == parent); nnext->avl_nextino = newnode; } } else { parent->avl_forw = newnode; newnode->avl_nextino = parent->avl_nextino; parent->avl_nextino = newnode; } } avl64node_t * avl64_insert( avl64tree_desc_t *tree, avl64node_t *newnode) { avl64node_t *np; __uint64_t start = AVL_START(tree, newnode); __uint64_t end = AVL_END(tree, newnode); int growth; ASSERT(newnode); /* * Clean all pointers for sanity; some will be reset as necessary. */ newnode->avl_nextino = NULL; newnode->avl_parent = NULL; newnode->avl_forw = NULL; newnode->avl_back = NULL; newnode->avl_balance = AVL_BALANCE; if ((np = tree->avl_root) == NULL) { /* degenerate case... */ tree->avl_root = newnode; tree->avl_firstino = newnode; return newnode; } if ((np = avl64_insert_find_growth(tree, start, end, &growth)) == NULL) { if (start != end) { /* non-zero length range */ fprintf(stderr, _("avl_insert: Warning! duplicate range [%llu,%llu]\n"), (unsigned long long)start, (unsigned long long)end); } return(NULL); } avl64_insert_grow(tree, np, newnode, growth); if (growth == AVL_BACK) { /* * Growing to left. if np was firstino, newnode will be firstino */ if (tree->avl_firstino == np) tree->avl_firstino = newnode; } #ifdef notneeded else if (growth == AVL_FORW) /* * Cannot possibly be firstino; there is somebody to our left. */ ; #endif newnode->avl_parent = np; CERT(np->avl_forw == newnode || np->avl_back == newnode); avl64_balance(&tree->avl_root, np, growth); avl64_checktree(tree, tree->avl_root); return newnode; } /* * * avl64_insert_immediate(tree, afterp, newnode): * insert newnode immediately into tree immediately after afterp. * after insertion, newnode is right child of afterp. */ void avl64_insert_immediate( avl64tree_desc_t *tree, avl64node_t *afterp, avl64node_t *newnode) { /* * Clean all pointers for sanity; some will be reset as necessary. */ newnode->avl_nextino = NULL; newnode->avl_parent = NULL; newnode->avl_forw = NULL; newnode->avl_back = NULL; newnode->avl_balance = AVL_BALANCE; if (afterp == NULL) { tree->avl_root = newnode; tree->avl_firstino = newnode; return; } ASSERT(afterp->avl_forw == NULL); avl64_insert_grow(tree, afterp, newnode, AVL_FORW); /* grow to right */ CERT(afterp->avl_forw == newnode); avl64_balance(&tree->avl_root, afterp, AVL_FORW); avl64_checktree(tree, tree->avl_root); } /* * Returns first in order node */ avl64node_t * avl64_firstino(avl64node_t *root) { avl64node_t *np; if ((np = root) == NULL) return NULL; while (np->avl_back) np = np->avl_back; return np; } /* * Returns last in order node */ avl64node_t * avl64_lastino(avl64node_t *root) { avl64node_t *np; if ((np = root) == NULL) return NULL; while (np->avl_forw) np = np->avl_forw; return np; } void avl64_init_tree(avl64tree_desc_t *tree, avl64ops_t *ops) { tree->avl_root = NULL; tree->avl_firstino = NULL; tree->avl_ops = ops; } #ifdef AVL_DEBUG static void avl64_printnode(avl64tree_desc_t *tree, avl64node_t *np, int nl) { printf("[%d-%d]%c", AVL_START(tree, np), (AVL_END(tree, np) - 1), nl ? '\n' : ' '); } #endif #ifdef STAND_ALONE_DEBUG struct avl_debug_node { avl64node_t avl_node; xfs_off_t avl_start; unsigned int avl_size; } avl64ops_t avl_debug_ops = { avl_debug_start, avl_debug_end, } static __uint64_t avl64_debug_start(avl64node_t *node) { return (__uint64_t)(struct avl_debug_node *)node->avl_start; } static __uint64_t avl64_debug_end(avl64node_t *node) { return (__uint64_t) ((struct avl_debug_node *)node->avl_start + (struct avl_debug_node *)node->avl_size); } avl_debug_node freenodes[100]; avl_debug_node *freehead = &freenodes[0]; static avl64node_t * alloc_avl64_debug_node() { freehead->avl_balance = AVL_BALANCE; freehead->avl_parent = freehead->avl_forw = freehead->avl_back = NULL; return(freehead++); } static void avl64_print(avl64tree_desc_t *tree, avl64node_t *root, int depth) { int i; if (!root) return; if (root->avl_forw) avl64_print(tree, root->avl_forw, depth+5); for (i = 0; i < depth; i++) putchar((int) ' '); avl64_printnode(tree, root,1); if (root->avl_back) avl64_print(tree, root->avl_back, depth+5); } main() { int i, j; avl64node_t *np; avl64tree_desc_t tree; char linebuf[256], cmd[256]; avl64_init_tree(&tree, &avl_debug_ops); for (i = 100; i > 0; i = i - 10) { np = alloc__debug_avlnode(); ASSERT(np); np->avl_start = i; np->avl_size = 10; avl64_insert(&tree, np); } avl64_print(&tree, tree.avl_root, 0); for (np = tree.avl_firstino; np != NULL; np = np->avl_nextino) avl64_printnode(&tree, np, 0); printf("\n"); while (1) { printf(_("Command [fpdir] : ")); fgets(linebuf, 256, stdin); if (feof(stdin)) break; cmd[0] = NULL; if (sscanf(linebuf, "%[fpdir]%d", cmd, &i) != 2) continue; switch (cmd[0]) { case 'd': case 'f': printf(_("end of range ? ")); fgets(linebuf, 256, stdin); j = atoi(linebuf); if (i == j) j = i+1; np = avl64_findinrange(&tree,i,j); if (np) { avl64_printnode(&tree, np, 1); if (cmd[0] == 'd') avl64_delete(&tree, np); } else printf(_("Cannot find %d\n"), i); break; case 'p': avl64_print(&tree, tree.avl_root, 0); for (np = tree.avl_firstino; np != NULL; np = np->avl_nextino) avl64_printnode(&tree, np, 0); printf("\n"); break; case 'i': np = alloc_avlnode(); ASSERT(np); np->avl_start = i; printf(_("size of range ? ")); fgets(linebuf, 256, stdin); j = atoi(linebuf); np->avl_size = j; avl64_insert(&tree, np); break; case 'r': { avl64node_t *b, *e, *t; int checklen; printf(_("End of range ? ")); fgets(linebuf, 256, stdin); j = atoi(linebuf); printf(_("checklen 0/1 ? ")); fgets(linebuf, 256, stdin); checklen = atoi(linebuf); b = avl64_findanyrange(&tree, i, j, checklen); if (b) { printf(_("Found something\n")); t = b; while (t) { if (t != b && AVL_START(&tree, t) >= j) break; avl64_printnode(&tree, t, 0); t = t->avl_nextino; } printf("\n"); } } } } } #endif /* * Given a tree, find value; will find return range enclosing value, * or range immediately succeeding value, * or range immediately preceeding value. */ avl64node_t * avl64_findadjacent( avl64tree_desc_t *tree, __uint64_t value, int dir) { avl64node_t *np = tree->avl_root; while (np) { if (value < AVL_START(tree, np)) { if (np->avl_back) { np = np->avl_back; continue; } /* if we were to add node with value, would * have a growth of AVL_BACK */ if (dir == AVL_SUCCEED) { /* if succeeding node is needed, this is it. */ return(np); } if (dir == AVL_PRECEED) { /* * find nearest ancestor with lesser value. */ np = np->avl_parent; while (np) { if (AVL_END(tree, np) <= value) break; np = np->avl_parent; } return(np); } ASSERT(dir == AVL_SUCCEED || dir == AVL_PRECEED); break; } if (value >= AVL_END(tree, np)) { if (np->avl_forw) { np = np->avl_forw; continue; } /* if we were to add node with value, would * have a growth of AVL_FORW; */ if (dir == AVL_SUCCEED) { /* we are looking for a succeeding node; * this is nextino. */ return(np->avl_nextino); } if (dir == AVL_PRECEED) { /* looking for a preceeding node; this is it. */ return(np); } ASSERT(dir == AVL_SUCCEED || dir == AVL_PRECEED); } /* AVL_START(tree, np) <= value < AVL_END(tree, np) */ return(np); } return NULL; } /* * avl_findranges: * * Given range r [start, end), find all ranges in tree which are contained * in r. At return, startp and endp point to first and last of * a chain of elements which describe the contained ranges. Elements * in startp ... endp are in sort order, and can be accessed by * using avl_nextino. */ void avl64_findranges( avl64tree_desc_t *tree, __uint64_t start, __uint64_t end, avl64node_t **startp, avl64node_t **endp) { avl64node_t *np; np = avl64_findadjacent(tree, start, AVL_SUCCEED); if (np == NULL /* nothing succeding start */ || (np && (end <= AVL_START(tree, np)))) /* something follows start, but... is entirely after end */ { *startp = NULL; *endp = NULL; return; } *startp = np; /* see if end is in this region itself */ if (end <= AVL_END(tree, np) || np->avl_nextino == NULL || (np->avl_nextino && (end <= AVL_START(tree, np->avl_nextino)))) { *endp = np; return; } /* have to munge for end */ /* * note: have to look for (end - 1), since * findadjacent will look for exact value, and does not * care about the fact that end is actually one more * than the value actually being looked for; thus feed it one less. */ *endp = avl64_findadjacent(tree, (end-1), AVL_PRECEED); ASSERT(*endp); } xfsprogs-4.9.0+nmu1ubuntu2/repair/avl64.h0000644000000000000000000000570513063067172015071 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __XR_AVL64_H__ #define __XR_AVL64_H__ #include typedef struct avl64node { struct avl64node *avl_forw; /* pointer to right child (> parent) */ struct avl64node *avl_back; /* pointer to left child (< parent) */ struct avl64node *avl_parent; /* parent pointer */ struct avl64node *avl_nextino; /* next in-order; NULL terminated list*/ char avl_balance; /* tree balance */ } avl64node_t; /* * avl-tree operations */ typedef struct avl64ops { __uint64_t (*avl_start)(avl64node_t *); __uint64_t (*avl_end)(avl64node_t *); } avl64ops_t; /* * avoid complaints about multiple def's since these are only used by * the avl code internally */ #ifndef AVL_START #define AVL_START(tree, n) (*(tree)->avl_ops->avl_start)(n) #define AVL_END(tree, n) (*(tree)->avl_ops->avl_end)(n) #endif /* * tree descriptor: * root points to the root of the tree. * firstino points to the first in the ordered list. */ typedef struct avl64tree_desc { avl64node_t *avl_root; avl64node_t *avl_firstino; avl64ops_t *avl_ops; } avl64tree_desc_t; /* possible values for avl_balance */ #define AVL_BACK 1 #define AVL_BALANCE 0 #define AVL_FORW 2 /* * 'Exported' avl tree routines */ avl64node_t *avl64_insert( avl64tree_desc_t *tree, avl64node_t *newnode); void avl64_delete( avl64tree_desc_t *tree, avl64node_t *np); void avl64_insert_immediate( avl64tree_desc_t *tree, avl64node_t *afterp, avl64node_t *newnode); void avl64_init_tree( avl64tree_desc_t *tree, avl64ops_t *ops); avl64node_t * avl64_findrange( avl64tree_desc_t *tree, __uint64_t value); avl64node_t * avl64_find( avl64tree_desc_t *tree, __uint64_t value); avl64node_t * avl64_findanyrange( avl64tree_desc_t *tree, __uint64_t start, __uint64_t end, int checklen); avl64node_t * avl64_findadjacent( avl64tree_desc_t *tree, __uint64_t value, int dir); void avl64_findranges( avl64tree_desc_t *tree, __uint64_t start, __uint64_t end, avl64node_t **startp, avl64node_t **endp); /* * avoid complaints about multiple def's since these are only used by * the avl code internally */ #ifndef AVL_PRECEED #define AVL_PRECEED 0x1 #define AVL_SUCCEED 0x2 #define AVL_INCLUDE_ZEROLEN 0x0000 #define AVL_EXCLUDE_ZEROLEN 0x0001 #endif #endif /* __XR_AVL64_H__ */ xfsprogs-4.9.0+nmu1ubuntu2/repair/bmap.c0000644000000000000000000002200113063067173015034 0ustar /* * Copyright (c) 2000-2001,2005,2008 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "err_protos.h" #include "bmap.h" /* * Track the logical to physical block mapping for inodes. * * Repair only processes one inode at a given time per thread, and the * block map does not have to outlive the processing of a single inode. * * The combination of those factors means we can use pthreads thread-local * storage to store the block map, and we can re-use the allocation over * and over again. */ pthread_key_t dblkmap_key; pthread_key_t ablkmap_key; blkmap_t * blkmap_alloc( xfs_extnum_t nex, int whichfork) { pthread_key_t key; blkmap_t *blkmap; ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK); if (nex < 1) nex = 1; #if (BITS_PER_LONG == 32) /* on 64-bit platforms this is never true */ if (nex > BLKMAP_NEXTS_MAX) { do_warn( _("Number of extents requested in blkmap_alloc (%d) overflows 32 bits.\n" "If this is not a corruption, then you will need a 64 bit system\n" "to repair this filesystem.\n"), nex); return NULL; } #endif key = whichfork ? ablkmap_key : dblkmap_key; blkmap = pthread_getspecific(key); if (!blkmap || blkmap->naexts < nex) { blkmap = realloc(blkmap, BLKMAP_SIZE(nex)); if (!blkmap) { do_warn(_("malloc failed in blkmap_alloc (%zu bytes)\n"), BLKMAP_SIZE(nex)); return NULL; } pthread_setspecific(key, blkmap); blkmap->naexts = nex; } blkmap->nexts = 0; return blkmap; } /* * Free a block map. * * If the map is a large, uncommon size (say for hundreds of thousands of * extents) then free it to release the memory. This prevents us from pinning * large tracts of memory due to corrupted fork values or one-off fragmented * files. Otherwise we have nothing to do but keep the memory around for the * next inode. * When the thread is done, it should do an unconditional, final free. */ void blkmap_free( blkmap_t *blkmap) { if (!blkmap) return; /* consider more than 100k extents rare */ if (blkmap->naexts < 100 * 1024) return; if (blkmap == pthread_getspecific(dblkmap_key)) pthread_setspecific(dblkmap_key, NULL); else pthread_setspecific(ablkmap_key, NULL); free(blkmap); } void blkmap_free_final(void) { blkmap_t *blkmap; blkmap = pthread_getspecific(dblkmap_key); pthread_setspecific(dblkmap_key, NULL); free(blkmap); blkmap = pthread_getspecific(ablkmap_key); pthread_setspecific(ablkmap_key, NULL); free(blkmap); } /* * Get one entry from a block map. */ xfs_fsblock_t blkmap_get( blkmap_t *blkmap, xfs_fileoff_t o) { bmap_ext_t *ext = blkmap->exts; int i; for (i = 0; i < blkmap->nexts; i++, ext++) { if (o >= ext->startoff && o < ext->startoff + ext->blockcount) return ext->startblock + (o - ext->startoff); } return NULLFSBLOCK; } /* * Get a chunk of entries from a block map - only used for reading dirv2 blocks */ int blkmap_getn( blkmap_t *blkmap, xfs_fileoff_t o, xfs_filblks_t nb, bmap_ext_t **bmpp, bmap_ext_t *bmpp_single) { bmap_ext_t *bmp = NULL; bmap_ext_t *ext; int i; int nex; if (nb == 1) { /* * in the common case, when mp->m_dirblkfsbs == 1, * avoid additional malloc/free overhead */ bmpp_single->startblock = blkmap_get(blkmap, o); goto single_ext; } ext = blkmap->exts; nex = 0; for (i = 0; i < blkmap->nexts; i++, ext++) { if (ext->startoff >= o + nb) break; if (ext->startoff + ext->blockcount <= o) continue; /* * if all the requested blocks are in one extent (also common), * use the bmpp_single option as well */ if (!bmp && o >= ext->startoff && o + nb <= ext->startoff + ext->blockcount) { bmpp_single->startblock = ext->startblock + (o - ext->startoff); goto single_ext; } /* * rare case - multiple extents for a single dir block */ if (!bmp) bmp = malloc(nb * sizeof(bmap_ext_t)); if (!bmp) do_error(_("blkmap_getn malloc failed (%" PRIu64 " bytes)\n"), nb * sizeof(bmap_ext_t)); bmp[nex].startblock = ext->startblock + (o - ext->startoff); bmp[nex].blockcount = MIN(nb, ext->blockcount - (bmp[nex].startblock - ext->startblock)); o += bmp[nex].blockcount; nb -= bmp[nex].blockcount; nex++; } *bmpp = bmp; return nex; single_ext: bmpp_single->blockcount = nb; bmpp_single->startoff = 0; /* not even used by caller! */ *bmpp = bmpp_single; return (bmpp_single->startblock != NULLFSBLOCK) ? 1 : 0; } /* * Return the last offset in a block map. */ xfs_fileoff_t blkmap_last_off( blkmap_t *blkmap) { bmap_ext_t *ext; if (!blkmap->nexts) return NULLFILEOFF; ext = blkmap->exts + blkmap->nexts - 1; return ext->startoff + ext->blockcount; } /** * blkmap_next_off - Return next logical block offset in a block map. * @blkmap: blockmap to use * @o: current file logical block number * @t: current extent index into blockmap (in/out) * * Given a logical block offset in a file, return the next mapped logical offset * The map index "t" tracks the current extent number in the block map, and * is updated automatically if the returned offset resides within the next * mapped extent. * * If the blockmap contains no extents, or no more logical offsets are mapped, * or the extent index exceeds the number of extents in the map, * return NULLFILEOFF. * * If offset o is beyond extent index t, the first offset in the next extent * after extent t will be returned. * * Intended to be called starting with offset 0, index 0, and iterated. */ xfs_fileoff_t blkmap_next_off( blkmap_t *blkmap, xfs_fileoff_t o, int *t) { bmap_ext_t *ext; if (!blkmap->nexts) return NULLFILEOFF; if (o == NULLFILEOFF) { *t = 0; return blkmap->exts[0].startoff; } if (*t >= blkmap->nexts) return NULLFILEOFF; ext = blkmap->exts + *t; if (o < ext->startoff + ext->blockcount - 1) return o + 1; if (*t == blkmap->nexts - 1) return NULLFILEOFF; (*t)++; return ext[1].startoff; } /* * Make a block map larger. */ static blkmap_t * blkmap_grow( blkmap_t *blkmap) { pthread_key_t key = dblkmap_key; blkmap_t *new_blkmap; int new_naexts; /* reduce the number of reallocations for large files */ if (blkmap->naexts < 1000) new_naexts = blkmap->naexts + 4; else if (blkmap->naexts < 10000) new_naexts = blkmap->naexts + 100; else new_naexts = blkmap->naexts + 1000; if (pthread_getspecific(key) != blkmap) { key = ablkmap_key; ASSERT(pthread_getspecific(key) == blkmap); } #if (BITS_PER_LONG == 32) /* on 64-bit platforms this is never true */ if (new_naexts > BLKMAP_NEXTS_MAX) { do_error( _("Number of extents requested in blkmap_grow (%d) overflows 32 bits.\n" "You need a 64 bit system to repair this filesystem.\n"), new_naexts); return NULL; } #endif if (new_naexts <= 0) { do_error( _("Number of extents requested in blkmap_grow (%d) overflowed the\n" "maximum number of supported extents (%d).\n"), new_naexts, BLKMAP_NEXTS_MAX); return NULL; } new_blkmap = realloc(blkmap, BLKMAP_SIZE(new_naexts)); if (!new_blkmap) { do_error(_("realloc failed in blkmap_grow\n")); return NULL; } new_blkmap->naexts = new_naexts; pthread_setspecific(key, new_blkmap); return new_blkmap; } /* * Set an extent into a block map. * * If this function fails, it leaves the blkmapp untouched so the caller can * handle the error and free the blkmap appropriately. */ int blkmap_set_ext( blkmap_t **blkmapp, xfs_fileoff_t o, xfs_fsblock_t b, xfs_filblks_t c) { blkmap_t *blkmap = *blkmapp; xfs_extnum_t i; if (blkmap->nexts == blkmap->naexts) { blkmap = blkmap_grow(blkmap); if (!blkmap) return ENOMEM; *blkmapp = blkmap; } ASSERT(blkmap->nexts < blkmap->naexts); if (blkmap->nexts == 0) { i = 0; goto insert; } /* * The most common insert pattern comes from an ascending offset order * bmapbt scan. In this case, the extent being added will end up at the * end of the array. Hence do a reverse order search for the insertion * point so we don't needlessly scan the entire array on every * insertion. * * Also, use "plus 1" indexing for the loop counter so when we break out * of the loop we are at the correct index for insertion. */ for (i = blkmap->nexts; i > 0; i--) { if (blkmap->exts[i - 1].startoff < o) break; } /* make space for the new extent */ memmove(blkmap->exts + i + 1, blkmap->exts + i, sizeof(bmap_ext_t) * (blkmap->nexts - i)); insert: blkmap->exts[i].startoff = o; blkmap->exts[i].startblock = b; blkmap->exts[i].blockcount = c; blkmap->nexts++; return 0; } xfsprogs-4.9.0+nmu1ubuntu2/repair/bmap.h0000644000000000000000000000430113063067172015043 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XFS_REPAIR_BMAP_H #define _XFS_REPAIR_BMAP_H /* * Extent descriptor. */ typedef struct bmap_ext { xfs_fileoff_t startoff; xfs_fsblock_t startblock; xfs_filblks_t blockcount; } bmap_ext_t; /* * Block map. */ typedef struct blkmap { int naexts; int nexts; bmap_ext_t exts[1]; } blkmap_t; #define BLKMAP_SIZE(n) \ (offsetof(blkmap_t, exts) + (sizeof(bmap_ext_t) * (n))) /* * For 32 bit platforms, we are limited to extent arrays of 2^31 bytes, which * limits the number of extents in an inode we can check. If we don't limit the * valid range, we can overflow the BLKMAP_SIZE() calculation and allocate less * memory than we think we needed, and hence walk off the end of the array and * corrupt memory. */ #if BITS_PER_LONG == 32 #define BLKMAP_NEXTS_MAX ((INT_MAX / sizeof(bmap_ext_t)) - 1) #else #define BLKMAP_NEXTS_MAX INT_MAX #endif extern pthread_key_t dblkmap_key; extern pthread_key_t ablkmap_key; blkmap_t *blkmap_alloc(xfs_extnum_t nex, int whichfork); void blkmap_free(blkmap_t *blkmap); void blkmap_free_final(void); int blkmap_set_ext(blkmap_t **blkmapp, xfs_fileoff_t o, xfs_fsblock_t b, xfs_filblks_t c); xfs_fsblock_t blkmap_get(blkmap_t *blkmap, xfs_fileoff_t o); int blkmap_getn(blkmap_t *blkmap, xfs_fileoff_t o, xfs_filblks_t nb, bmap_ext_t **bmpp, bmap_ext_t *bmpp_single); xfs_fileoff_t blkmap_last_off(blkmap_t *blkmap); xfs_fileoff_t blkmap_next_off(blkmap_t *blkmap, xfs_fileoff_t o, int *t); #endif /* _XFS_REPAIR_BMAP_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/btree.c0000644000000000000000000006412113063067172015226 0ustar /* * Copyright (c) 2007, Silicon Graphics, Inc. Barry Naujok * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "btree.h" /* * Maximum number of keys per node. Must be greater than 2 for the code * to work. */ #define BTREE_KEY_MAX 7 #define BTREE_KEY_MIN (BTREE_KEY_MAX / 2) #define BTREE_PTR_MAX (BTREE_KEY_MAX + 1) struct btree_node { unsigned long num_keys; unsigned long keys[BTREE_KEY_MAX]; struct btree_node *ptrs[BTREE_PTR_MAX]; }; struct btree_cursor { struct btree_node *node; int index; }; struct btree_root { struct btree_node *root_node; struct btree_cursor *cursor; /* track path to end leaf */ int height; /* lookup cache */ int keys_valid; /* set if the cache is valid */ unsigned long cur_key; unsigned long next_key; void *next_value; unsigned long prev_key; void *prev_value; #ifdef BTREE_STATS struct btree_stats { unsigned long num_items; unsigned long max_items; int alloced; int cache_hits; int cache_misses; int lookup; int find; int key_update; int value_update; int insert; int delete; int inc_height; int dec_height; int shift_prev; int shift_next; int split; int merge_prev; int merge_next; int balance_prev; int balance_next; } stats; #endif }; static struct btree_node * btree_node_alloc(void) { return calloc(1, sizeof(struct btree_node)); } static void btree_node_free( struct btree_node *node) { free(node); } static void btree_free_nodes( struct btree_node *node, int level) { int i; if (level) for (i = 0; i <= node->num_keys; i++) btree_free_nodes(node->ptrs[i], level - 1); btree_node_free(node); } static void __btree_init( struct btree_root *root) { memset(root, 0, sizeof(struct btree_root)); root->height = 1; root->cursor = calloc(1, sizeof(struct btree_cursor)); root->root_node = btree_node_alloc(); ASSERT(root->root_node); #ifdef BTREE_STATS root->stats.max_items = 1; root->stats.alloced += 1; #endif } static void __btree_free( struct btree_root *root) { btree_free_nodes(root->root_node, root->height - 1); free(root->cursor); root->height = 0; root->cursor = NULL; root->root_node = NULL; } void btree_init( struct btree_root **root) { *root = calloc(1, sizeof(struct btree_root)); __btree_init(*root); } void btree_clear( struct btree_root *root) { __btree_free(root); __btree_init(root); } void btree_destroy( struct btree_root *root) { __btree_free(root); free(root); } int btree_is_empty( struct btree_root *root) { return root->root_node->num_keys == 0; } static inline void btree_invalidate_cursor( struct btree_root *root) { root->cursor[0].node = NULL; root->keys_valid = 0; } static inline unsigned long btree_key_of_cursor( struct btree_cursor *cursor, int height) { while (cursor->node->num_keys == cursor->index && --height > 0) cursor++; return cursor->node->keys[cursor->index]; } static void * btree_get_prev( struct btree_root *root, unsigned long *key) { struct btree_cursor *cur = root->cursor; int level = 0; struct btree_node *node; if (cur->index > 0) { if (key) *key = cur->node->keys[cur->index - 1]; return cur->node->ptrs[cur->index - 1]; } /* else need to go up and back down the tree to find the previous */ do { if (cur->index) break; cur++; } while (++level < root->height); if (level == root->height) return NULL; /* the key is in the current level */ if (key) *key = cur->node->keys[cur->index - 1]; /* descend back down the right side to get the pointer */ node = cur->node->ptrs[cur->index - 1]; while (level--) node = node->ptrs[node->num_keys]; return node; } static void * btree_get_next( struct btree_root *root, unsigned long *key) { struct btree_cursor *cur = root->cursor; int level = 0; struct btree_node *node; while (cur->index == cur->node->num_keys) { if (++level == root->height) return NULL; cur++; } if (level == 0) { if (key) { cur->index++; *key = btree_key_of_cursor(cur, root->height); cur->index--; } return cur->node->ptrs[cur->index + 1]; } node = cur->node->ptrs[cur->index + 1]; while (--level > 0) node = node->ptrs[0]; if (key) *key = node->keys[0]; return node->ptrs[0]; } /* * Lookup/Search functions */ static int btree_do_search( struct btree_root *root, unsigned long key) { unsigned long k = 0; struct btree_cursor *cur = root->cursor + root->height; struct btree_node *node = root->root_node; int height = root->height; int key_found = 0; int i; while (--height >= 0) { cur--; for (i = 0; i < node->num_keys; i++) if (node->keys[i] >= key) { k = node->keys[i]; key_found = 1; break; } cur->node = node; cur->index = i; node = node->ptrs[i]; } root->keys_valid = key_found; if (!key_found) return 0; root->cur_key = k; root->next_value = NULL; /* do on-demand next value lookup */ root->prev_value = btree_get_prev(root, &root->prev_key); return 1; } static int btree_search( struct btree_root *root, unsigned long key) { if (root->keys_valid && key <= root->cur_key && (!root->prev_value || key > root->prev_key)) { #ifdef BTREE_STATS root->stats.cache_hits++; #endif return 1; } #ifdef BTREE_STATS root->stats.cache_misses++; #endif return btree_do_search(root, key); } void * btree_find( struct btree_root *root, unsigned long key, unsigned long *actual_key) { #ifdef BTREE_STATS root->stats.find += 1; #endif if (!btree_search(root, key)) return NULL; if (actual_key) *actual_key = root->cur_key; return root->cursor->node->ptrs[root->cursor->index]; } void * btree_lookup( struct btree_root *root, unsigned long key) { #ifdef BTREE_STATS root->stats.lookup += 1; #endif if (!btree_search(root, key) || root->cur_key != key) return NULL; return root->cursor->node->ptrs[root->cursor->index]; } void * btree_peek_prev( struct btree_root *root, unsigned long *key) { if (!root->keys_valid) return NULL; if (key) *key = root->prev_key; return root->prev_value; } void * btree_peek_next( struct btree_root *root, unsigned long *key) { if (!root->keys_valid) return NULL; if (!root->next_value) root->next_value = btree_get_next(root, &root->next_key); if (key) *key = root->next_key; return root->next_value; } static void * btree_move_cursor_to_next( struct btree_root *root, unsigned long *key) { struct btree_cursor *cur = root->cursor; int level = 0; while (cur->index == cur->node->num_keys) { if (++level == root->height) return NULL; cur++; } cur->index++; if (level == 0) { if (key) *key = btree_key_of_cursor(cur, root->height); return cur->node->ptrs[cur->index]; } while (--level >= 0) { root->cursor[level].node = cur->node->ptrs[cur->index]; root->cursor[level].index = 0; cur--; } if (key) *key = cur->node->keys[0]; return cur->node->ptrs[0]; } void * btree_lookup_next( struct btree_root *root, unsigned long *key) { void *value; if (!root->keys_valid) return NULL; root->prev_key = root->cur_key; root->prev_value = root->cursor->node->ptrs[root->cursor->index]; value = btree_move_cursor_to_next(root, &root->cur_key); if (!value) { btree_invalidate_cursor(root); return NULL; } root->next_value = NULL; /* on-demand next value fetch */ if (key) *key = root->cur_key; return value; } static void * btree_move_cursor_to_prev( struct btree_root *root, unsigned long *key) { struct btree_cursor *cur = root->cursor; int level = 0; while (cur->index == 0) { if (++level == root->height) return NULL; cur++; } cur->index--; if (key) /* the key is in the current level */ *key = cur->node->keys[cur->index]; while (level > 0) { level--; root->cursor[level].node = cur->node->ptrs[cur->index]; root->cursor[level].index = root->cursor[level].node->num_keys; cur--; } return cur->node->ptrs[cur->index]; } void * btree_lookup_prev( struct btree_root *root, unsigned long *key) { void *value; if (!root->keys_valid) return NULL; value = btree_move_cursor_to_prev(root, &root->cur_key); if (!value) return NULL; root->prev_value = btree_get_prev(root, &root->prev_key); root->next_value = NULL; /* on-demand next value fetch */ if (key) *key = root->cur_key; return value; } void * btree_uncached_lookup( struct btree_root *root, unsigned long key) { /* cursor-less (ie. uncached) lookup */ int height = root->height - 1; struct btree_node *node = root->root_node; int i; int key_found = 0; while (height >= 0) { for (i = 0; i < node->num_keys; i++) if (node->keys[i] >= key) { key_found = node->keys[i] == key; break; } node = node->ptrs[i]; height--; } return key_found ? node : NULL; } /* Update functions */ static inline void btree_update_node_key( struct btree_root *root, struct btree_cursor *cursor, int level, unsigned long new_key) { int i; #ifdef BTREE_STATS root->stats.key_update += 1; #endif cursor += level; for (i = level; i < root->height; i++) { if (cursor->index < cursor->node->num_keys) { cursor->node->keys[cursor->index] = new_key; break; } cursor++; } } int btree_update_key( struct btree_root *root, unsigned long old_key, unsigned long new_key) { if (!btree_search(root, old_key) || root->cur_key != old_key) return ENOENT; if (root->next_value && new_key >= root->next_key) return EINVAL; if (root->prev_value && new_key <= root->prev_key) return EINVAL; btree_update_node_key(root, root->cursor, 0, new_key); root->cur_key = new_key; return 0; } int btree_update_value( struct btree_root *root, unsigned long key, void *new_value) { if (!new_value) return EINVAL; if (!btree_search(root, key) || root->cur_key != key) return ENOENT; #ifdef BTREE_STATS root->stats.value_update += 1; #endif root->cursor->node->ptrs[root->cursor->index] = new_value; return 0; } /* * Cursor modification functions - used for inserting and deleting */ static struct btree_cursor * btree_copy_cursor_prev( struct btree_root *root, struct btree_cursor *dest_cursor, int level) { struct btree_cursor *src_cur = root->cursor + level; struct btree_cursor *dst_cur; int l = level; int i; if (level >= root->height) return NULL; while (src_cur->index == 0) { if (++l >= root->height) return NULL; src_cur++; } for (i = l; i < root->height; i++) dest_cursor[i] = *src_cur++; dst_cur = dest_cursor + l; dst_cur->index--; while (l-- >= level) { dest_cursor[l].node = dst_cur->node->ptrs[dst_cur->index]; dest_cursor[l].index = dest_cursor[l].node->num_keys; dst_cur--; } return dest_cursor; } static struct btree_cursor * btree_copy_cursor_next( struct btree_root *root, struct btree_cursor *dest_cursor, int level) { struct btree_cursor *src_cur = root->cursor + level; struct btree_cursor *dst_cur; int l = level; int i; if (level >= root->height) return NULL; while (src_cur->index == src_cur->node->num_keys) { if (++l >= root->height) return NULL; src_cur++; } for (i = l; i < root->height; i++) dest_cursor[i] = *src_cur++; dst_cur = dest_cursor + l; dst_cur->index++; while (l-- >= level) { dest_cursor[l].node = dst_cur->node->ptrs[dst_cur->index]; dest_cursor[l].index = 0; dst_cur--; } return dest_cursor; } /* * Shift functions * * Tries to move items in the current leaf to its sibling if it has space. * Used in both insert and delete functions. * Returns the number of items shifted. */ static int btree_shift_to_prev( struct btree_root *root, int level, struct btree_cursor *prev_cursor, int num_children) { struct btree_node *node; struct btree_node *prev_node; int num_remain; /* # of keys left in "node" */ unsigned long key; int i; if (!prev_cursor || !num_children) return 0; prev_node = prev_cursor[level].node; node = root->cursor[level].node; ASSERT(num_children > 0 && num_children <= node->num_keys + 1); if ((prev_node->num_keys + num_children) > BTREE_KEY_MAX) return 0; #ifdef BTREE_STATS root->stats.shift_prev += 1; #endif num_remain = node->num_keys - num_children; ASSERT(num_remain == -1 || num_remain >= BTREE_KEY_MIN); /* shift parent keys around */ level++; if (num_remain > 0) key = node->keys[num_children - 1]; else key = btree_key_of_cursor(root->cursor + level, root->height - level); while (prev_cursor[level].index == prev_cursor[level].node->num_keys) { level++; ASSERT(level < root->height); } prev_node->keys[prev_node->num_keys] = prev_cursor[level].node->keys[prev_cursor[level].index]; prev_cursor[level].node->keys[prev_cursor[level].index] = key; /* copy pointers and keys to the end of the prev node */ for (i = 0; i < num_children - 1; i++) { prev_node->keys[prev_node->num_keys + 1 + i] = node->keys[i]; prev_node->ptrs[prev_node->num_keys + 1 + i] = node->ptrs[i]; } prev_node->ptrs[prev_node->num_keys + 1 + i] = node->ptrs[i]; prev_node->num_keys += num_children; /* move remaining pointers/keys to start of node */ if (num_remain >= 0) { for (i = 0; i < num_remain; i++) { node->keys[i] = node->keys[num_children + i]; node->ptrs[i] = node->ptrs[num_children + i]; } node->ptrs[i] = node->ptrs[num_children + i]; node->num_keys = num_remain; } else node->num_keys = 0; return num_children; } static int btree_shift_to_next( struct btree_root *root, int level, struct btree_cursor *next_cursor, int num_children) { struct btree_node *node; struct btree_node *next_node; int num_remain; /* # of children left in node */ int i; if (!next_cursor || !num_children) return 0; node = root->cursor[level].node; next_node = next_cursor[level].node; ASSERT(num_children > 0 && num_children <= node->num_keys + 1); if ((next_node->num_keys + num_children) > BTREE_KEY_MAX) return 0; num_remain = node->num_keys + 1 - num_children; ASSERT(num_remain == 0 || num_remain > BTREE_KEY_MIN); #ifdef BTREE_STATS root->stats.shift_next += 1; #endif /* make space for "num_children" items at beginning of next-leaf */ i = next_node->num_keys; next_node->ptrs[num_children + i] = next_node->ptrs[i]; while (--i >= 0) { next_node->keys[num_children + i] = next_node->keys[i]; next_node->ptrs[num_children + i] = next_node->ptrs[i]; } /* update keys in parent and next node from parent */ do { level++; ASSERT(level < root->height); } while (root->cursor[level].index == root->cursor[level].node->num_keys); next_node->keys[num_children - 1] = root->cursor[level].node->keys[root->cursor[level].index]; root->cursor[level].node->keys[root->cursor[level].index] = node->keys[node->num_keys - num_children]; /* copy last "num_children" items from node into start of next-node */ for (i = 0; i < num_children - 1; i++) { next_node->keys[i] = node->keys[num_remain + i]; next_node->ptrs[i] = node->ptrs[num_remain + i]; } next_node->ptrs[i] = node->ptrs[num_remain + i]; next_node->num_keys += num_children; if (num_remain > 0) node->num_keys -= num_children; else node->num_keys = 0; return num_children; } /* * Insertion functions */ static struct btree_node * btree_increase_height( struct btree_root *root) { struct btree_node *new_root; struct btree_cursor *new_cursor; new_cursor = realloc(root->cursor, (root->height + 1) * sizeof(struct btree_cursor)); if (!new_cursor) return NULL; root->cursor = new_cursor; new_root = btree_node_alloc(); if (!new_root) return NULL; #ifdef BTREE_STATS root->stats.alloced += 1; root->stats.inc_height += 1; root->stats.max_items *= BTREE_PTR_MAX; #endif new_root->ptrs[0] = root->root_node; root->root_node = new_root; root->cursor[root->height].node = new_root; root->cursor[root->height].index = 0; root->height++; return new_root; } static int btree_insert_item( struct btree_root *root, int level, unsigned long key, void *value); static struct btree_node * btree_split( struct btree_root *root, int level, unsigned long key, int *index) { struct btree_node *node = root->cursor[level].node; struct btree_node *new_node; int i; new_node = btree_node_alloc(); if (!new_node) return NULL; if (btree_insert_item(root, level + 1, node->keys[BTREE_KEY_MIN], new_node) != 0) { btree_node_free(new_node); return NULL; } #ifdef BTREE_STATS root->stats.alloced += 1; root->stats.split += 1; #endif for (i = 0; i < BTREE_KEY_MAX - BTREE_KEY_MIN - 1; i++) { new_node->keys[i] = node->keys[BTREE_KEY_MIN + 1 + i]; new_node->ptrs[i] = node->ptrs[BTREE_KEY_MIN + 1 + i]; } new_node->ptrs[i] = node->ptrs[BTREE_KEY_MIN + 1 + i]; new_node->num_keys = BTREE_KEY_MAX - BTREE_KEY_MIN - 1; node->num_keys = BTREE_KEY_MIN; if (key < node->keys[BTREE_KEY_MIN]) return node; /* index doesn't change */ /* insertion point is in new node... */ *index -= BTREE_KEY_MIN + 1; return new_node; } static int btree_insert_shift_to_prev( struct btree_root *root, int level, int *index) { struct btree_cursor tmp_cursor[root->height]; int n; if (*index <= 0) return -1; if (!btree_copy_cursor_prev(root, tmp_cursor, level + 1)) return -1; n = MIN(*index, (BTREE_PTR_MAX - tmp_cursor[level].node->num_keys) / 2); if (!n || !btree_shift_to_prev(root, level, tmp_cursor, n)) return -1; *index -= n; return 0; } static int btree_insert_shift_to_next( struct btree_root *root, int level, int *index) { struct btree_cursor tmp_cursor[root->height]; int n; if (*index >= BTREE_KEY_MAX) return -1; if (!btree_copy_cursor_next(root, tmp_cursor, level + 1)) return -1; n = MIN(BTREE_KEY_MAX - *index, (BTREE_PTR_MAX - tmp_cursor[level].node->num_keys) / 2); if (!n || !btree_shift_to_next(root, level, tmp_cursor, n)) return -1; return 0; } static int btree_insert_item( struct btree_root *root, int level, unsigned long key, void *value) { struct btree_node *node = root->cursor[level].node; int index = root->cursor[level].index; int i; if (node->num_keys == BTREE_KEY_MAX) { if (btree_insert_shift_to_prev(root, level, &index) == 0) goto insert; if (btree_insert_shift_to_next(root, level, &index) == 0) goto insert; if (level == root->height - 1) { if (!btree_increase_height(root)) return ENOMEM; } node = btree_split(root, level, key, &index); if (!node) return ENOMEM; } insert: ASSERT(index <= node->num_keys); i = node->num_keys; node->ptrs[i + 1] = node->ptrs[i]; while (--i >= index) { node->keys[i + 1] = node->keys[i]; node->ptrs[i + 1] = node->ptrs[i]; } node->num_keys++; node->keys[index] = key; if (level == 0) node->ptrs[index] = value; else node->ptrs[index + 1] = value; return 0; } int btree_insert( struct btree_root *root, unsigned long key, void *value) { int result; if (!value) return EINVAL; if (btree_search(root, key) && root->cur_key == key) return EEXIST; #ifdef BTREE_STATS root->stats.insert += 1; root->stats.num_items += 1; #endif result = btree_insert_item(root, 0, key, value); btree_invalidate_cursor(root); return result; } /* * Deletion functions * * Rather more complicated as deletions has 4 ways to go once a node * ends up with less than the minimum number of keys: * - move remainder to previous node * - move remainder to next node * (both will involve a parent deletion which may recurse) * - balance by moving some items from previous node * - balance by moving some items from next node */ static void btree_decrease_height( struct btree_root *root) { struct btree_node *old_root = root->root_node; ASSERT(old_root->num_keys == 0); #ifdef BTREE_STATS root->stats.alloced -= 1; root->stats.dec_height += 1; root->stats.max_items /= BTREE_PTR_MAX; #endif root->root_node = old_root->ptrs[0]; btree_node_free(old_root); root->height--; } static int btree_merge_with_prev( struct btree_root *root, int level, struct btree_cursor *prev_cursor) { if (!prev_cursor) return 0; if (!btree_shift_to_prev(root, level, prev_cursor, root->cursor[level].node->num_keys + 1)) return 0; #ifdef BTREE_STATS root->stats.merge_prev += 1; #endif return 1; } static int btree_merge_with_next( struct btree_root *root, int level, struct btree_cursor *next_cursor) { if (!next_cursor) return 0; if (!btree_shift_to_next(root, level, next_cursor, root->cursor[level].node->num_keys + 1)) return 0; #ifdef BTREE_STATS root->stats.merge_next += 1; #endif return 1; } static int btree_balance_with_prev( struct btree_root *root, int level, struct btree_cursor *prev_cursor) { struct btree_cursor *root_cursor = root->cursor; if (!prev_cursor) return 0; ASSERT(prev_cursor[level].node->num_keys > BTREE_KEY_MIN); #ifdef BTREE_STATS root->stats.balance_prev += 1; #endif /* * Move some nodes from the prev node into the current node. * As the shift operation is a right shift and is relative to * the root cursor, make the root cursor the prev cursor and * pass in the root cursor as the next cursor. */ root->cursor = prev_cursor; if (!btree_shift_to_next(root, level, root_cursor, (prev_cursor[level].node->num_keys + 1 - BTREE_KEY_MIN) / 2)) abort(); root->cursor = root_cursor; return 1; } static int btree_balance_with_next( struct btree_root *root, int level, struct btree_cursor *next_cursor) { struct btree_cursor *root_cursor = root->cursor; if (!next_cursor) return 0; assert(next_cursor[level].node->num_keys > BTREE_KEY_MIN); #ifdef btree_stats root->stats.balance_next += 1; #endif /* * move some nodes from the next node into the current node. * as the shift operation is a left shift and is relative to * the root cursor, make the root cursor the next cursor and * pass in the root cursor as the prev cursor. */ root->cursor = next_cursor; if (!btree_shift_to_prev(root, level, root_cursor, (next_cursor[level].node->num_keys + 1 - BTREE_KEY_MIN) / 2)) abort(); root->cursor = root_cursor; return 1; } static void btree_delete_key( struct btree_root *root, int level); /* * btree_delete_node: * * Return 0 if it's done or 1 if the next level needs to be collapsed */ static void btree_delete_node( struct btree_root *root, int level) { struct btree_cursor prev_cursor[root->height]; struct btree_cursor next_cursor[root->height]; struct btree_cursor *pc; struct btree_cursor *nc; /* * the node has underflowed, grab or merge keys/items from a * neighbouring node. */ if (level == root->height - 1) { if (level > 0 && root->root_node->num_keys == 0) btree_decrease_height(root); return; } pc = btree_copy_cursor_prev(root, prev_cursor, level + 1); if (!btree_merge_with_prev(root, level, pc)) { nc = btree_copy_cursor_next(root, next_cursor, level + 1); if (!btree_merge_with_next(root, level, nc)) { /* merging failed, try redistrubution */ if (!btree_balance_with_prev(root, level, pc) && !btree_balance_with_next(root, level, nc)) abort(); return; /* when balancing, then the node isn't freed */ } } #ifdef BTREE_STATS root->stats.alloced -= 1; #endif btree_node_free(root->cursor[level].node); btree_delete_key(root, level + 1); } static void btree_delete_key( struct btree_root *root, int level) { struct btree_node *node = root->cursor[level].node; int index = root->cursor[level].index; node->num_keys--; if (index <= node->num_keys) { /* * if not deleting the last item, shift higher items down * to cover the item being deleted */ while (index < node->num_keys) { node->keys[index] = node->keys[index + 1]; node->ptrs[index] = node->ptrs[index + 1]; index++; } node->ptrs[index] = node->ptrs[index + 1]; } else { /* * else update the associated parent key as the last key * in the leaf has changed */ btree_update_node_key(root, root->cursor, level + 1, node->keys[node->num_keys]); } /* * if node underflows, either merge with sibling or rebalance * with sibling. */ if (node->num_keys < BTREE_KEY_MIN) btree_delete_node(root, level); } void * btree_delete( struct btree_root *root, unsigned long key) { void *value; value = btree_lookup(root, key); if (!value) return NULL; #ifdef BTREE_STATS root->stats.delete += 1; root->stats.num_items -= 1; #endif btree_delete_key(root, 0); btree_invalidate_cursor(root); return value; } #ifdef BTREE_STATS void btree_print_stats( struct btree_root *root, FILE *f) { unsigned long max_items = root->stats.max_items * (root->root_node->num_keys + 1); fprintf(f, "\tnum_items = %lu, max_items = %lu (%lu%%)\n", root->stats.num_items, max_items, root->stats.num_items * 100 / max_items); fprintf(f, "\talloced = %d nodes, %lu bytes, %lu bytes per item\n", root->stats.alloced, root->stats.alloced * sizeof(struct btree_node), root->stats.alloced * sizeof(struct btree_node) / root->stats.num_items); fprintf(f, "\tlookup = %d\n", root->stats.lookup); fprintf(f, "\tfind = %d\n", root->stats.find); fprintf(f, "\tcache_hits = %d\n", root->stats.cache_hits); fprintf(f, "\tcache_misses = %d\n", root->stats.cache_misses); fprintf(f, "\tkey_update = %d\n", root->stats.key_update); fprintf(f, "\tvalue_update = %d\n", root->stats.value_update); fprintf(f, "\tinsert = %d\n", root->stats.insert); fprintf(f, "\tshift_prev = %d\n", root->stats.shift_prev); fprintf(f, "\tshift_next = %d\n", root->stats.shift_next); fprintf(f, "\tsplit = %d\n", root->stats.split); fprintf(f, "\tinc_height = %d\n", root->stats.inc_height); fprintf(f, "\tdelete = %d\n", root->stats.delete); fprintf(f, "\tmerge_prev = %d\n", root->stats.merge_prev); fprintf(f, "\tmerge_next = %d\n", root->stats.merge_next); fprintf(f, "\tbalance_prev = %d\n", root->stats.balance_prev); fprintf(f, "\tbalance_next = %d\n", root->stats.balance_next); fprintf(f, "\tdec_height = %d\n", root->stats.dec_height); } #endif xfsprogs-4.9.0+nmu1ubuntu2/repair/btree.h0000644000000000000000000000354013063067172015231 0ustar /* * Copyright (c) 2007 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _BTREE_H #define _BTREE_H struct btree_root; void btree_init( struct btree_root **root); void btree_destroy( struct btree_root *root); int btree_is_empty( struct btree_root *root); void * btree_lookup( struct btree_root *root, unsigned long key); void * btree_find( struct btree_root *root, unsigned long key, unsigned long *actual_key); void * btree_peek_prev( struct btree_root *root, unsigned long *key); void * btree_peek_next( struct btree_root *root, unsigned long *key); void * btree_lookup_next( struct btree_root *root, unsigned long *key); void * btree_lookup_prev( struct btree_root *root, unsigned long *key); int btree_insert( struct btree_root *root, unsigned long key, void *value); void * btree_delete( struct btree_root *root, unsigned long key); int btree_update_key( struct btree_root *root, unsigned long old_key, unsigned long new_key); int btree_update_value( struct btree_root *root, unsigned long key, void *new_value); void btree_clear( struct btree_root *root); #ifdef BTREE_STATS void btree_print_stats( struct btree_root *root, FILE *f); #endif #endif /* _BTREE_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/da_util.c0000644000000000000000000004551213063067173015552 0ustar /* * Copyright (c) 2015 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. */ /* Various utilities for repair of directory and attribute metadata */ #include "libxfs.h" #include "globals.h" #include "err_protos.h" #include "bmap.h" #include "da_util.h" /* * takes a name and length (name need not be null-terminated) * and returns 1 if the name contains a '/' or a \0, returns 0 * otherwise */ int namecheck(char *name, int length) { char *c; int i; ASSERT(length < MAXNAMELEN); for (c = name, i = 0; i < length; i++, c++) { if (*c == '/' || *c == '\0') return 1; } return 0; } /* * the cursor gets passed up and down the da btree processing * routines. The interior block processing routines use the * cursor to determine if the pointers to and from the preceding * and succeeding sibling blocks are ok and whether the values in * the current block are consistent with the entries in the parent * nodes. When a block is traversed, a parent-verification routine * is called to verify if the next logical entry in the next level up * is consistent with the greatest hashval in the next block of the * current level. The verification routine is itself recursive and * calls itself if it has to traverse an interior block to get * the next logical entry. The routine recurses upwards through * the tree until it finds a block where it can simply step to * the next entry. The hashval in that entry should be equal to * the hashval being passed to it (the greatest hashval in the block * that the entry points to). If that isn't true, then the tree * is blown and we need to trash it, salvage and trash it, or fix it. * Currently, we just trash it. */ /* * Multibuffer handling. * V2 directory blocks can be noncontiguous, needing multiple buffers. * attr blocks are single blocks; this code handles that as well. */ struct xfs_buf * da_read_buf( xfs_mount_t *mp, int nex, bmap_ext_t *bmp, const struct xfs_buf_ops *ops) { #define MAP_ARRAY_SZ 4 struct xfs_buf_map map_array[MAP_ARRAY_SZ]; struct xfs_buf_map *map; struct xfs_buf *bp; int i; if (nex > MAP_ARRAY_SZ) { map = calloc(nex, sizeof(*map)); if (map == NULL) { do_error(_("couldn't malloc dir2 buffer list\n")); exit(1); } } else { /* common case avoids calloc/free */ map = map_array; } for (i = 0; i < nex; i++) { map[i].bm_bn = XFS_FSB_TO_DADDR(mp, bmp[i].startblock); map[i].bm_len = XFS_FSB_TO_BB(mp, bmp[i].blockcount); } bp = libxfs_readbuf_map(mp->m_dev, map, nex, 0, ops); if (map != map_array) free(map); return bp; } #define FORKNAME(type) (type == XFS_DATA_FORK ? _("directory") : _("attribute")) /* * walk tree from root to the left-most leaf block reading in * blocks and setting up cursor. passes back file block number of the * left-most leaf block if successful (bno). returns 1 if successful, * 0 if unsuccessful. */ int traverse_int_dablock( xfs_mount_t *mp, da_bt_cursor_t *da_cursor, xfs_dablk_t *rbno, int whichfork) { bmap_ext_t *bmp; xfs_dablk_t bno; struct xfs_buf *bp; int i; int nex; xfs_da_intnode_t *node; bmap_ext_t lbmp; struct xfs_da_geometry *geo; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; if (whichfork == XFS_DATA_FORK) { geo = mp->m_dir_geo; bno = geo->leafblk; } else { geo = mp->m_attr_geo; bno = 0; } /* * traverse down left-side of tree until we hit the * left-most leaf block setting up the btree cursor along * the way. */ i = -1; node = NULL; da_cursor->active = 0; do { /* * read in each block along the way and set up cursor */ nex = blkmap_getn(da_cursor->blkmap, bno, geo->fsbcount, &bmp, &lbmp); if (nex == 0) goto error_out; bp = da_read_buf(mp, nex, bmp, &xfs_da3_node_buf_ops); if (bmp != &lbmp) free(bmp); if (!bp) { do_warn( _("can't read %s block %u for inode %" PRIu64 "\n"), FORKNAME(whichfork), bno, da_cursor->ino); goto error_out; } node = bp->b_addr; M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node); if (whichfork == XFS_DATA_FORK && (nodehdr.magic == XFS_DIR2_LEAFN_MAGIC || nodehdr.magic == XFS_DIR3_LEAFN_MAGIC)) { if (i != -1) { do_warn( _("found non-root LEAFN node in inode %" PRIu64 " bno = %u\n"), da_cursor->ino, bno); } *rbno = 0; libxfs_putbuf(bp); return 1; } if (nodehdr.magic != XFS_DA_NODE_MAGIC && nodehdr.magic != XFS_DA3_NODE_MAGIC) { do_warn( _("bad %s magic number 0x%x in inode %" PRIu64 " bno = %u\n"), FORKNAME(whichfork), nodehdr.magic, da_cursor->ino, bno); libxfs_putbuf(bp); goto error_out; } /* corrupt node; rebuild the dir. */ if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) { libxfs_putbuf(bp); do_warn( _("corrupt %s tree block %u for inode %" PRIu64 "\n"), FORKNAME(whichfork), bno, da_cursor->ino); goto error_out; } btree = M_DIROPS(mp)->node_tree_p(node); if (nodehdr.count > geo->node_ents) { do_warn( _("bad %s record count in inode %" PRIu64 ", count = %d, max = %d\n"), FORKNAME(whichfork), da_cursor->ino, nodehdr.count, geo->node_ents); libxfs_putbuf(bp); goto error_out; } /* * maintain level counter */ if (i == -1) { i = da_cursor->active = nodehdr.level; if (i < 1 || i >= XFS_DA_NODE_MAXDEPTH) { do_warn( _("bad header depth for directory inode %" PRIu64 "\n"), da_cursor->ino); libxfs_putbuf(bp); i = -1; goto error_out; } } else { if (nodehdr.level == i - 1) { i--; } else { do_warn( _("bad %s btree for inode %" PRIu64 "\n"), FORKNAME(whichfork), da_cursor->ino); libxfs_putbuf(bp); goto error_out; } } da_cursor->level[i].hashval = be32_to_cpu(btree[0].hashval); da_cursor->level[i].bp = bp; da_cursor->level[i].bno = bno; da_cursor->level[i].index = 0; /* * set up new bno for next level down */ bno = be32_to_cpu(btree[0].before); } while (node != NULL && i > 1); /* * now return block number and get out */ *rbno = da_cursor->level[0].bno = bno; return 1; error_out: while (i > 1 && i <= da_cursor->active) { libxfs_putbuf(da_cursor->level[i].bp); i++; } return 0; } /* * blow out buffer for this level and all the rest above as well * if error == 0, we are not expecting to encounter any unreleased * buffers (e.g. if we do, it's a mistake). if error == 1, we're * in an error-handling case so unreleased buffers may exist. */ static void release_da_cursor_int( xfs_mount_t *mp, da_bt_cursor_t *cursor, int prev_level, int error) { int level = prev_level + 1; if (cursor->level[level].bp != NULL) { if (!error) { do_warn(_("release_da_cursor_int got unexpected " "non-null bp, dabno = %u\n"), cursor->level[level].bno); } ASSERT(error != 0); libxfs_putbuf(cursor->level[level].bp); cursor->level[level].bp = NULL; } if (level < cursor->active) release_da_cursor_int(mp, cursor, level, error); return; } void release_da_cursor( xfs_mount_t *mp, da_bt_cursor_t *cursor, int prev_level) { release_da_cursor_int(mp, cursor, prev_level, 0); } void err_release_da_cursor( xfs_mount_t *mp, da_bt_cursor_t *cursor, int prev_level) { release_da_cursor_int(mp, cursor, prev_level, 1); } /* * make sure that all entries in all blocks along the right side of * of the tree are used and hashval's are consistent. level is the * level of the descendent block. returns 0 if good (even if it had * to be fixed up), and 1 if bad. The right edge of the tree is * technically a block boundary. This routine should be used then * instead of verify_da_path(). */ int verify_final_da_path( xfs_mount_t *mp, da_bt_cursor_t *cursor, const int p_level, int whichfork) { xfs_da_intnode_t *node; xfs_dahash_t hashval; int bad = 0; int entry; int this_level = p_level + 1; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; #ifdef XR_DIR_TRACE fprintf(stderr, "in verify_final_da_path, this_level = %d\n", this_level); #endif /* * the index should point to the next "unprocessed" entry * in the block which should be the final (rightmost) entry */ entry = cursor->level[this_level].index; node = cursor->level[this_level].bp->b_addr; btree = M_DIROPS(mp)->node_tree_p(node); M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node); /* * check internal block consistency on this level -- ensure * that all entries are used, encountered and expected hashvals * match, etc. */ if (entry != nodehdr.count - 1) { do_warn( _("%s block used/count inconsistency - %d/%hu\n"), FORKNAME(whichfork), entry, nodehdr.count); bad++; } /* * hash values monotonically increasing ??? */ if (cursor->level[this_level].hashval >= be32_to_cpu(btree[entry].hashval)) { do_warn( _("%s block hashvalue inconsistency, expected > %u / saw %u\n"), FORKNAME(whichfork), cursor->level[this_level].hashval, be32_to_cpu(btree[entry].hashval)); bad++; } if (nodehdr.forw != 0) { do_warn( _("bad %s forward block pointer, expected 0, saw %u\n"), FORKNAME(whichfork), nodehdr.forw); bad++; } if (bad) { do_warn(_("bad %s block in inode %" PRIu64 "\n"), FORKNAME(whichfork), cursor->ino); return 1; } /* * keep track of greatest block # -- that gets * us the length of the directory/attribute */ if (cursor->level[this_level].bno > cursor->greatest_bno) cursor->greatest_bno = cursor->level[this_level].bno; /* * ok, now check descendant block number against this level */ if (cursor->level[p_level].bno != be32_to_cpu(btree[entry].before)) { #ifdef XR_DIR_TRACE fprintf(stderr, "bad %s btree pointer, child bno should " "be %d, block bno is %d, hashval is %u\n", FORKNAME(whichfork), be16_to_cpu(btree[entry].before), cursor->level[p_level].bno, cursor->level[p_level].hashval); fprintf(stderr, "verify_final_da_path returns 1 (bad) #1a\n"); #endif return 1; } if (cursor->level[p_level].hashval != be32_to_cpu(btree[entry].hashval)) { if (!no_modify) { do_warn( _("correcting bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %" PRIu64 ".\n"), FORKNAME(whichfork), this_level, cursor->ino); btree[entry].hashval = cpu_to_be32( cursor->level[p_level].hashval); cursor->level[this_level].dirty++; } else { do_warn( _("would correct bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %" PRIu64 ".\n"), FORKNAME(whichfork), this_level, cursor->ino); } } /* * Note: squirrel hashval away _before_ releasing the * buffer, preventing a use-after-free problem. */ hashval = be32_to_cpu(btree[entry].hashval); /* * release/write buffer */ ASSERT(cursor->level[this_level].dirty == 0 || (cursor->level[this_level].dirty && !no_modify)); if (cursor->level[this_level].dirty && !no_modify) libxfs_writebuf(cursor->level[this_level].bp, 0); else libxfs_putbuf(cursor->level[this_level].bp); cursor->level[this_level].bp = NULL; /* * bail out if this is the root block (top of tree) */ if (this_level >= cursor->active) { #ifdef XR_DIR_TRACE fprintf(stderr, "verify_final_da_path returns 0 (ok)\n"); #endif return 0; } /* * set hashvalue to correctly reflect the now-validated * last entry in this block and continue upwards validation */ cursor->level[this_level].hashval = hashval; return verify_final_da_path(mp, cursor, this_level, whichfork); } /* * Verifies the path from a descendant block up to the root. * Should be called when the descendant level traversal hits * a block boundary before crossing the boundary (reading in a new * block). * * the directory/attr btrees work differently to the other fs btrees. * each interior block contains records that are * pairs. The bno is a file bno, not a filesystem bno. The last * hashvalue in the block will be . BUT unlike * the freespace btrees, the *last* value in each block gets * propagated up the tree instead of the first value in each block. * that is, the interior records point to child blocks and the *greatest* * hash value contained by the child block is the one the block above * uses as the key for the child block. * * level is the level of the descendent block. returns 0 if good, * and 1 if bad. The descendant block may be a leaf block. * * the invariant here is that the values in the cursor for the * levels beneath this level (this_level) and the cursor index * for this level *must* be valid. * * that is, the hashval/bno info is accurate for all * DESCENDANTS and match what the node[index] information * for the current index in the cursor for this level. * * the index values in the cursor for the descendant level * are allowed to be off by one as they will reflect the * next entry at those levels to be processed. * * the hashvalue for the current level can't be set until * we hit the last entry in the block so, it's garbage * until set by this routine. * * bno and bp for the current block/level are always valid * since they have to be set so we can get a buffer for the * block. */ int verify_da_path( xfs_mount_t *mp, da_bt_cursor_t *cursor, const int p_level, int whichfork) { xfs_da_intnode_t *node; xfs_da_intnode_t *newnode; xfs_dablk_t dabno; struct xfs_buf *bp; int bad; int entry; int this_level = p_level + 1; bmap_ext_t *bmp; int nex; bmap_ext_t lbmp; struct xfs_da_geometry *geo; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; if (whichfork == XFS_DATA_FORK) geo = mp->m_dir_geo; else geo = mp->m_attr_geo; /* * index is currently set to point to the entry that * should be processed now in this level. */ entry = cursor->level[this_level].index; node = cursor->level[this_level].bp->b_addr; btree = M_DIROPS(mp)->node_tree_p(node); M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node); /* * if this block is out of entries, validate this * block and move on to the next block. * and update cursor value for said level */ if (entry >= nodehdr.count) { /* * update the hash value for this level before * validating it. bno value should be ok since * it was set when the block was first read in. */ cursor->level[this_level].hashval = be32_to_cpu(btree[entry - 1].hashval); /* * keep track of greatest block # -- that gets * us the length of the directory */ if (cursor->level[this_level].bno > cursor->greatest_bno) cursor->greatest_bno = cursor->level[this_level].bno; /* * validate the path for the current used-up block * before we trash it */ if (verify_da_path(mp, cursor, this_level, whichfork)) return 1; /* * ok, now get the next buffer and check sibling pointers */ dabno = nodehdr.forw; ASSERT(dabno != 0); nex = blkmap_getn(cursor->blkmap, dabno, geo->fsbcount, &bmp, &lbmp); if (nex == 0) { do_warn( _("can't get map info for %s block %u of inode %" PRIu64 "\n"), FORKNAME(whichfork), dabno, cursor->ino); return 1; } bp = da_read_buf(mp, nex, bmp, &xfs_da3_node_buf_ops); if (bmp != &lbmp) free(bmp); if (!bp) { do_warn( _("can't read %s block %u for inode %" PRIu64 "\n"), FORKNAME(whichfork), dabno, cursor->ino); return 1; } newnode = bp->b_addr; btree = M_DIROPS(mp)->node_tree_p(newnode); M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, newnode); /* * verify magic number and back pointer, sanity-check * entry count, verify level */ bad = 0; if (nodehdr.magic != XFS_DA_NODE_MAGIC && nodehdr.magic != XFS_DA3_NODE_MAGIC) { do_warn( _("bad magic number %x in %s block %u for inode %" PRIu64 "\n"), nodehdr.magic, FORKNAME(whichfork), dabno, cursor->ino); bad++; } if (nodehdr.back != cursor->level[this_level].bno) { do_warn( _("bad back pointer in %s block %u for inode %" PRIu64 "\n"), FORKNAME(whichfork), dabno, cursor->ino); bad++; } if (nodehdr.count > geo->node_ents) { do_warn( _("entry count %d too large in %s block %u for inode %" PRIu64 "\n"), nodehdr.count, FORKNAME(whichfork), dabno, cursor->ino); bad++; } if (nodehdr.level != this_level) { do_warn( _("bad level %d in %s block %u for inode %" PRIu64 "\n"), nodehdr.level, FORKNAME(whichfork), dabno, cursor->ino); bad++; } if (bad) { #ifdef XR_DIR_TRACE fprintf(stderr, "verify_da_path returns 1 (bad) #4\n"); #endif libxfs_putbuf(bp); return 1; } /* * update cursor, write out the *current* level if * required. don't write out the descendant level */ ASSERT(cursor->level[this_level].dirty == 0 || (cursor->level[this_level].dirty && !no_modify)); /* * If block looks ok but CRC didn't match, make sure to * recompute it. */ if (!no_modify && cursor->level[this_level].bp->b_error == -EFSBADCRC) cursor->level[this_level].dirty = 1; if (cursor->level[this_level].dirty && !no_modify) libxfs_writebuf(cursor->level[this_level].bp, 0); else libxfs_putbuf(cursor->level[this_level].bp); /* switch cursor to point at the new buffer we just read */ cursor->level[this_level].bp = bp; cursor->level[this_level].dirty = 0; cursor->level[this_level].bno = dabno; cursor->level[this_level].hashval = be32_to_cpu(btree[0].hashval); entry = cursor->level[this_level].index = 0; } /* * ditto for block numbers */ if (cursor->level[p_level].bno != be32_to_cpu(btree[entry].before)) { #ifdef XR_DIR_TRACE fprintf(stderr, "bad %s btree pointer, child bno " "should be %d, block bno is %d, hashval is %u\n", FORKNAME(whichfork), be32_to_cpu(btree[entry].before), cursor->level[p_level].bno, cursor->level[p_level].hashval); fprintf(stderr, "verify_da_path returns 1 (bad) #1a\n"); #endif return 1; } /* * ok, now validate last hashvalue in the descendant * block against the hashval in the current entry */ if (cursor->level[p_level].hashval != be32_to_cpu(btree[entry].hashval)) { if (!no_modify) { do_warn( _("correcting bad hashval in interior %s block\n" "\tin (level %d) in inode %" PRIu64 ".\n"), FORKNAME(whichfork), this_level, cursor->ino); btree[entry].hashval = cpu_to_be32( cursor->level[p_level].hashval); cursor->level[this_level].dirty++; } else { do_warn( _("would correct bad hashval in interior %s block\n" "\tin (level %d) in inode %" PRIu64 ".\n"), FORKNAME(whichfork), this_level, cursor->ino); } } /* * increment index for this level to point to next entry * (which should point to the next descendant block) */ cursor->level[this_level].index++; #ifdef XR_DIR_TRACE fprintf(stderr, "verify_da_path returns 0 (ok)\n"); #endif return 0; } xfsprogs-4.9.0+nmu1ubuntu2/repair/da_util.h0000644000000000000000000000361213063067172015551 0ustar /* * Copyright (c) 2015 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XR_DA_UTIL_H #define _XR_DA_UTIL_H struct da_level_state { xfs_buf_t *bp; /* block bp */ xfs_dablk_t bno; /* file block number */ xfs_dahash_t hashval; /* last verified hashval */ int index; /* current index in block */ int dirty; /* is buffer dirty ? (1 == yes) */ }; typedef struct da_bt_cursor { int active; /* highest level in tree (# levels-1) */ xfs_ino_t ino; xfs_dablk_t greatest_bno; xfs_dinode_t *dip; struct da_level_state level[XFS_DA_NODE_MAXDEPTH]; struct blkmap *blkmap; } da_bt_cursor_t; int namecheck( char *name, int length); struct xfs_buf * da_read_buf( xfs_mount_t *mp, int nex, bmap_ext_t *bmp, const struct xfs_buf_ops *ops); void release_da_cursor( xfs_mount_t *mp, da_bt_cursor_t *cursor, int prev_level); void err_release_da_cursor( xfs_mount_t *mp, da_bt_cursor_t *cursor, int prev_level); int traverse_int_dablock( xfs_mount_t *mp, da_bt_cursor_t *da_cursor, xfs_dablk_t *rbno, int whichfork); int verify_da_path( xfs_mount_t *mp, da_bt_cursor_t *cursor, const int p_level, int whichfork); int verify_final_da_path( xfs_mount_t *mp, da_bt_cursor_t *cursor, const int p_level, int whichfork); #endif /* _XR_DA_UTIL_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/dino_chunks.c0000644000000000000000000010143413063067173016431 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "versions.h" #include "prefetch.h" #include "progress.h" /* * validates inode block or chunk, returns # of good inodes * the dinodes are verified using verify_uncertain_dinode() which * means only the basic inode info is checked, no fork checks. */ static int check_aginode_block(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t agbno) { xfs_dinode_t *dino_p; int i; int cnt = 0; xfs_buf_t *bp; /* * it's ok to read these possible inode blocks in one at * a time because they don't belong to known inodes (if * they did, we'd know about them courtesy of the incore inode * tree and we wouldn't be here and we stale the buffers out * so no one else will overlap them. */ bp = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1), 0, NULL); if (!bp) { do_warn(_("cannot read agbno (%u/%u), disk block %" PRId64 "\n"), agno, agbno, XFS_AGB_TO_DADDR(mp, agno, agbno)); return(0); } for (i = 0; i < mp->m_sb.sb_inopblock; i++) { dino_p = xfs_make_iptr(mp, bp, i); if (!verify_uncertain_dinode(mp, dino_p, agno, XFS_OFFBNO_TO_AGINO(mp, agbno, i))) cnt++; } if (cnt) bp->b_ops = &xfs_inode_buf_ops; libxfs_putbuf(bp); return(cnt); } /* * tries to establish if the inode really exists in a valid * inode chunk. returns number of new inodes if things are good * and 0 if bad. start is the start of the discovered inode chunk. * routine assumes that ino is a legal inode number * (verified by verify_inum()). If the inode chunk turns out * to be good, this routine will put the inode chunk into * the good inode chunk tree if required. * * the verify_(ag)inode* family of routines are utility * routines called by check_uncertain_aginodes() and * process_uncertain_aginodes(). */ static int verify_inode_chunk(xfs_mount_t *mp, xfs_ino_t ino, xfs_ino_t *start_ino) { xfs_agnumber_t agno; xfs_agino_t agino; xfs_agino_t start_agino; xfs_agblock_t agbno; xfs_agblock_t start_agbno = 0; xfs_agblock_t end_agbno; xfs_agblock_t max_agbno; xfs_agblock_t cur_agbno; xfs_agblock_t chunk_start_agbno; xfs_agblock_t chunk_stop_agbno; ino_tree_node_t *irec_before_p = NULL; ino_tree_node_t *irec_after_p = NULL; ino_tree_node_t *irec_p; ino_tree_node_t *irec_next_p; int irec_cnt; int ino_cnt = 0; int num_blks; int i; int j; int state; xfs_extlen_t blen; agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); agbno = XFS_INO_TO_AGBNO(mp, ino); *start_ino = NULLFSINO; ASSERT(mp->m_ialloc_blks > 0); if (agno == mp->m_sb.sb_agcount - 1) max_agbno = mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno; else max_agbno = mp->m_sb.sb_agblocks; /* * is the inode beyond the end of the AG? */ if (agbno >= max_agbno) return(0); /* * check for the easy case, inodes per block >= XFS_INODES_PER_CHUNK * (multiple chunks per block) */ if (mp->m_ialloc_blks == 1) { if (agbno > max_agbno) return 0; if (check_aginode_block(mp, agno, agino) == 0) return 0; pthread_mutex_lock(&ag_locks[agno].lock); state = get_bmap(agno, agbno); switch (state) { case XR_E_INO: do_warn( _("uncertain inode block %d/%d already known\n"), agno, agbno); break; case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: set_bmap(agno, agbno, XR_E_INO); break; case XR_E_MULT: case XR_E_INUSE: case XR_E_INUSE_FS: case XR_E_FS_MAP: /* * if block is already claimed, forget it. */ do_warn( _("inode block %d/%d multiply claimed, (state %d)\n"), agno, agbno, state); set_bmap(agno, agbno, XR_E_MULT); pthread_mutex_unlock(&ag_locks[agno].lock); return(0); default: do_warn( _("inode block %d/%d bad state, (state %d)\n"), agno, agbno, state); set_bmap(agno, agbno, XR_E_INO); break; } pthread_mutex_unlock(&ag_locks[agno].lock); start_agino = XFS_OFFBNO_TO_AGINO(mp, agbno, 0); *start_ino = XFS_AGINO_TO_INO(mp, agno, start_agino); /* * put new inode record(s) into inode tree */ for (j = 0; j < chunks_pblock; j++) { if ((irec_p = find_inode_rec(mp, agno, start_agino)) == NULL) { irec_p = set_inode_free_alloc(mp, agno, start_agino); for (i = 1; i < XFS_INODES_PER_CHUNK; i++) set_inode_free(irec_p, i); } if (start_agino <= agino && agino < start_agino + XFS_INODES_PER_CHUNK) set_inode_used(irec_p, agino - start_agino); start_agino += XFS_INODES_PER_CHUNK; ino_cnt += XFS_INODES_PER_CHUNK; } return(ino_cnt); } else if (fs_aligned_inodes) { /* * next easy case -- aligned inode filesystem. * just check out the chunk */ start_agbno = rounddown(XFS_INO_TO_AGBNO(mp, ino), fs_ino_alignment); end_agbno = start_agbno + mp->m_ialloc_blks; /* * if this fs has aligned inodes but the end of the * chunk is beyond the end of the ag, this is a bad * chunk */ if (end_agbno > max_agbno) return(0); /* * check out all blocks in chunk */ ino_cnt = 0; for (cur_agbno = start_agbno; cur_agbno < end_agbno; cur_agbno++) { ino_cnt += check_aginode_block(mp, agno, cur_agbno); } /* * if we lose either 2 blocks worth of inodes or >25% of * the chunk, just forget it. */ if (ino_cnt < XFS_INODES_PER_CHUNK - 2 * mp->m_sb.sb_inopblock || ino_cnt < XFS_INODES_PER_CHUNK - 16) return(0); /* * ok, put the record into the tree, if no conflict. */ if (find_uncertain_inode_rec(agno, XFS_OFFBNO_TO_AGINO(mp, start_agbno, 0))) return(0); start_agino = XFS_OFFBNO_TO_AGINO(mp, start_agbno, 0); *start_ino = XFS_AGINO_TO_INO(mp, agno, start_agino); irec_p = set_inode_free_alloc(mp, agno, XFS_OFFBNO_TO_AGINO(mp, start_agbno, 0)); for (i = 1; i < XFS_INODES_PER_CHUNK; i++) set_inode_free(irec_p, i); ASSERT(start_agino <= agino && start_agino + XFS_INODES_PER_CHUNK > agino); set_inode_used(irec_p, agino - start_agino); return(XFS_INODES_PER_CHUNK); } /* * hard case -- pre-6.3 filesystem. * set default start/end agbnos and ensure agbnos are legal. * we're setting a range [start_agbno, end_agbno) such that * a discovered inode chunk completely within that range * would include the inode passed into us. */ if (mp->m_ialloc_blks > 1) { if (agino > mp->m_ialloc_inos) start_agbno = agbno - mp->m_ialloc_blks + 1; else start_agbno = 1; } end_agbno = agbno + mp->m_ialloc_blks; if (end_agbno > max_agbno) end_agbno = max_agbno; /* * search tree for known inodes within +/- 1 inode chunk range */ irec_before_p = irec_after_p = NULL; find_inode_rec_range(mp, agno, XFS_OFFBNO_TO_AGINO(mp, start_agbno, 0), XFS_OFFBNO_TO_AGINO(mp, end_agbno, mp->m_sb.sb_inopblock - 1), &irec_before_p, &irec_after_p); /* * if we have known inode chunks in our search range, establish * their start and end-points to tighten our search range. range * is [start, end) -- e.g. max/end agbno is one beyond the * last block to be examined. the avl routines work this way. */ if (irec_before_p) { /* * only one inode record in the range, move one boundary in */ if (irec_before_p == irec_after_p) { if (irec_before_p->ino_startnum < agino) start_agbno = XFS_AGINO_TO_AGBNO(mp, irec_before_p->ino_startnum + XFS_INODES_PER_CHUNK); else end_agbno = XFS_AGINO_TO_AGBNO(mp, irec_before_p->ino_startnum); } /* * find the start of the gap in the search range (which * should contain our unknown inode). if the only irec * within +/- 1 chunks starts after the inode we're * looking for, skip this stuff since the end_agbno * of the range has already been trimmed in to not * include that irec. */ if (irec_before_p->ino_startnum < agino) { irec_p = irec_before_p; irec_next_p = next_ino_rec(irec_p); while(irec_next_p != NULL && irec_p->ino_startnum + XFS_INODES_PER_CHUNK == irec_next_p->ino_startnum) { irec_p = irec_next_p; irec_next_p = next_ino_rec(irec_next_p); } start_agbno = XFS_AGINO_TO_AGBNO(mp, irec_p->ino_startnum) + mp->m_ialloc_blks; /* * we know that the inode we're trying to verify isn't * in an inode chunk so the next ino_rec marks the end * of the gap -- is it within the search range? */ if (irec_next_p != NULL && agino + mp->m_ialloc_inos >= irec_next_p->ino_startnum) end_agbno = XFS_AGINO_TO_AGBNO(mp, irec_next_p->ino_startnum); } ASSERT(start_agbno < end_agbno); } /* * if the gap is too small to contain a chunk, we lose. * this means that inode chunks known to be good surround * the inode in question and that the space between them * is too small for a legal inode chunk */ if (end_agbno - start_agbno < mp->m_ialloc_blks) return(0); /* * now grunge around the disk, start at the inode block and * go in each direction until you hit a non-inode block or * run into a range boundary. A non-inode block is block * with *no* good inodes in it. Unfortunately, we can't * co-opt bad blocks into inode chunks (which might take * care of disk blocks that turn into zeroes) because the * filesystem could very well allocate two inode chunks * with a one block file in between and we'd zap the file. * We're better off just losing the rest of the * inode chunk instead. */ for (cur_agbno = agbno; cur_agbno >= start_agbno; cur_agbno--) { /* * if the block has no inodes, it's a bad block so * break out now without decrementing cur_agbno so * chunk start blockno will be set to the last good block */ if (!(irec_cnt = check_aginode_block(mp, agno, cur_agbno))) break; ino_cnt += irec_cnt; } chunk_start_agbno = cur_agbno + 1; for (cur_agbno = agbno + 1; cur_agbno < end_agbno; cur_agbno++) { /* * if the block has no inodes, it's a bad block so * break out now without incrementing cur_agbno so * chunk start blockno will be set to the block * immediately after the last good block. */ if (!(irec_cnt = check_aginode_block(mp, agno, cur_agbno))) break; ino_cnt += irec_cnt; } chunk_stop_agbno = cur_agbno; num_blks = chunk_stop_agbno - chunk_start_agbno; if (num_blks < mp->m_ialloc_blks || ino_cnt == 0) return 0; /* * XXX - later - if the entire range is selected and they're all * good inodes, keep searching in either direction. * until you the range of inodes end, then split into chunks * for now, just take one chunk's worth starting at the lowest * possible point and hopefully we'll pick the rest up later. * * XXX - if we were going to fix up an inode chunk for * any good inodes in the chunk, this is where we would * do it. For now, keep it simple and lose the rest of * the chunk */ if (num_blks % mp->m_ialloc_blks != 0) { num_blks = rounddown(num_blks, mp->m_ialloc_blks); chunk_stop_agbno = chunk_start_agbno + num_blks; } /* * ok, we've got a candidate inode chunk. now we have to * verify that we aren't trying to use blocks that are already * in use. If so, mark them as multiply claimed since odds * are very low that we found this chunk by stumbling across * user data -- we're probably here as a result of a directory * entry or an iunlinked pointer */ pthread_mutex_lock(&ag_locks[agno].lock); for (cur_agbno = chunk_start_agbno; cur_agbno < chunk_stop_agbno; cur_agbno += blen) { state = get_bmap_ext(agno, cur_agbno, chunk_stop_agbno, &blen); switch (state) { case XR_E_MULT: case XR_E_INUSE: case XR_E_INUSE_FS: case XR_E_FS_MAP: do_warn( _("inode block %d/%d multiply claimed, (state %d)\n"), agno, cur_agbno, state); set_bmap_ext(agno, cur_agbno, blen, XR_E_MULT); pthread_mutex_unlock(&ag_locks[agno].lock); return 0; case XR_E_INO: do_error( _("uncertain inode block overlap, agbno = %d, ino = %" PRIu64 "\n"), agbno, ino); break; default: break; } } pthread_mutex_unlock(&ag_locks[agno].lock); /* * ok, chunk is good. put the record into the tree if required, * and fill in the bitmap. All inodes will be marked as "free" * except for the one that led us to discover the chunk. That's * ok because we'll override the free setting later if the * contents of the inode indicate it's in use. */ start_agino = XFS_OFFBNO_TO_AGINO(mp, chunk_start_agbno, 0); *start_ino = XFS_AGINO_TO_INO(mp, agno, start_agino); ASSERT(find_inode_rec(mp, agno, start_agino) == NULL); irec_p = set_inode_free_alloc(mp, agno, start_agino); for (i = 1; i < XFS_INODES_PER_CHUNK; i++) set_inode_free(irec_p, i); ASSERT(start_agino <= agino && start_agino + XFS_INODES_PER_CHUNK > agino); set_inode_used(irec_p, agino - start_agino); pthread_mutex_lock(&ag_locks[agno].lock); for (cur_agbno = chunk_start_agbno; cur_agbno < chunk_stop_agbno; cur_agbno += blen) { state = get_bmap_ext(agno, cur_agbno, chunk_stop_agbno, &blen); switch (state) { case XR_E_INO: do_error( _("uncertain inode block %" PRIu64 " already known\n"), XFS_AGB_TO_FSB(mp, agno, cur_agbno)); break; case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: set_bmap_ext(agno, cur_agbno, blen, XR_E_INO); break; case XR_E_MULT: case XR_E_INUSE: case XR_E_INUSE_FS: case XR_E_FS_MAP: do_error( _("inode block %d/%d multiply claimed, (state %d)\n"), agno, cur_agbno, state); break; default: do_warn( _("inode block %d/%d bad state, (state %d)\n"), agno, cur_agbno, state); set_bmap_ext(agno, cur_agbno, blen, XR_E_INO); break; } } pthread_mutex_unlock(&ag_locks[agno].lock); return(ino_cnt); } /* * same as above only for ag inode chunks */ static int verify_aginode_chunk(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t agino, xfs_agino_t *agino_start) { xfs_ino_t ino; int res; res = verify_inode_chunk(mp, XFS_AGINO_TO_INO(mp, agno, agino), &ino); if (res) *agino_start = XFS_INO_TO_AGINO(mp, ino); else *agino_start = NULLAGINO; return(res); } /* * this does the same as the two above only it returns a pointer * to the inode record in the good inode tree */ static ino_tree_node_t * verify_aginode_chunk_irec(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t agino) { xfs_agino_t start_agino; ino_tree_node_t *irec = NULL; if (verify_aginode_chunk(mp, agno, agino, &start_agino)) irec = find_inode_rec(mp, agno, start_agino); return(irec); } /* * Set the state of an inode block during inode chunk processing. The block is * expected to be in the free or inode state. If free, it transitions to the * inode state. Warn if the block is in neither expected state as this indicates * multiply claimed blocks. */ static void process_inode_agbno_state( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno) { int state; pthread_mutex_lock(&ag_locks[agno].lock); state = get_bmap(agno, agbno); switch (state) { case XR_E_INO: /* already marked */ break; case XR_E_UNKNOWN: case XR_E_FREE: case XR_E_FREE1: set_bmap(agno, agbno, XR_E_INO); break; case XR_E_BAD_STATE: do_error(_("bad state in block map %d\n"), state); break; default: set_bmap(agno, agbno, XR_E_MULT); do_warn( _("inode block %" PRIu64 " multiply claimed, state was %d\n"), XFS_AGB_TO_FSB(mp, agno, agbno), state); break; } pthread_mutex_unlock(&ag_locks[agno].lock); } /* * processes an inode allocation chunk/block, returns 1 on I/O errors, * 0 otherwise * * *bogus is set to 1 if the entire set of inodes is bad. */ static int process_inode_chunk( xfs_mount_t *mp, xfs_agnumber_t agno, int num_inos, ino_tree_node_t *first_irec, int ino_discovery, int check_dups, int extra_attr_check, int *bogus) { xfs_ino_t parent; ino_tree_node_t *ino_rec; xfs_buf_t **bplist; xfs_dinode_t *dino; int icnt; int status; int is_used; int ino_dirty; int irec_offset; int ibuf_offset; xfs_agino_t agino; xfs_agblock_t agbno; xfs_ino_t ino; int dirty = 0; int isa_dir = 0; int blks_per_cluster; int cluster_count; int bp_index; int cluster_offset; ASSERT(first_irec != NULL); ASSERT(XFS_AGINO_TO_OFFSET(mp, first_irec->ino_startnum) == 0); *bogus = 0; ASSERT(mp->m_ialloc_blks > 0); blks_per_cluster = mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog; if (blks_per_cluster == 0) blks_per_cluster = 1; cluster_count = XFS_INODES_PER_CHUNK / inodes_per_cluster; if (cluster_count == 0) cluster_count = 1; /* * get all blocks required to read in this chunk (may wind up * having to process more chunks in a multi-chunk per block fs) */ agbno = XFS_AGINO_TO_AGBNO(mp, first_irec->ino_startnum); /* * set up first irec */ ino_rec = first_irec; irec_offset = 0; bplist = malloc(cluster_count * sizeof(xfs_buf_t *)); if (bplist == NULL) do_error(_("failed to allocate %zd bytes of memory\n"), cluster_count * sizeof(xfs_buf_t *)); for (bp_index = 0; bp_index < cluster_count; bp_index++) { /* * Skip the cluster buffer if the first inode is sparse. The * remaining inodes in the cluster share the same state as * sparse inodes occur at cluster granularity. */ if (is_inode_sparse(ino_rec, irec_offset)) { pftrace("skip sparse inode, startnum 0x%x idx %d", ino_rec->ino_startnum, irec_offset); bplist[bp_index] = NULL; goto next_readbuf; } pftrace("about to read off %llu in AG %d", XFS_AGB_TO_DADDR(mp, agno, agbno), agno); bplist[bp_index] = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, blks_per_cluster), 0, &xfs_inode_buf_ops); if (!bplist[bp_index]) { do_warn(_("cannot read inode %" PRIu64 ", disk block %" PRId64 ", cnt %d\n"), XFS_AGINO_TO_INO(mp, agno, first_irec->ino_startnum), XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, blks_per_cluster)); while (bp_index > 0) { bp_index--; libxfs_putbuf(bplist[bp_index]); } free(bplist); return(1); } pftrace("readbuf %p (%llu, %d) in AG %d", bplist[bp_index], (long long)XFS_BUF_ADDR(bplist[bp_index]), XFS_BUF_COUNT(bplist[bp_index]), agno); bplist[bp_index]->b_ops = &xfs_inode_buf_ops; next_readbuf: irec_offset += mp->m_sb.sb_inopblock * blks_per_cluster; agbno += blks_per_cluster; } agbno = XFS_AGINO_TO_AGBNO(mp, first_irec->ino_startnum); /* * initialize counters */ irec_offset = 0; ibuf_offset = 0; cluster_offset = 0; icnt = 0; status = 0; bp_index = 0; /* * verify inode chunk if necessary */ if (ino_discovery) { for (;;) { agino = irec_offset + ino_rec->ino_startnum; /* no buffers for sparse clusters */ if (bplist[bp_index]) { /* make inode pointer */ dino = xfs_make_iptr(mp, bplist[bp_index], cluster_offset); /* * we always think that the root and realtime * inodes are verified even though we may have * to reset them later to keep from losing the * chunk that they're in */ if (verify_dinode(mp, dino, agno, agino) == 0 || (agno == 0 && (mp->m_sb.sb_rootino == agino || mp->m_sb.sb_rsumino == agino || mp->m_sb.sb_rbmino == agino))) status++; } irec_offset++; icnt++; cluster_offset++; if (icnt == mp->m_ialloc_inos && irec_offset == XFS_INODES_PER_CHUNK) { /* * done! - finished up irec and block * simultaneously */ break; } else if (irec_offset == XFS_INODES_PER_CHUNK) { /* * get new irec (multiple chunks per block fs) */ ino_rec = next_ino_rec(ino_rec); ASSERT(ino_rec->ino_startnum == agino + 1); irec_offset = 0; } if (cluster_offset == inodes_per_cluster) { bp_index++; cluster_offset = 0; } } /* * if chunk/block is bad, blow it off. the inode records * will be deleted by the caller if appropriate. */ if (!status) { *bogus = 1; for (bp_index = 0; bp_index < cluster_count; bp_index++) if (bplist[bp_index]) libxfs_putbuf(bplist[bp_index]); free(bplist); return(0); } /* * reset irec and counters */ ino_rec = first_irec; irec_offset = 0; cluster_offset = 0; bp_index = 0; icnt = 0; status = 0; } /* * mark block as an inode block in the incore bitmap */ if (!is_inode_sparse(ino_rec, irec_offset)) process_inode_agbno_state(mp, agno, agbno); for (;;) { agino = irec_offset + ino_rec->ino_startnum; ino = XFS_AGINO_TO_INO(mp, agno, agino); if (is_inode_sparse(ino_rec, irec_offset)) goto process_next; /* make inode pointer */ dino = xfs_make_iptr(mp, bplist[bp_index], cluster_offset); is_used = 3; ino_dirty = 0; parent = 0; status = process_dinode(mp, dino, agno, agino, is_inode_free(ino_rec, irec_offset), &ino_dirty, &is_used,ino_discovery, check_dups, extra_attr_check, &isa_dir, &parent); ASSERT(is_used != 3); if (ino_dirty) { dirty = 1; libxfs_dinode_calc_crc(mp, dino); } /* * XXX - if we want to try and keep * track of whether we need to bang on * the inode maps (instead of just * blindly reconstructing them like * we do now, this is where to start. */ if (is_used) { __uint16_t di_mode; if (is_inode_free(ino_rec, irec_offset)) { if (verbose || no_modify) { do_warn( _("imap claims in-use inode %" PRIu64 " is free, "), ino); } if (verbose || !no_modify) do_warn(_("correcting imap\n")); else do_warn(_("would correct imap\n")); } set_inode_used(ino_rec, irec_offset); /* * store the on-disk file type for comparing in * phase 6. */ di_mode = be16_to_cpu(dino->di_mode); di_mode = (di_mode & S_IFMT) >> S_SHIFT; set_inode_ftype(ino_rec, irec_offset, xfs_mode_to_ftype[di_mode]); /* * store on-disk nlink count for comparing in phase 7 */ set_inode_disk_nlinks(ino_rec, irec_offset, dino->di_version > 1 ? be32_to_cpu(dino->di_nlink) : be16_to_cpu(dino->di_onlink)); } else { set_inode_free(ino_rec, irec_offset); } /* * if we lose the root inode, or it turns into * a non-directory, that allows us to double-check * later whether or not we need to reinitialize it. */ if (isa_dir) { set_inode_isadir(ino_rec, irec_offset); /* * we always set the parent but * we may as well wait until * phase 4 (no inode discovery) * because the parent info will * be solid then. */ if (!ino_discovery) { ASSERT(parent != 0); set_inode_parent(ino_rec, irec_offset, parent); ASSERT(parent == get_inode_parent(ino_rec, irec_offset)); } } else { clear_inode_isadir(ino_rec, irec_offset); } if (status) { if (mp->m_sb.sb_rootino == ino) { need_root_inode = 1; if (!no_modify) { do_warn( _("cleared root inode %" PRIu64 "\n"), ino); } else { do_warn( _("would clear root inode %" PRIu64 "\n"), ino); } } else if (mp->m_sb.sb_rbmino == ino) { need_rbmino = 1; if (!no_modify) { do_warn( _("cleared realtime bitmap inode %" PRIu64 "\n"), ino); } else { do_warn( _("would clear realtime bitmap inode %" PRIu64 "\n"), ino); } } else if (mp->m_sb.sb_rsumino == ino) { need_rsumino = 1; if (!no_modify) { do_warn( _("cleared realtime summary inode %" PRIu64 "\n"), ino); } else { do_warn( _("would clear realtime summary inode %" PRIu64 "\n"), ino); } } else if (!no_modify) { do_warn(_("cleared inode %" PRIu64 "\n"), ino); } else { do_warn(_("would have cleared inode %" PRIu64 "\n"), ino); } clear_inode_was_rl(ino_rec, irec_offset); } process_next: irec_offset++; ibuf_offset++; icnt++; cluster_offset++; if (icnt == mp->m_ialloc_inos && irec_offset == XFS_INODES_PER_CHUNK) { /* * done! - finished up irec and block simultaneously */ for (bp_index = 0; bp_index < cluster_count; bp_index++) { if (!bplist[bp_index]) continue; pftrace("put/writebuf %p (%llu) in AG %d", bplist[bp_index], (long long) XFS_BUF_ADDR(bplist[bp_index]), agno); if (dirty && !no_modify) libxfs_writebuf(bplist[bp_index], 0); else libxfs_putbuf(bplist[bp_index]); } free(bplist); break; } else if (ibuf_offset == mp->m_sb.sb_inopblock) { /* * mark block as an inode block in the incore bitmap * and reset inode buffer offset counter */ ibuf_offset = 0; agbno++; if (!is_inode_sparse(ino_rec, irec_offset)) process_inode_agbno_state(mp, agno, agbno); } else if (irec_offset == XFS_INODES_PER_CHUNK) { /* * get new irec (multiple chunks per block fs) */ ino_rec = next_ino_rec(ino_rec); ASSERT(ino_rec->ino_startnum == agino + 1); irec_offset = 0; } if (cluster_offset == inodes_per_cluster) { bp_index++; cluster_offset = 0; } } return(0); } /* * check all inodes mentioned in the ag's incore inode maps. * the map may be incomplete. If so, we'll catch the missing * inodes (hopefully) when we traverse the directory tree. * check_dirs is set to 1 if directory inodes should be * processed for internal consistency, parent setting and * discovery of unknown inodes. this only happens * in phase 3. check_dups is set to 1 if we're looking for * inodes that reference duplicate blocks so we can trash * the inode right then and there. this is set only in * phase 4 after we've run through and set the bitmap once. */ void process_aginodes( xfs_mount_t *mp, prefetch_args_t *pf_args, xfs_agnumber_t agno, int ino_discovery, int check_dups, int extra_attr_check) { int num_inos, bogus; ino_tree_node_t *ino_rec, *first_ino_rec, *prev_ino_rec; #ifdef XR_PF_TRACE int count; #endif first_ino_rec = ino_rec = findfirst_inode_rec(agno); while (ino_rec != NULL) { /* * paranoia - step through inode records until we step * through a full allocation of inodes. this could * be an issue in big-block filesystems where a block * can hold more than one inode chunk. make sure to * grab the record corresponding to the beginning of * the next block before we call the processing routines. */ num_inos = XFS_INODES_PER_CHUNK; while (num_inos < mp->m_ialloc_inos && ino_rec != NULL) { /* * inodes chunks will always be aligned and sized * correctly */ if ((ino_rec = next_ino_rec(ino_rec)) != NULL) num_inos += XFS_INODES_PER_CHUNK; } ASSERT(num_inos == mp->m_ialloc_inos); if (pf_args) { sem_post(&pf_args->ra_count); #ifdef XR_PF_TRACE sem_getvalue(&pf_args->ra_count, &count); pftrace("processing inode chunk %p in AG %d (sem count = %d)", first_ino_rec, agno, count); #endif } if (process_inode_chunk(mp, agno, num_inos, first_ino_rec, ino_discovery, check_dups, extra_attr_check, &bogus)) { /* XXX - i/o error, we've got a problem */ abort(); } if (!bogus) first_ino_rec = ino_rec = next_ino_rec(ino_rec); else { /* * inodes pointed to by this record are * completely bogus, blow the records for * this chunk out. * the inode block(s) will get reclaimed * in phase 4 when the block map is * reconstructed after inodes claiming * duplicate blocks are deleted. */ num_inos = 0; ino_rec = first_ino_rec; while (num_inos < mp->m_ialloc_inos && ino_rec != NULL) { prev_ino_rec = ino_rec; if ((ino_rec = next_ino_rec(ino_rec)) != NULL) num_inos += XFS_INODES_PER_CHUNK; get_inode_rec(mp, agno, prev_ino_rec); free_inode_rec(agno, prev_ino_rec); } first_ino_rec = ino_rec; } PROG_RPT_INC(prog_rpt_done[agno], num_inos); } } /* * verify the uncertain inode list for an ag. * Good inodes get moved into the good inode tree. * returns 0 if there are no uncertain inode records to * be processed, 1 otherwise. This routine destroys the * the entire uncertain inode tree for the ag as a side-effect. */ void check_uncertain_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno) { ino_tree_node_t *irec; ino_tree_node_t *nrec; xfs_agino_t start; xfs_agino_t i; xfs_agino_t agino; int got_some; nrec = NULL; got_some = 0; clear_uncertain_ino_cache(agno); if ((irec = findfirst_uncertain_inode_rec(agno)) == NULL) return; /* * the trick here is to find a contiguous range * of inodes, make sure that it doesn't overlap * with a known to exist chunk, and then make * sure it is a number of entire chunks. * we check on-disk once we have an idea of what's * going on just to double-check. * * process the uncertain inode record list and look * on disk to see if the referenced inodes are good */ do_warn(_("found inodes not in the inode allocation tree\n")); do { /* * check every confirmed (which in this case means * inode that we really suspect to be an inode) inode */ for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { if (!is_inode_confirmed(irec, i)) continue; agino = i + irec->ino_startnum; if (verify_aginum(mp, agno, agino)) continue; if (nrec != NULL && nrec->ino_startnum <= agino && agino < nrec->ino_startnum + XFS_INODES_PER_CHUNK) continue; if ((nrec = find_inode_rec(mp, agno, agino)) == NULL) if (!verify_aginum(mp, agno, agino)) if (verify_aginode_chunk(mp, agno, agino, &start)) got_some = 1; } get_uncertain_inode_rec(mp, agno, irec); free_inode_rec(agno, irec); irec = findfirst_uncertain_inode_rec(agno); } while (irec != NULL); if (got_some) do_warn(_("found inodes not in the inode allocation tree\n")); return; } /* * verify and process the uncertain inodes for an ag. * this is different from check_ in that we can't just * move the good inodes into the good inode tree and let * process_aginodes() deal with them because this gets called * after process_aginodes() has been run on the ag inode tree. * So we have to process the inodes as well as verify since * we don't want to rerun process_aginodes() on a tree that has * mostly been processed. * * Note that if this routine does process some inodes, it can * add uncertain inodes to any ag which would require that * the routine be called again to process those newly-added * uncertain inodes. * * returns 0 if no inodes were processed and 1 if inodes * were processed (and it is possible that new uncertain * inodes were discovered). * * as a side-effect, this routine tears down the uncertain * inode tree for the ag. */ int process_uncertain_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno) { ino_tree_node_t *irec; ino_tree_node_t *nrec; xfs_agino_t agino; int i; int bogus; int cnt; int got_some; #ifdef XR_INODE_TRACE fprintf(stderr, "in process_uncertain_aginodes, agno = %d\n", agno); #endif got_some = 0; clear_uncertain_ino_cache(agno); if ((irec = findfirst_uncertain_inode_rec(agno)) == NULL) return(0); nrec = NULL; do { /* * check every confirmed inode */ for (cnt = i = 0; i < XFS_INODES_PER_CHUNK; i++) { if (!is_inode_confirmed(irec, i)) continue; cnt++; agino = i + irec->ino_startnum; #ifdef XR_INODE_TRACE fprintf(stderr, "ag inode = %d (0x%x)\n", agino, agino); #endif /* * skip over inodes already processed (in the * good tree), bad inode numbers, and inode numbers * pointing to bogus inodes */ if (verify_aginum(mp, agno, agino)) continue; if (nrec != NULL && nrec->ino_startnum <= agino && agino < nrec->ino_startnum + XFS_INODES_PER_CHUNK) continue; if ((nrec = find_inode_rec(mp, agno, agino)) != NULL) continue; /* * verify the chunk. if good, it will be * added to the good inode tree. */ if ((nrec = verify_aginode_chunk_irec(mp, agno, agino)) == NULL) continue; got_some = 1; /* * process the inode record we just added * to the good inode tree. The inode * processing may add more records to the * uncertain inode lists. */ if (process_inode_chunk(mp, agno, mp->m_ialloc_inos, nrec, 1, 0, 0, &bogus)) { /* XXX - i/o error, we've got a problem */ abort(); } } ASSERT(cnt != 0); /* * now return the uncertain inode record to the free pool * and pull another one off the list for processing */ get_uncertain_inode_rec(mp, agno, irec); free_inode_rec(agno, irec); irec = findfirst_uncertain_inode_rec(agno); } while (irec != NULL); if (got_some) do_warn(_("found inodes not in the inode allocation tree\n")); return(1); } xfsprogs-4.9.0+nmu1ubuntu2/repair/dinode.c0000644000000000000000000021706413063067173015376 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "protos.h" #include "err_protos.h" #include "dir2.h" #include "dinode.h" #include "scan.h" #include "versions.h" #include "attr_repair.h" #include "bmap.h" #include "threads.h" #include "slab.h" #include "rmap.h" /* * gettext lookups for translations of strings use mutexes internally to * the library. Hence when we come through here doing parallel scans in * multiple AGs, then all do concurrent text conversions and serialise * on the translation string lookups. Let's avoid doing repeated lookups * by making them static variables and only assigning the translation * once. */ static char *forkname_data; static char *forkname_attr; static char *ftype_real_time; static char *ftype_regular; void dinode_bmbt_translation_init(void) { forkname_data = _("data"); forkname_attr = _("attr"); ftype_real_time = _("real-time"); ftype_regular = _("regular"); } char * get_forkname(int whichfork) { if (whichfork == XFS_DATA_FORK) return forkname_data; return forkname_attr; } /* * inode clearing routines */ static int clear_dinode_attr(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num) { ASSERT(dino->di_forkoff != 0); if (!no_modify) fprintf(stderr, _("clearing inode %" PRIu64 " attributes\n"), ino_num); else fprintf(stderr, _("would have cleared inode %" PRIu64 " attributes\n"), ino_num); if (be16_to_cpu(dino->di_anextents) != 0) { if (no_modify) return(1); dino->di_anextents = cpu_to_be16(0); } if (dino->di_aformat != XFS_DINODE_FMT_EXTENTS) { if (no_modify) return(1); dino->di_aformat = XFS_DINODE_FMT_EXTENTS; } /* get rid of the fork by clearing forkoff */ /* Originally, when the attr repair code was added, the fork was cleared * by turning it into shortform status. This meant clearing the * hdr.totsize/count fields and also changing aformat to LOCAL * (vs EXTENTS). Over various fixes, the aformat and forkoff have * been updated to not show an attribute fork at all, however. * It could be possible that resetting totsize/count are not needed, * but just to be safe, leave it in for now. */ if (!no_modify) { xfs_attr_shortform_t *asf = (xfs_attr_shortform_t *) XFS_DFORK_APTR(dino); asf->hdr.totsize = cpu_to_be16(sizeof(xfs_attr_sf_hdr_t)); asf->hdr.count = 0; dino->di_forkoff = 0; /* got to do this after asf is set */ } /* * always returns 1 since the fork gets zapped */ return(1); } static int clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num) { int dirty = 0; int i; #define __dirty_no_modify_ret(dirty) \ ({ (dirty) = 1; if (no_modify) return 1; }) if (be16_to_cpu(dinoc->di_magic) != XFS_DINODE_MAGIC) { __dirty_no_modify_ret(dirty); dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); } if (!libxfs_dinode_good_version(mp, dinoc->di_version)) { __dirty_no_modify_ret(dirty); if (xfs_sb_version_hascrc(&mp->m_sb)) dinoc->di_version = 3; else dinoc->di_version = 2; } if (be16_to_cpu(dinoc->di_mode) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_mode = 0; } if (be16_to_cpu(dinoc->di_flags) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_flags = 0; } if (be32_to_cpu(dinoc->di_dmevmask) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_dmevmask = 0; } if (dinoc->di_forkoff != 0) { __dirty_no_modify_ret(dirty); dinoc->di_forkoff = 0; } if (dinoc->di_format != XFS_DINODE_FMT_EXTENTS) { __dirty_no_modify_ret(dirty); dinoc->di_format = XFS_DINODE_FMT_EXTENTS; } if (dinoc->di_aformat != XFS_DINODE_FMT_EXTENTS) { __dirty_no_modify_ret(dirty); dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS; } if (be64_to_cpu(dinoc->di_size) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_size = 0; } if (be64_to_cpu(dinoc->di_nblocks) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_nblocks = 0; } if (be16_to_cpu(dinoc->di_onlink) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_onlink = 0; } if (be32_to_cpu(dinoc->di_nextents) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_nextents = 0; } if (be16_to_cpu(dinoc->di_anextents) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_anextents = 0; } if (dinoc->di_version > 1 && be32_to_cpu(dinoc->di_nlink) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_nlink = 0; } /* we are done for version 1/2 inodes */ if (dinoc->di_version < 3) return dirty; if (be64_to_cpu(dinoc->di_ino) != ino_num) { __dirty_no_modify_ret(dirty); dinoc->di_ino = cpu_to_be64(ino_num); } if (platform_uuid_compare(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid)) { __dirty_no_modify_ret(dirty); platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid); } for (i = 0; i < sizeof(dinoc->di_pad2)/sizeof(dinoc->di_pad2[0]); i++) { if (dinoc->di_pad2[i] != 0) { __dirty_no_modify_ret(dirty); memset(dinoc->di_pad2, 0, sizeof(dinoc->di_pad2)); break; } } if (be64_to_cpu(dinoc->di_flags2) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_flags2 = 0; } if (be64_to_cpu(dinoc->di_lsn) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_lsn = 0; } if (be64_to_cpu(dinoc->di_changecount) != 0) { __dirty_no_modify_ret(dirty); dinoc->di_changecount = 0; } return dirty; } static int clear_dinode_unlinked(xfs_mount_t *mp, xfs_dinode_t *dino) { if (be32_to_cpu(dino->di_next_unlinked) != NULLAGINO) { if (!no_modify) dino->di_next_unlinked = cpu_to_be32(NULLAGINO); return(1); } return(0); } /* * this clears the unlinked list too so it should not be called * until after the agi unlinked lists are walked in phase 3. * returns > zero if the inode has been altered while being cleared */ static int clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num) { int dirty; dirty = clear_dinode_core(mp, dino, ino_num); dirty += clear_dinode_unlinked(mp, dino); /* and clear the forks */ if (dirty && !no_modify) memset(XFS_DFORK_DPTR(dino), 0, XFS_LITINO(mp, dino->di_version)); return(dirty); } /* * misc. inode-related utility routines */ /* * verify_ag_bno is heavily used. In the common case, it * performs just two number of compares * Returns 1 for bad ag/bno pair or 0 if it's valid. */ static __inline int verify_ag_bno(xfs_sb_t *sbp, xfs_agnumber_t agno, xfs_agblock_t agbno) { if (agno < (sbp->sb_agcount - 1)) return (agbno >= sbp->sb_agblocks); if (agno == (sbp->sb_agcount - 1)) return (agbno >= (sbp->sb_dblocks - ((xfs_rfsblock_t)(sbp->sb_agcount - 1) * sbp->sb_agblocks))); return 1; } /* * returns 0 if inode number is valid, 1 if bogus */ int verify_inum(xfs_mount_t *mp, xfs_ino_t ino) { xfs_agnumber_t agno; xfs_agino_t agino; xfs_agblock_t agbno; xfs_sb_t *sbp = &mp->m_sb;; /* range check ag #, ag block. range-checking offset is pointless */ agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); if (agbno == 0) return 1; if (ino == 0 || ino == NULLFSINO) return(1); if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) return(1); return verify_ag_bno(sbp, agno, agbno); } /* * have a separate routine to ensure that we don't accidentally * lose illegally set bits in the agino by turning it into an FSINO * to feed to the above routine */ int verify_aginum(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t agino) { xfs_agblock_t agbno; xfs_sb_t *sbp = &mp->m_sb;; /* range check ag #, ag block. range-checking offset is pointless */ if (agino == 0 || agino == NULLAGINO) return(1); /* * agino's can't be too close to NULLAGINO because the min blocksize * is 9 bits and at most 1 bit of that gets used for the inode offset * so if the agino gets shifted by the # of offset bits and compared * to the legal agbno values, a bogus agino will be too large. there * will be extra bits set at the top that shouldn't be set. */ agbno = XFS_AGINO_TO_AGBNO(mp, agino); if (agbno == 0) return 1; return verify_ag_bno(sbp, agno, agbno); } /* * return 1 if block number is good, 0 if out of range */ int verify_dfsbno(xfs_mount_t *mp, xfs_fsblock_t fsbno) { xfs_agnumber_t agno; xfs_agblock_t agbno; xfs_sb_t *sbp = &mp->m_sb;; /* range check ag #, ag block. range-checking offset is pointless */ agno = XFS_FSB_TO_AGNO(mp, fsbno); agbno = XFS_FSB_TO_AGBNO(mp, fsbno); return verify_ag_bno(sbp, agno, agbno) == 0; } #define XR_DFSBNORANGE_VALID 0 #define XR_DFSBNORANGE_BADSTART 1 #define XR_DFSBNORANGE_BADEND 2 #define XR_DFSBNORANGE_OVERFLOW 3 static __inline int verify_dfsbno_range(xfs_mount_t *mp, xfs_fsblock_t fsbno, xfs_filblks_t count) { xfs_agnumber_t agno; xfs_agblock_t agbno; xfs_sb_t *sbp = &mp->m_sb;; /* the start and end blocks better be in the same allocation group */ agno = XFS_FSB_TO_AGNO(mp, fsbno); if (agno != XFS_FSB_TO_AGNO(mp, fsbno + count - 1)) { return XR_DFSBNORANGE_OVERFLOW; } agbno = XFS_FSB_TO_AGBNO(mp, fsbno); if (verify_ag_bno(sbp, agno, agbno)) { return XR_DFSBNORANGE_BADSTART; } agbno = XFS_FSB_TO_AGBNO(mp, fsbno + count - 1); if (verify_ag_bno(sbp, agno, agbno)) { return XR_DFSBNORANGE_BADEND; } return (XR_DFSBNORANGE_VALID); } int verify_agbno(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t agbno) { xfs_sb_t *sbp = &mp->m_sb;; /* range check ag #, ag block. range-checking offset is pointless */ return verify_ag_bno(sbp, agno, agbno) == 0; } static int process_rt_rec( xfs_mount_t *mp, xfs_bmbt_irec_t *irec, xfs_ino_t ino, xfs_rfsblock_t *tot, int check_dups) { xfs_fsblock_t b; xfs_rtblock_t ext; int state; int pwe; /* partially-written extent */ /* * check numeric validity of the extent */ if (irec->br_startblock >= mp->m_sb.sb_rblocks) { do_warn( _("inode %" PRIu64 " - bad rt extent start block number %" PRIu64 ", offset %" PRIu64 "\n"), ino, irec->br_startblock, irec->br_startoff); return 1; } if (irec->br_startblock + irec->br_blockcount - 1 >= mp->m_sb.sb_rblocks) { do_warn( _("inode %" PRIu64 " - bad rt extent last block number %" PRIu64 ", offset %" PRIu64 "\n"), ino, irec->br_startblock + irec->br_blockcount - 1, irec->br_startoff); return 1; } if (irec->br_startblock + irec->br_blockcount - 1 < irec->br_startblock) { do_warn( _("inode %" PRIu64 " - bad rt extent overflows - start %" PRIu64 ", " "end %" PRIu64 ", offset %" PRIu64 "\n"), ino, irec->br_startblock, irec->br_startblock + irec->br_blockcount - 1, irec->br_startoff); return 1; } /* * verify that the blocks listed in the record * are multiples of an extent */ if (xfs_sb_version_hasextflgbit(&mp->m_sb) == 0 && (irec->br_startblock % mp->m_sb.sb_rextsize != 0 || irec->br_blockcount % mp->m_sb.sb_rextsize != 0)) { do_warn( _("malformed rt inode extent [%" PRIu64 " %" PRIu64 "] (fs rtext size = %u)\n"), irec->br_startblock, irec->br_blockcount, mp->m_sb.sb_rextsize); return 1; } /* * set the appropriate number of extents * this iterates block by block, this can be optimised using extents */ for (b = irec->br_startblock; b < irec->br_startblock + irec->br_blockcount; b += mp->m_sb.sb_rextsize) { ext = (xfs_rtblock_t) b / mp->m_sb.sb_rextsize; pwe = xfs_sb_version_hasextflgbit(&mp->m_sb) && irec->br_state == XFS_EXT_UNWRITTEN && (b % mp->m_sb.sb_rextsize != 0); if (check_dups == 1) { if (search_rt_dup_extent(mp, ext) && !pwe) { do_warn( _("data fork in rt ino %" PRIu64 " claims dup rt extent," "off - %" PRIu64 ", start - %" PRIu64 ", count %" PRIu64 "\n"), ino, irec->br_startoff, irec->br_startblock, irec->br_blockcount); return 1; } continue; } state = get_rtbmap(ext); switch (state) { case XR_E_FREE: case XR_E_UNKNOWN: set_rtbmap(ext, XR_E_INUSE); break; case XR_E_BAD_STATE: do_error( _("bad state in rt block map %" PRIu64 "\n"), ext); case XR_E_FS_MAP: case XR_E_INO: case XR_E_INUSE_FS: do_error( _("data fork in rt inode %" PRIu64 " found metadata block %" PRIu64 " in rt bmap\n"), ino, ext); case XR_E_INUSE: if (pwe) break; case XR_E_MULT: set_rtbmap(ext, XR_E_MULT); do_warn( _("data fork in rt inode %" PRIu64 " claims used rt block %" PRIu64 "\n"), ino, ext); return 1; case XR_E_FREE1: default: do_error( _("illegal state %d in rt block map %" PRIu64 "\n"), state, b); } } /* * bump up the block counter */ *tot += irec->br_blockcount; return 0; } /* * return 1 if inode should be cleared, 0 otherwise * if check_dups should be set to 1, that implies that * the primary purpose of this call is to see if the * file overlaps with any duplicate extents (in the * duplicate extent list). */ static int process_bmbt_reclist_int( xfs_mount_t *mp, xfs_bmbt_rec_t *rp, int *numrecs, int type, xfs_ino_t ino, xfs_rfsblock_t *tot, blkmap_t **blkmapp, xfs_fileoff_t *first_key, xfs_fileoff_t *last_key, int check_dups, int whichfork) { xfs_bmbt_irec_t irec; xfs_filblks_t cp = 0; /* prev count */ xfs_fsblock_t sp = 0; /* prev start */ xfs_fileoff_t op = 0; /* prev offset */ xfs_fsblock_t b; char *ftype; char *forkname = get_forkname(whichfork); int i; int state; xfs_agnumber_t agno; xfs_agblock_t agbno; xfs_agblock_t ebno; xfs_extlen_t blen; xfs_agnumber_t locked_agno = -1; int error = 1; if (type == XR_INO_RTDATA) ftype = ftype_real_time; else ftype = ftype_regular; for (i = 0; i < *numrecs; i++) { libxfs_bmbt_disk_get_all((rp +i), &irec); if (i == 0) *last_key = *first_key = irec.br_startoff; else *last_key = irec.br_startoff; if (i > 0 && op + cp > irec.br_startoff) { do_warn( _("bmap rec out of order, inode %" PRIu64" entry %d " "[o s c] [%" PRIu64 " %" PRIu64 " %" PRIu64 "], " "%d [%" PRIu64 " %" PRIu64 " %" PRIu64 "]\n"), ino, i, irec.br_startoff, irec.br_startblock, irec.br_blockcount, i - 1, op, sp, cp); goto done; } op = irec.br_startoff; cp = irec.br_blockcount; sp = irec.br_startblock; /* * check numeric validity of the extent */ if (irec.br_blockcount == 0) { do_warn( _("zero length extent (off = %" PRIu64 ", fsbno = %" PRIu64 ") in ino %" PRIu64 "\n"), irec.br_startoff, irec.br_startblock, ino); goto done; } if (type == XR_INO_RTDATA && whichfork == XFS_DATA_FORK) { /* * realtime bitmaps don't use AG locks, so returning * immediately is fine for this code path. */ if (process_rt_rec(mp, &irec, ino, tot, check_dups)) return 1; /* * skip rest of loop processing since that'irec.br_startblock * all for regular file forks and attr forks */ continue; } /* * regular file data fork or attribute fork */ switch (verify_dfsbno_range(mp, irec.br_startblock, irec.br_blockcount)) { case XR_DFSBNORANGE_VALID: break; case XR_DFSBNORANGE_BADSTART: do_warn( _("inode %" PRIu64 " - bad extent starting block number %" PRIu64 ", offset %" PRIu64 "\n"), ino, irec.br_startblock, irec.br_startoff); goto done; case XR_DFSBNORANGE_BADEND: do_warn( _("inode %" PRIu64 " - bad extent last block number %" PRIu64 ", offset %" PRIu64 "\n"), ino, irec.br_startblock + irec.br_blockcount - 1, irec.br_startoff); goto done; case XR_DFSBNORANGE_OVERFLOW: do_warn( _("inode %" PRIu64 " - bad extent overflows - start %" PRIu64 ", " "end %" PRIu64 ", offset %" PRIu64 "\n"), ino, irec.br_startblock, irec.br_startblock + irec.br_blockcount - 1, irec.br_startoff); goto done; } /* Ensure this extent does not extend beyond the max offset */ if (irec.br_startoff + irec.br_blockcount - 1 > fs_max_file_offset) { do_warn( _("inode %" PRIu64 " - extent exceeds max offset - start %" PRIu64 ", " "count %" PRIu64 ", physical block %" PRIu64 "\n"), ino, irec.br_startoff, irec.br_blockcount, irec.br_startblock); goto done; } if (blkmapp && *blkmapp) { int error2; error2 = blkmap_set_ext(blkmapp, irec.br_startoff, irec.br_startblock, irec.br_blockcount); if (error2) { /* * we don't want to clear the inode due to an * internal bmap tracking error, but if we've * run out of memory then we simply can't * validate that the filesystem is consistent. * Hence just abort at this point with an ENOMEM * error. */ do_abort( _("Fatal error: inode %" PRIu64 " - blkmap_set_ext(): %s\n" "\t%s fork, off - %" PRIu64 ", start - %" PRIu64 ", cnt %" PRIu64 "\n"), ino, strerror(error2), forkname, irec.br_startoff, irec.br_startblock, irec.br_blockcount); } } /* * Profiling shows that the following loop takes the * most time in all of xfs_repair. */ agno = XFS_FSB_TO_AGNO(mp, irec.br_startblock); agbno = XFS_FSB_TO_AGBNO(mp, irec.br_startblock); ebno = agbno + irec.br_blockcount; if (agno != locked_agno) { if (locked_agno != -1) pthread_mutex_unlock(&ag_locks[locked_agno].lock); pthread_mutex_lock(&ag_locks[agno].lock); locked_agno = agno; } if (check_dups) { /* * if we're just checking the bmap for dups, * return if we find one, otherwise, continue * checking each entry without setting the * block bitmap */ if (!(type == XR_INO_DATA && xfs_sb_version_hasreflink(&mp->m_sb)) && search_dup_extent(agno, agbno, ebno)) { do_warn( _("%s fork in ino %" PRIu64 " claims dup extent, " "off - %" PRIu64 ", start - %" PRIu64 ", cnt %" PRIu64 "\n"), forkname, ino, irec.br_startoff, irec.br_startblock, irec.br_blockcount); goto done; } *tot += irec.br_blockcount; continue; } for (b = irec.br_startblock; agbno < ebno; b += blen, agbno += blen) { state = get_bmap_ext(agno, agbno, ebno, &blen); switch (state) { case XR_E_FREE: case XR_E_FREE1: do_warn( _("%s fork in ino %" PRIu64 " claims free block %" PRIu64 "\n"), forkname, ino, (__uint64_t) b); /* fall through ... */ case XR_E_INUSE1: /* seen by rmap */ case XR_E_UNKNOWN: set_bmap_ext(agno, agbno, blen, XR_E_INUSE); break; case XR_E_BAD_STATE: do_error(_("bad state in block map %" PRIu64 "\n"), b); case XR_E_FS_MAP1: case XR_E_INO1: case XR_E_INUSE_FS1: do_warn(_("rmap claims metadata use!\n")); /* fall through */ case XR_E_FS_MAP: case XR_E_INO: case XR_E_INUSE_FS: do_warn( _("%s fork in inode %" PRIu64 " claims metadata block %" PRIu64 "\n"), forkname, ino, b); goto done; case XR_E_INUSE: case XR_E_MULT: set_bmap_ext(agno, agbno, blen, XR_E_MULT); if (type == XR_INO_DATA && xfs_sb_version_hasreflink(&mp->m_sb)) break; do_warn( _("%s fork in %s inode %" PRIu64 " claims used block %" PRIu64 "\n"), forkname, ftype, ino, b); goto done; default: do_error( _("illegal state %d in block map %" PRIu64 "\n"), state, b); } } if (collect_rmaps) { /* && !check_dups */ error = rmap_add_rec(mp, ino, whichfork, &irec); if (error) do_error( _("couldn't add reverse mapping\n") ); } *tot += irec.br_blockcount; } error = 0; done: if (locked_agno != -1) pthread_mutex_unlock(&ag_locks[locked_agno].lock); if (i != *numrecs) { ASSERT(i < *numrecs); do_warn(_("correcting nextents for inode %" PRIu64 "\n"), ino); *numrecs = i; } return error; } /* * return 1 if inode should be cleared, 0 otherwise, sets block bitmap * as a side-effect */ int process_bmbt_reclist( xfs_mount_t *mp, xfs_bmbt_rec_t *rp, int *numrecs, int type, xfs_ino_t ino, xfs_rfsblock_t *tot, blkmap_t **blkmapp, xfs_fileoff_t *first_key, xfs_fileoff_t *last_key, int whichfork) { return process_bmbt_reclist_int(mp, rp, numrecs, type, ino, tot, blkmapp, first_key, last_key, 0, whichfork); } /* * return 1 if inode should be cleared, 0 otherwise, does not set * block bitmap */ int scan_bmbt_reclist( xfs_mount_t *mp, xfs_bmbt_rec_t *rp, int *numrecs, int type, xfs_ino_t ino, xfs_rfsblock_t *tot, int whichfork) { xfs_fileoff_t first_key = 0; xfs_fileoff_t last_key = 0; return process_bmbt_reclist_int(mp, rp, numrecs, type, ino, tot, NULL, &first_key, &last_key, 1, whichfork); } /* * Grab the buffer backing an inode. This is meant for routines that * work with inodes one at a time in any order (like walking the * unlinked lists to look for inodes). The caller is responsible for * writing/releasing the buffer. */ struct xfs_buf * get_agino_buf( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino, struct xfs_dinode **dipp) { struct xfs_buf *bp; int cluster_size; int ino_per_cluster; xfs_agino_t cluster_agino; xfs_daddr_t cluster_daddr; xfs_daddr_t cluster_blks; /* * Inode buffers have been read into memory in inode_cluster_size * chunks (or one FSB). To find the correct buffer for an inode, * we must find the buffer for its cluster, add the appropriate * offset, and return that. */ cluster_size = MAX(mp->m_inode_cluster_size, mp->m_sb.sb_blocksize); ino_per_cluster = cluster_size / mp->m_sb.sb_inodesize; cluster_agino = agino & ~(ino_per_cluster - 1); cluster_blks = XFS_FSB_TO_DADDR(mp, MAX(1, mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog)); cluster_daddr = XFS_AGB_TO_DADDR(mp, agno, XFS_AGINO_TO_AGBNO(mp, cluster_agino)); #ifdef XR_INODE_TRACE printf("cluster_size %d ipc %d clusagino %d daddr %lld sectors %lld\n", cluster_size, ino_per_cluster, cluster_agino, cluster_daddr, cluster_blks); #endif bp = libxfs_readbuf(mp->m_dev, cluster_daddr, cluster_blks, 0, &xfs_inode_buf_ops); if (!bp) { do_warn(_("cannot read inode (%u/%u), disk block %" PRIu64 "\n"), agno, cluster_agino, cluster_daddr); return NULL; } *dipp = xfs_make_iptr(mp, bp, agino - cluster_agino); ASSERT(!xfs_sb_version_hascrc(&mp->m_sb) || XFS_AGINO_TO_INO(mp, agno, agino) == be64_to_cpu((*dipp)->di_ino)); return bp; } /* * higher level inode processing stuff starts here: * first, one utility routine for each type of inode */ /* * return 1 if inode should be cleared, 0 otherwise */ static int process_btinode( xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t ino, xfs_dinode_t *dip, int type, int *dirty, xfs_rfsblock_t *tot, __uint64_t *nex, blkmap_t **blkmapp, int whichfork, int check_dups) { xfs_bmdr_block_t *dib; xfs_fileoff_t last_key; xfs_fileoff_t first_key = 0; xfs_ino_t lino; xfs_bmbt_ptr_t *pp; xfs_bmbt_key_t *pkey; char *forkname = get_forkname(whichfork); int i; int level; int numrecs; bmap_cursor_t cursor; __uint64_t magic; dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); lino = XFS_AGINO_TO_INO(mp, agno, ino); *tot = 0; *nex = 0; magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_BMAP_CRC_MAGIC : XFS_BMAP_MAGIC; level = be16_to_cpu(dib->bb_level); numrecs = be16_to_cpu(dib->bb_numrecs); if ((level == 0) || (level > XFS_BM_MAXLEVELS(mp, whichfork))) { /* * XXX - if we were going to fix up the inode, * we'd try to treat the fork as an interior * node and see if we could get an accurate * level value from one of the blocks pointed * to by the pointers in the fork. For now * though, we just bail (and blow out the inode). */ do_warn( _("bad level %d in inode %" PRIu64 " bmap btree root block\n"), level, XFS_AGINO_TO_INO(mp, agno, ino)); return(1); } if (numrecs == 0) { do_warn( _("bad numrecs 0 in inode %" PRIu64 " bmap btree root block\n"), XFS_AGINO_TO_INO(mp, agno, ino)); return(1); } /* * use bmdr/dfork_dsize since the root block is in the data fork */ if (XFS_BMDR_SPACE_CALC(numrecs) > XFS_DFORK_SIZE(dip, mp, whichfork)) { do_warn( _("indicated size of %s btree root (%d bytes) greater than space in " "inode %" PRIu64 " %s fork\n"), forkname, XFS_BMDR_SPACE_CALC(numrecs), lino, forkname); return(1); } init_bm_cursor(&cursor, level + 1); pp = XFS_BMDR_PTR_ADDR(dib, 1, libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0)); pkey = XFS_BMDR_KEY_ADDR(dib, 1); last_key = NULLFILEOFF; for (i = 0; i < numrecs; i++) { /* * XXX - if we were going to do more to fix up the inode * btree, we'd do it right here. For now, if there's a * problem, we'll bail out and presumably clear the inode. */ if (!verify_dfsbno(mp, get_unaligned_be64(&pp[i]))) { do_warn( _("bad bmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"), get_unaligned_be64(&pp[i]), lino); return(1); } if (scan_lbtree(get_unaligned_be64(&pp[i]), level, scan_bmapbt, type, whichfork, lino, tot, nex, blkmapp, &cursor, 1, check_dups, magic, &xfs_bmbt_buf_ops)) return(1); /* * fix key (offset) mismatches between the keys in root * block records and the first key of each child block. * fixes cases where entries have been shifted between * blocks but the parent hasn't been updated */ if (!check_dups && cursor.level[level-1].first_key != get_unaligned_be64(&pkey[i].br_startoff)) { if (!no_modify) { do_warn( _("correcting key in bmbt root (was %" PRIu64 ", now %" PRIu64") in inode " "%" PRIu64" %s fork\n"), get_unaligned_be64(&pkey[i].br_startoff), cursor.level[level-1].first_key, XFS_AGINO_TO_INO(mp, agno, ino), forkname); *dirty = 1; put_unaligned_be64( cursor.level[level-1].first_key, &pkey[i].br_startoff); } else { do_warn( _("bad key in bmbt root (is %" PRIu64 ", would reset to %" PRIu64 ") in inode " "%" PRIu64 " %s fork\n"), get_unaligned_be64(&pkey[i].br_startoff), cursor.level[level-1].first_key, XFS_AGINO_TO_INO(mp, agno, ino), forkname); } } /* * make sure that keys are in ascending order. blow out * inode if the ordering doesn't hold */ if (check_dups == 0) { if (last_key != NULLFILEOFF && last_key >= cursor.level[level-1].first_key) { do_warn( _("out of order bmbt root key %" PRIu64 " in inode %" PRIu64 " %s fork\n"), first_key, XFS_AGINO_TO_INO(mp, agno, ino), forkname); return(1); } last_key = cursor.level[level-1].first_key; } } /* * Ideally if all the extents are ok (perhaps after further * checks below?) we'd just move this back into extents format. * But for now clear it, as the kernel will choke on this */ if (*nex <= XFS_DFORK_SIZE(dip, mp, whichfork) / sizeof(xfs_bmbt_rec_t)) { do_warn( _("extent count for ino %" PRIu64 " %s fork too low (%" PRIu64 ") for file format\n"), lino, forkname, *nex); return(1); } /* * Check that the last child block's forward sibling pointer * is NULL. */ if (check_dups == 0 && cursor.level[0].right_fsbno != NULLFSBLOCK) { do_warn( _("bad fwd (right) sibling pointer (saw %" PRIu64 " should be NULLFSBLOCK)\n"), cursor.level[0].right_fsbno); do_warn( _("\tin inode %" PRIu64 " (%s fork) bmap btree block %" PRIu64 "\n"), XFS_AGINO_TO_INO(mp, agno, ino), forkname, cursor.level[0].fsbno); return(1); } return(0); } /* * return 1 if inode should be cleared, 0 otherwise */ static int process_exinode( xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t ino, xfs_dinode_t *dip, int type, int *dirty, xfs_rfsblock_t *tot, __uint64_t *nex, blkmap_t **blkmapp, int whichfork, int check_dups) { xfs_ino_t lino; xfs_bmbt_rec_t *rp; xfs_fileoff_t first_key; xfs_fileoff_t last_key; int32_t numrecs; int ret; lino = XFS_AGINO_TO_INO(mp, agno, ino); rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork); *tot = 0; numrecs = XFS_DFORK_NEXTENTS(dip, whichfork); /* * We've already decided on the maximum number of extents on the inode, * and numrecs may be corrupt. Hence make sure we only allow numrecs to * be in the range of valid on-disk numbers, which is: * 0 < numrecs < 2^31 - 1 */ if (numrecs < 0) numrecs = *nex; /* * XXX - if we were going to fix up the btree record, * we'd do it right here. For now, if there's a problem, * we'll bail out and presumably clear the inode. */ if (check_dups == 0) ret = process_bmbt_reclist(mp, rp, &numrecs, type, lino, tot, blkmapp, &first_key, &last_key, whichfork); else ret = scan_bmbt_reclist(mp, rp, &numrecs, type, lino, tot, whichfork); *nex = numrecs; return ret; } /* * return 1 if inode should be cleared, 0 otherwise */ static int process_lclinode( xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t ino, xfs_dinode_t *dip, int whichfork) { xfs_attr_shortform_t *asf; xfs_ino_t lino; lino = XFS_AGINO_TO_INO(mp, agno, ino); if (whichfork == XFS_DATA_FORK && be64_to_cpu(dip->di_size) > XFS_DFORK_DSIZE(dip, mp)) { do_warn( _("local inode %" PRIu64 " data fork is too large (size = %lld, max = %d)\n"), lino, (unsigned long long) be64_to_cpu(dip->di_size), XFS_DFORK_DSIZE(dip, mp)); return(1); } else if (whichfork == XFS_ATTR_FORK) { asf = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); if (be16_to_cpu(asf->hdr.totsize) > XFS_DFORK_ASIZE(dip, mp)) { do_warn( _("local inode %" PRIu64 " attr fork too large (size %d, max = %d)\n"), lino, be16_to_cpu(asf->hdr.totsize), XFS_DFORK_ASIZE(dip, mp)); return(1); } if (be16_to_cpu(asf->hdr.totsize) < sizeof(xfs_attr_sf_hdr_t)) { do_warn( _("local inode %" PRIu64 " attr too small (size = %d, min size = %zd)\n"), lino, be16_to_cpu(asf->hdr.totsize), sizeof(xfs_attr_sf_hdr_t)); return(1); } } return(0); } static int process_symlink_extlist(xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino) { xfs_fileoff_t expected_offset; xfs_bmbt_rec_t *rp; xfs_bmbt_irec_t irec; int numrecs; int i; int max_blocks; if (be64_to_cpu(dino->di_size) <= XFS_DFORK_DSIZE(dino, mp)) { if (dino->di_format == XFS_DINODE_FMT_LOCAL) return 0; do_warn( _("mismatch between format (%d) and size (%" PRId64 ") in symlink ino %" PRIu64 "\n"), dino->di_format, (__int64_t)be64_to_cpu(dino->di_size), lino); return 1; } if (dino->di_format == XFS_DINODE_FMT_LOCAL) { do_warn( _("mismatch between format (%d) and size (%" PRId64 ") in symlink inode %" PRIu64 "\n"), dino->di_format, (__int64_t)be64_to_cpu(dino->di_size), lino); return 1; } rp = (xfs_bmbt_rec_t *)XFS_DFORK_DPTR(dino); numrecs = be32_to_cpu(dino->di_nextents); /* * the max # of extents in a symlink inode is equal to the * number of max # of blocks required to store the symlink */ if (numrecs > max_symlink_blocks) { do_warn( _("bad number of extents (%d) in symlink %" PRIu64 " data fork\n"), numrecs, lino); return(1); } max_blocks = max_symlink_blocks; expected_offset = 0; for (i = 0; i < numrecs; i++) { libxfs_bmbt_disk_get_all((rp +i), &irec); if (irec.br_startoff != expected_offset) { do_warn( _("bad extent #%d offset (%" PRIu64 ") in symlink %" PRIu64 " data fork\n"), i, irec.br_startoff, lino); return(1); } if (irec.br_blockcount == 0 || irec.br_blockcount > max_blocks) { do_warn( _("bad extent #%d count (%" PRIu64 ") in symlink %" PRIu64 " data fork\n"), i, irec.br_blockcount, lino); return(1); } max_blocks -= irec.br_blockcount; expected_offset += irec.br_blockcount; } return(0); } /* * takes a name and length and returns 1 if the name contains * a \0, returns 0 otherwise */ static int null_check(char *name, int length) { int i; ASSERT(length < MAXPATHLEN); for (i = 0; i < length; i++, name++) { if (*name == '\0') return(1); } return(0); } static int process_symlink_remote( struct xfs_mount *mp, xfs_ino_t lino, struct xfs_dinode *dino, struct blkmap *blkmap, char *dst) { xfs_fsblock_t fsbno; struct xfs_buf *bp; char *src; int pathlen; int offset; int i; offset = 0; pathlen = be64_to_cpu(dino->di_size); i = 0; while (pathlen > 0) { int blk_cnt = 1; int byte_cnt; int badcrc = 0; fsbno = blkmap_get(blkmap, i); if (fsbno == NULLFSBLOCK) { do_warn( _("cannot read inode %" PRIu64 ", file block %d, NULL disk block\n"), lino, i); return 1; } /* * There's a symlink header for each contiguous extent. If * there are contiguous blocks, read them in one go. */ while (blk_cnt <= max_symlink_blocks) { if (blkmap_get(blkmap, i + 1) != fsbno + 1) break; blk_cnt++; i++; } byte_cnt = XFS_FSB_TO_B(mp, blk_cnt); bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno), BTOBB(byte_cnt), 0, &xfs_symlink_buf_ops); if (!bp) { do_warn( _("cannot read inode %" PRIu64 ", file block %d, disk block %" PRIu64 "\n"), lino, i, fsbno); return 1; } if (bp->b_error == -EFSBADCRC) { do_warn( _("Bad symlink buffer CRC, block %" PRIu64 ", inode %" PRIu64 ".\n" "Correcting CRC, but symlink may be bad.\n"), fsbno, lino); badcrc = 1; } byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt); byte_cnt = MIN(pathlen, byte_cnt); src = bp->b_addr; if (xfs_sb_version_hascrc(&mp->m_sb)) { if (!libxfs_symlink_hdr_ok(lino, offset, byte_cnt, bp)) { do_warn( _("bad symlink header ino %" PRIu64 ", file block %d, disk block %" PRIu64 "\n"), lino, i, fsbno); libxfs_putbuf(bp); return 1; } src += sizeof(struct xfs_dsymlink_hdr); } memmove(dst + offset, src, byte_cnt); pathlen -= byte_cnt; offset += byte_cnt; i++; if (badcrc && !no_modify) libxfs_writebuf(bp, 0); else libxfs_putbuf(bp); } return 0; } /* * like usual, returns 0 if everything's ok and 1 if something's * bogus */ static int process_symlink( xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino, blkmap_t *blkmap) { char *symlink; char data[MAXPATHLEN]; /* * check size against kernel symlink limits. we know * size is consistent with inode storage format -- e.g. * the inode is structurally ok so we don't have to check * for that */ if (be64_to_cpu(dino->di_size) >= MAXPATHLEN) { do_warn(_("symlink in inode %" PRIu64 " too long (%llu chars)\n"), lino, (unsigned long long) be64_to_cpu(dino->di_size)); return(1); } /* * have to check symlink component by component. * get symlink contents into data area */ symlink = &data[0]; if (be64_to_cpu(dino->di_size) <= XFS_DFORK_DSIZE(dino, mp)) { /* * local symlink, just copy the symlink out of the * inode into the data area */ memmove(symlink, XFS_DFORK_DPTR(dino), be64_to_cpu(dino->di_size)); } else { int error; error = process_symlink_remote(mp, lino, dino, blkmap, symlink); if (error) return error; } data[be64_to_cpu(dino->di_size)] = '\0'; /* * check for nulls */ if (null_check(symlink, be64_to_cpu(dino->di_size))) { do_warn( _("found illegal null character in symlink inode %" PRIu64 "\n"), lino); return(1); } return(0); } /* * called to process the set of misc inode special inode types * that have no associated data storage (fifos, pipes, devices, etc.). */ static int process_misc_ino_types(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t lino, int type) { /* * disallow mountpoint inodes until such time as the * kernel actually allows them to be created (will * probably require a superblock version rev, sigh). */ if (type == XR_INO_MOUNTPOINT) { do_warn( _("inode %" PRIu64 " has bad inode type (IFMNT)\n"), lino); return(1); } /* * must also have a zero size */ if (be64_to_cpu(dino->di_size) != 0) { switch (type) { case XR_INO_CHRDEV: do_warn( _("size of character device inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, (__int64_t)be64_to_cpu(dino->di_size)); break; case XR_INO_BLKDEV: do_warn( _("size of block device inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, (__int64_t)be64_to_cpu(dino->di_size)); break; case XR_INO_SOCK: do_warn( _("size of socket inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, (__int64_t)be64_to_cpu(dino->di_size)); break; case XR_INO_FIFO: do_warn( _("size of fifo inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, (__int64_t)be64_to_cpu(dino->di_size)); break; default: do_warn(_("Internal error - process_misc_ino_types, " "illegal type %d\n"), type); abort(); } return(1); } return(0); } static int process_misc_ino_types_blocks(xfs_rfsblock_t totblocks, xfs_ino_t lino, int type) { /* * you can not enforce all misc types have zero data fork blocks * by checking dino->di_nblocks because atotblocks (attribute * blocks) are part of nblocks. We must check this later when atotblocks * has been calculated or by doing a simple check that anExtents == 0. * We must also guarantee that totblocks is 0. Thus nblocks checking * will be done later in process_dinode_int for misc types. */ if (totblocks != 0) { switch (type) { case XR_INO_CHRDEV: do_warn( _("size of character device inode %" PRIu64 " != 0 (%" PRIu64 " blocks)\n"), lino, totblocks); break; case XR_INO_BLKDEV: do_warn( _("size of block device inode %" PRIu64 " != 0 (%" PRIu64 " blocks)\n"), lino, totblocks); break; case XR_INO_SOCK: do_warn( _("size of socket inode %" PRIu64 " != 0 (%" PRIu64 " blocks)\n"), lino, totblocks); break; case XR_INO_FIFO: do_warn( _("size of fifo inode %" PRIu64 " != 0 (%" PRIu64 " blocks)\n"), lino, totblocks); break; default: return(0); } return(1); } return (0); } static inline int dinode_fmt( xfs_dinode_t *dino) { return be16_to_cpu(dino->di_mode) & S_IFMT; } static inline void change_dinode_fmt( xfs_dinode_t *dino, int new_fmt) { int mode = be16_to_cpu(dino->di_mode); ASSERT((new_fmt & ~S_IFMT) == 0); mode &= ~S_IFMT; mode |= new_fmt; dino->di_mode = cpu_to_be16(mode); } static int check_dinode_mode_format( xfs_dinode_t *dinoc) { if (dinoc->di_format >= XFS_DINODE_FMT_UUID) return -1; /* FMT_UUID is not used */ switch (dinode_fmt(dinoc)) { case S_IFIFO: case S_IFCHR: case S_IFBLK: case S_IFSOCK: return (dinoc->di_format != XFS_DINODE_FMT_DEV) ? -1 : 0; case S_IFDIR: return (dinoc->di_format < XFS_DINODE_FMT_LOCAL || dinoc->di_format > XFS_DINODE_FMT_BTREE) ? -1 : 0; case S_IFREG: return (dinoc->di_format < XFS_DINODE_FMT_EXTENTS || dinoc->di_format > XFS_DINODE_FMT_BTREE) ? -1 : 0; case S_IFLNK: return (dinoc->di_format < XFS_DINODE_FMT_LOCAL || dinoc->di_format > XFS_DINODE_FMT_EXTENTS) ? -1 : 0; default: ; } return 0; /* invalid modes are checked elsewhere */ } /* * If inode is a superblock inode, does type check to make sure is it valid. * Returns 0 if it's valid, non-zero if it needs to be cleared. */ static int process_check_sb_inodes( xfs_mount_t *mp, xfs_dinode_t *dinoc, xfs_ino_t lino, int *type, int *dirty) { if (lino == mp->m_sb.sb_rootino) { if (*type != XR_INO_DIR) { do_warn(_("root inode %" PRIu64 " has bad type 0x%x\n"), lino, dinode_fmt(dinoc)); *type = XR_INO_DIR; if (!no_modify) { do_warn(_("resetting to directory\n")); change_dinode_fmt(dinoc, S_IFDIR); *dirty = 1; } else do_warn(_("would reset to directory\n")); } return 0; } if (lino == mp->m_sb.sb_uquotino) { if (*type != XR_INO_DATA) { do_warn(_("user quota inode %" PRIu64 " has bad type 0x%x\n"), lino, dinode_fmt(dinoc)); mp->m_sb.sb_uquotino = NULLFSINO; return 1; } return 0; } if (lino == mp->m_sb.sb_gquotino) { if (*type != XR_INO_DATA) { do_warn(_("group quota inode %" PRIu64 " has bad type 0x%x\n"), lino, dinode_fmt(dinoc)); mp->m_sb.sb_gquotino = NULLFSINO; return 1; } return 0; } if (lino == mp->m_sb.sb_pquotino) { if (*type != XR_INO_DATA) { do_warn(_("project quota inode %" PRIu64 " has bad type 0x%x\n"), lino, dinode_fmt(dinoc)); mp->m_sb.sb_pquotino = NULLFSINO; return 1; } return 0; } if (lino == mp->m_sb.sb_rsumino) { if (*type != XR_INO_RTSUM) { do_warn( _("realtime summary inode %" PRIu64 " has bad type 0x%x, "), lino, dinode_fmt(dinoc)); if (!no_modify) { do_warn(_("resetting to regular file\n")); change_dinode_fmt(dinoc, S_IFREG); *dirty = 1; } else { do_warn(_("would reset to regular file\n")); } } if (mp->m_sb.sb_rblocks == 0 && dinoc->di_nextents != 0) { do_warn( _("bad # of extents (%u) for realtime summary inode %" PRIu64 "\n"), be32_to_cpu(dinoc->di_nextents), lino); return 1; } return 0; } if (lino == mp->m_sb.sb_rbmino) { if (*type != XR_INO_RTBITMAP) { do_warn( _("realtime bitmap inode %" PRIu64 " has bad type 0x%x, "), lino, dinode_fmt(dinoc)); if (!no_modify) { do_warn(_("resetting to regular file\n")); change_dinode_fmt(dinoc, S_IFREG); *dirty = 1; } else { do_warn(_("would reset to regular file\n")); } } if (mp->m_sb.sb_rblocks == 0 && dinoc->di_nextents != 0) { do_warn( _("bad # of extents (%u) for realtime bitmap inode %" PRIu64 "\n"), be32_to_cpu(dinoc->di_nextents), lino); return 1; } return 0; } return 0; } /* * general size/consistency checks: * * if the size <= size of the data fork, directories must be * local inodes unlike regular files which would be extent inodes. * all the other mentioned types have to have a zero size value. * * if the size and format don't match, get out now rather than * risk trying to process a non-existent extents or btree * type data fork. */ static int process_check_inode_sizes( xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t lino, int type) { xfs_fsize_t size = be64_to_cpu(dino->di_size); switch (type) { case XR_INO_DIR: if (size <= XFS_DFORK_DSIZE(dino, mp) && dino->di_format != XFS_DINODE_FMT_LOCAL) { do_warn( _("mismatch between format (%d) and size (%" PRId64 ") in directory ino %" PRIu64 "\n"), dino->di_format, size, lino); return 1; } if (size > XFS_DIR2_LEAF_OFFSET) { do_warn( _("directory inode %" PRIu64 " has bad size %" PRId64 "\n"), lino, size); return 1; } break; case XR_INO_SYMLINK: if (process_symlink_extlist(mp, lino, dino)) { do_warn(_("bad data fork in symlink %" PRIu64 "\n"), lino); return 1; } break; case XR_INO_CHRDEV: /* fall through to FIFO case ... */ case XR_INO_BLKDEV: /* fall through to FIFO case ... */ case XR_INO_SOCK: /* fall through to FIFO case ... */ case XR_INO_MOUNTPOINT: /* fall through to FIFO case ... */ case XR_INO_FIFO: if (process_misc_ino_types(mp, dino, lino, type)) return 1; break; case XR_INO_RTDATA: /* * if we have no realtime blocks, any inode claiming * to be a real-time file is bogus */ if (mp->m_sb.sb_rblocks == 0) { do_warn( _("found inode %" PRIu64 " claiming to be a real-time file\n"), lino); return 1; } break; case XR_INO_RTBITMAP: if (size != (__int64_t)mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize) { do_warn( _("realtime bitmap inode %" PRIu64 " has bad size %" PRId64 " (should be %" PRIu64 ")\n"), lino, size, (__int64_t) mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize); return 1; } break; case XR_INO_RTSUM: if (size != mp->m_rsumsize) { do_warn( _("realtime summary inode %" PRIu64 " has bad size %" PRId64 " (should be %d)\n"), lino, size, mp->m_rsumsize); return 1; } break; default: break; } return 0; } /* * check for illegal values of forkoff */ static int process_check_inode_forkoff( xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t lino) { if (dino->di_forkoff == 0) return 0; switch (dino->di_format) { case XFS_DINODE_FMT_DEV: if (dino->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3)) { do_warn( _("bad attr fork offset %d in dev inode %" PRIu64 ", should be %d\n"), dino->di_forkoff, lino, (int)(roundup(sizeof(xfs_dev_t), 8) >> 3)); return 1; } break; case XFS_DINODE_FMT_LOCAL: /* fall through ... */ case XFS_DINODE_FMT_EXTENTS: /* fall through ... */ case XFS_DINODE_FMT_BTREE: if (dino->di_forkoff >= (XFS_LITINO(mp, dino->di_version) >> 3)) { do_warn( _("bad attr fork offset %d in inode %" PRIu64 ", max=%d\n"), dino->di_forkoff, lino, XFS_LITINO(mp, dino->di_version) >> 3); return 1; } break; default: do_error(_("unexpected inode format %d\n"), dino->di_format); break; } return 0; } /* * Updates the inodes block and extent counts if they are wrong */ static int process_inode_blocks_and_extents( xfs_dinode_t *dino, xfs_rfsblock_t nblocks, __uint64_t nextents, __uint64_t anextents, xfs_ino_t lino, int *dirty) { if (nblocks != be64_to_cpu(dino->di_nblocks)) { if (!no_modify) { do_warn( _("correcting nblocks for inode %" PRIu64 ", was %llu - counted %" PRIu64 "\n"), lino, (unsigned long long) be64_to_cpu(dino->di_nblocks), nblocks); dino->di_nblocks = cpu_to_be64(nblocks); *dirty = 1; } else { do_warn( _("bad nblocks %llu for inode %" PRIu64 ", would reset to %" PRIu64 "\n"), (unsigned long long) be64_to_cpu(dino->di_nblocks), lino, nblocks); } } if (nextents > MAXEXTNUM) { do_warn( _("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"), nextents, lino); return 1; } if (nextents != be32_to_cpu(dino->di_nextents)) { if (!no_modify) { do_warn( _("correcting nextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"), lino, be32_to_cpu(dino->di_nextents), nextents); dino->di_nextents = cpu_to_be32(nextents); *dirty = 1; } else { do_warn( _("bad nextents %d for inode %" PRIu64 ", would reset to %" PRIu64 "\n"), be32_to_cpu(dino->di_nextents), lino, nextents); } } if (anextents > MAXAEXTNUM) { do_warn( _("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"), anextents, lino); return 1; } if (anextents != be16_to_cpu(dino->di_anextents)) { if (!no_modify) { do_warn( _("correcting anextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"), lino, be16_to_cpu(dino->di_anextents), anextents); dino->di_anextents = cpu_to_be16(anextents); *dirty = 1; } else { do_warn( _("bad anextents %d for inode %" PRIu64 ", would reset to %" PRIu64 "\n"), be16_to_cpu(dino->di_anextents), lino, anextents); } } /* * We are comparing different units here, but that's fine given that * an extent has to have at least a block in it. */ if (nblocks < nextents + anextents) { do_warn( _("nblocks (%" PRIu64 ") smaller than nextents for inode %" PRIu64 "\n"), nblocks, lino); return 1; } return 0; } /* * check data fork -- if it's bad, clear the inode */ static int process_inode_data_fork( xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t ino, xfs_dinode_t *dino, int type, int *dirty, xfs_rfsblock_t *totblocks, __uint64_t *nextents, blkmap_t **dblkmap, int check_dups) { xfs_ino_t lino = XFS_AGINO_TO_INO(mp, agno, ino); int err = 0; int nex; /* * extent count on disk is only valid for positive values. The kernel * uses negative values in memory. hence if we see negative numbers * here, trash it! */ nex = be32_to_cpu(dino->di_nextents); if (nex < 0) *nextents = 1; else *nextents = nex; if (*nextents > be64_to_cpu(dino->di_nblocks)) *nextents = 1; if (dino->di_format != XFS_DINODE_FMT_LOCAL && type != XR_INO_RTDATA) *dblkmap = blkmap_alloc(*nextents, XFS_DATA_FORK); *nextents = 0; switch (dino->di_format) { case XFS_DINODE_FMT_LOCAL: err = process_lclinode(mp, agno, ino, dino, XFS_DATA_FORK); *totblocks = 0; break; case XFS_DINODE_FMT_EXTENTS: err = process_exinode(mp, agno, ino, dino, type, dirty, totblocks, nextents, dblkmap, XFS_DATA_FORK, check_dups); break; case XFS_DINODE_FMT_BTREE: err = process_btinode(mp, agno, ino, dino, type, dirty, totblocks, nextents, dblkmap, XFS_DATA_FORK, check_dups); break; case XFS_DINODE_FMT_DEV: /* fall through */ err = 0; break; default: do_error(_("unknown format %d, ino %" PRIu64 " (mode = %d)\n"), dino->di_format, lino, be16_to_cpu(dino->di_mode)); } if (err) { do_warn(_("bad data fork in inode %" PRIu64 "\n"), lino); if (!no_modify) { *dirty += clear_dinode(mp, dino, lino); ASSERT(*dirty > 0); } return 1; } if (check_dups) { /* * if check_dups was non-zero, we have to * re-process data fork to set bitmap since the * bitmap wasn't set the first time through */ switch (dino->di_format) { case XFS_DINODE_FMT_LOCAL: err = process_lclinode(mp, agno, ino, dino, XFS_DATA_FORK); break; case XFS_DINODE_FMT_EXTENTS: err = process_exinode(mp, agno, ino, dino, type, dirty, totblocks, nextents, dblkmap, XFS_DATA_FORK, 0); break; case XFS_DINODE_FMT_BTREE: err = process_btinode(mp, agno, ino, dino, type, dirty, totblocks, nextents, dblkmap, XFS_DATA_FORK, 0); break; case XFS_DINODE_FMT_DEV: /* fall through */ err = 0; break; default: do_error(_("unknown format %d, ino %" PRIu64 " (mode = %d)\n"), dino->di_format, lino, be16_to_cpu(dino->di_mode)); } if (no_modify && err != 0) return 1; ASSERT(err == 0); } return 0; } /* * Process extended attribute fork in inode */ static int process_inode_attr_fork( xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t ino, xfs_dinode_t *dino, int type, int *dirty, xfs_rfsblock_t *atotblocks, __uint64_t *anextents, int check_dups, int extra_attr_check, int *retval) { xfs_ino_t lino = XFS_AGINO_TO_INO(mp, agno, ino); blkmap_t *ablkmap = NULL; int repair = 0; int err; if (!XFS_DFORK_Q(dino)) { *anextents = 0; if (dino->di_aformat != XFS_DINODE_FMT_EXTENTS) { do_warn(_("bad attribute format %d in inode %" PRIu64 ", "), dino->di_aformat, lino); if (!no_modify) { do_warn(_("resetting value\n")); dino->di_aformat = XFS_DINODE_FMT_EXTENTS; *dirty = 1; } else do_warn(_("would reset value\n")); } return 0; } *anextents = be16_to_cpu(dino->di_anextents); if (*anextents > be64_to_cpu(dino->di_nblocks)) *anextents = 1; switch (dino->di_aformat) { case XFS_DINODE_FMT_LOCAL: *anextents = 0; *atotblocks = 0; err = process_lclinode(mp, agno, ino, dino, XFS_ATTR_FORK); break; case XFS_DINODE_FMT_EXTENTS: ablkmap = blkmap_alloc(*anextents, XFS_ATTR_FORK); *anextents = 0; err = process_exinode(mp, agno, ino, dino, type, dirty, atotblocks, anextents, &ablkmap, XFS_ATTR_FORK, check_dups); break; case XFS_DINODE_FMT_BTREE: ablkmap = blkmap_alloc(*anextents, XFS_ATTR_FORK); *anextents = 0; err = process_btinode(mp, agno, ino, dino, type, dirty, atotblocks, anextents, &ablkmap, XFS_ATTR_FORK, check_dups); break; default: do_warn(_("illegal attribute format %d, ino %" PRIu64 "\n"), dino->di_aformat, lino); err = 1; break; } if (err) { /* * clear the attribute fork if necessary. we can't * clear the inode because we've already put the * inode space info into the blockmap. * * XXX - put the inode onto the "move it" list and * log the the attribute scrubbing */ do_warn(_("bad attribute fork in inode %" PRIu64), lino); if (!no_modify) { if (delete_attr_ok) { do_warn(_(", clearing attr fork\n")); *dirty += clear_dinode_attr(mp, dino, lino); dino->di_aformat = XFS_DINODE_FMT_LOCAL; } else { do_warn("\n"); *dirty += clear_dinode(mp, dino, lino); } ASSERT(*dirty > 0); } else { do_warn(_(", would clear attr fork\n")); } *atotblocks = 0; *anextents = 0; blkmap_free(ablkmap); *retval = 1; return delete_attr_ok ? 0 : 1; } if (check_dups) { switch (dino->di_aformat) { case XFS_DINODE_FMT_LOCAL: err = process_lclinode(mp, agno, ino, dino, XFS_ATTR_FORK); break; case XFS_DINODE_FMT_EXTENTS: err = process_exinode(mp, agno, ino, dino, type, dirty, atotblocks, anextents, &ablkmap, XFS_ATTR_FORK, 0); break; case XFS_DINODE_FMT_BTREE: err = process_btinode(mp, agno, ino, dino, type, dirty, atotblocks, anextents, &ablkmap, XFS_ATTR_FORK, 0); break; default: do_error(_("illegal attribute fmt %d, ino %" PRIu64 "\n"), dino->di_aformat, lino); } if (no_modify && err != 0) { blkmap_free(ablkmap); return 1; } ASSERT(err == 0); } /* * do attribute semantic-based consistency checks now */ /* get this only in phase 3, not in both phase 3 and 4 */ if (extra_attr_check && process_attributes(mp, lino, dino, ablkmap, &repair)) { do_warn( _("problem with attribute contents in inode %" PRIu64 "\n"), lino); if (!repair) { /* clear attributes if not done already */ if (!no_modify) { *dirty += clear_dinode_attr(mp, dino, lino); dino->di_aformat = XFS_DINODE_FMT_LOCAL; } else { do_warn(_("would clear attr fork\n")); } *atotblocks = 0; *anextents = 0; } else { *dirty = 1; /* it's been repaired */ } } blkmap_free(ablkmap); return 0; } /* * check nlinks feature, if it's a version 1 inode, * just leave nlinks alone. even if it's set wrong, * it'll be reset when read in. */ static int process_check_inode_nlink_version( xfs_dinode_t *dino, xfs_ino_t lino) { int dirty = 0; /* * if it's a version 2 inode, it should have a zero * onlink field, so clear it. */ if (dino->di_version > 1 && dino->di_onlink != 0) { if (!no_modify) { do_warn( _("clearing obsolete nlink field in version 2 inode %" PRIu64 ", was %d, now 0\n"), lino, be16_to_cpu(dino->di_onlink)); dino->di_onlink = 0; dirty = 1; } else { do_warn( _("would clear obsolete nlink field in version 2 inode %" PRIu64 ", currently %d\n"), lino, be16_to_cpu(dino->di_onlink)); } } return dirty; } /* * returns 0 if the inode is ok, 1 if the inode is corrupt * check_dups can be set to 1 *only* when called by the * first pass of the duplicate block checking of phase 4. * *dirty is set > 0 if the dinode has been altered and * needs to be written out. * * for detailed, info, look at process_dinode() comments. */ static int process_dinode_int(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_agnumber_t agno, xfs_agino_t ino, int was_free, /* 1 if inode is currently free */ int *dirty, /* out == > 0 if inode is now dirty */ int *used, /* out == 1 if inode is in use */ int verify_mode, /* 1 == verify but don't modify inode */ int uncertain, /* 1 == inode is uncertain */ int ino_discovery, /* 1 == check dirs for unknown inodes */ int check_dups, /* 1 == check if inode claims * duplicate blocks */ int extra_attr_check, /* 1 == do attribute format and value checks */ int *isa_dir, /* out == 1 if inode is a directory */ xfs_ino_t *parent) /* out -- parent if ino is a dir */ { xfs_rfsblock_t totblocks = 0; xfs_rfsblock_t atotblocks = 0; int di_mode; int type; int retval = 0; __uint64_t nextents; __uint64_t anextents; xfs_ino_t lino; const int is_free = 0; const int is_used = 1; blkmap_t *dblkmap = NULL; *dirty = *isa_dir = 0; *used = is_used; type = XR_INO_UNKNOWN; lino = XFS_AGINO_TO_INO(mp, agno, ino); di_mode = be16_to_cpu(dino->di_mode); /* * if in verify mode, don't modify the inode. * * if correcting, reset stuff that has known values * * if in uncertain mode, be silent on errors since we're * trying to find out if these are inodes as opposed * to assuming that they are. Just return the appropriate * return code in that case. * * If uncertain is set, verify_mode MUST be set. */ ASSERT(uncertain == 0 || verify_mode != 0); /* * This is the only valid point to check the CRC; after this we may have * made changes which invalidate it, and the CRC is only updated again * when it gets written out. * * Of course if we make any modifications after this, the inode gets * rewritten, and the CRC is updated automagically. */ if (xfs_sb_version_hascrc(&mp->m_sb) && !libxfs_verify_cksum((char *)dino, mp->m_sb.sb_inodesize, XFS_DINODE_CRC_OFF)) { retval = 1; if (!uncertain) do_warn(_("bad CRC for inode %" PRIu64 "%c"), lino, verify_mode ? '\n' : ','); if (!verify_mode) { if (!no_modify) { do_warn(_(" will rewrite\n")); *dirty = 1; } else do_warn(_(" would rewrite\n")); } } if (be16_to_cpu(dino->di_magic) != XFS_DINODE_MAGIC) { retval = 1; if (!uncertain) do_warn(_("bad magic number 0x%x on inode %" PRIu64 "%c"), be16_to_cpu(dino->di_magic), lino, verify_mode ? '\n' : ','); if (!verify_mode) { if (!no_modify) { do_warn(_(" resetting magic number\n")); dino->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); *dirty = 1; } else do_warn(_(" would reset magic number\n")); } } if (!libxfs_dinode_good_version(mp, dino->di_version)) { retval = 1; if (!uncertain) do_warn(_("bad version number 0x%x on inode %" PRIu64 "%c"), (__s8)dino->di_version, lino, verify_mode ? '\n' : ','); if (!verify_mode) { if (!no_modify) { do_warn(_(" resetting version number\n")); dino->di_version = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 2; *dirty = 1; } else do_warn(_(" would reset version number\n")); } } /* * We don't bother checking the CRC here - we cannot guarantee that when * we are called here that the inode has not already been modified in * memory and hence invalidated the CRC. */ if (xfs_sb_version_hascrc(&mp->m_sb)) { if (be64_to_cpu(dino->di_ino) != lino) { if (!uncertain) do_warn( _("inode identifier %llu mismatch on inode %" PRIu64 "\n"), be64_to_cpu(dino->di_ino), lino); if (verify_mode) return 1; goto clear_bad_out; } if (platform_uuid_compare(&dino->di_uuid, &mp->m_sb.sb_meta_uuid)) { if (!uncertain) do_warn( _("UUID mismatch on inode %" PRIu64 "\n"), lino); if (verify_mode) return 1; goto clear_bad_out; } } /* * blow out of here if the inode size is < 0 */ if ((xfs_fsize_t)be64_to_cpu(dino->di_size) < 0) { if (!uncertain) do_warn( _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), (__int64_t)be64_to_cpu(dino->di_size), lino); if (verify_mode) return 1; goto clear_bad_out; } /* * if not in verify mode, check to sii if the inode and imap * agree that the inode is free */ if (!verify_mode && di_mode == 0) { /* * was_free value is not meaningful if we're in verify mode */ if (was_free) { /* * easy case, inode free -- inode and map agree, clear * it just in case to ensure that format, etc. are * set correctly */ if (!no_modify) *dirty += clear_dinode(mp, dino, lino); *used = is_free; return 0; } /* * the inode looks free but the map says it's in use. * clear the inode just to be safe and mark the inode * free. */ do_warn( _("imap claims a free inode %" PRIu64 " is in use, "), lino); if (!no_modify) { do_warn(_("correcting imap and clearing inode\n")); *dirty += clear_dinode(mp, dino, lino); retval = 1; } else do_warn(_("would correct imap and clear inode\n")); *used = is_free; return retval; } /* * because of the lack of any write ordering guarantee, it's * possible that the core got updated but the forks didn't. * so rather than be ambitious (and probably incorrect), * if there's an inconsistency, we get conservative and * just pitch the file. blow off checking formats of * free inodes since technically any format is legal * as we reset the inode when we re-use it. */ if (di_mode != 0 && check_dinode_mode_format(dino) != 0) { if (!uncertain) do_warn( _("bad inode format in inode %" PRIu64 "\n"), lino); if (verify_mode) return 1; goto clear_bad_out; } /* * check that we only have valid flags set, and those that are set make * sense. */ if (dino->di_flags) { uint16_t flags = be16_to_cpu(dino->di_flags); if (flags & ~XFS_DIFLAG_ANY) { if (!uncertain) { do_warn( _("Bad flags set in inode %" PRIu64 "\n"), lino); } flags &= XFS_DIFLAG_ANY; } if (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT)) { /* need an rt-dev! */ if (!rt_name) { if (!uncertain) { do_warn( _("inode %" PRIu64 " has RT flag set but there is no RT device\n"), lino); } flags &= ~(XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT); } } if (flags & XFS_DIFLAG_NEWRTBM) { /* must be a rt bitmap inode */ if (lino != mp->m_sb.sb_rbmino) { if (!uncertain) { do_warn( _("inode %" PRIu64 " not rt bitmap\n"), lino); } flags &= ~XFS_DIFLAG_NEWRTBM; } } if (flags & (XFS_DIFLAG_RTINHERIT | XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS)) { /* must be a directory */ if (di_mode && !S_ISDIR(di_mode)) { if (!uncertain) { do_warn( _("directory flags set on non-directory inode %" PRIu64 "\n" ), lino); } flags &= ~(XFS_DIFLAG_RTINHERIT | XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS); } } if (flags & (XFS_DIFLAG_REALTIME | FS_XFLAG_EXTSIZE)) { /* must be a file */ if (di_mode && !S_ISREG(di_mode)) { if (!uncertain) { do_warn( _("file flags set on non-file inode %" PRIu64 "\n"), lino); } flags &= ~(XFS_DIFLAG_REALTIME | FS_XFLAG_EXTSIZE); } } if (!verify_mode && flags != be16_to_cpu(dino->di_flags)) { if (!no_modify) { do_warn(_("fixing bad flags.\n")); dino->di_flags = cpu_to_be16(flags); *dirty = 1; } else do_warn(_("would fix bad flags.\n")); } } /* * check that we only have valid flags2 set, and those that are set make * sense. */ if (dino->di_version >= 3) { uint16_t flags = be16_to_cpu(dino->di_flags); uint64_t flags2 = be64_to_cpu(dino->di_flags2); if (flags2 & ~XFS_DIFLAG2_ANY) { if (!uncertain) { do_warn( _("Bad flags2 set in inode %" PRIu64 "\n"), lino); } flags2 &= XFS_DIFLAG2_ANY; } if ((flags2 & XFS_DIFLAG2_REFLINK) && !xfs_sb_version_hasreflink(&mp->m_sb)) { if (!uncertain) { do_warn( _("inode %" PRIu64 " is marked reflinked but file system does not support reflink\n"), lino); } goto clear_bad_out; } if (flags2 & XFS_DIFLAG2_REFLINK) { /* must be a file */ if (di_mode && !S_ISREG(di_mode)) { if (!uncertain) { do_warn( _("reflink flag set on non-file inode %" PRIu64 "\n"), lino); } goto clear_bad_out; } } if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) { if (!uncertain) { do_warn( _("Cannot have a reflinked realtime inode %" PRIu64 "\n"), lino); } goto clear_bad_out; } if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) && !xfs_sb_version_hasreflink(&mp->m_sb)) { if (!uncertain) { do_warn( _("inode %" PRIu64 " has CoW extent size hint but file system does not support reflink\n"), lino); } flags2 &= ~XFS_DIFLAG2_COWEXTSIZE; } if (flags2 & XFS_DIFLAG2_COWEXTSIZE) { /* must be a directory or file */ if (di_mode && !S_ISDIR(di_mode) && !S_ISREG(di_mode)) { if (!uncertain) { do_warn( _("CoW extent size flag set on non-file, non-directory inode %" PRIu64 "\n" ), lino); } flags2 &= ~XFS_DIFLAG2_COWEXTSIZE; } } if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) && (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) { if (!uncertain) { do_warn( _("Cannot have CoW extent size hint on a realtime inode %" PRIu64 "\n"), lino); } flags2 &= ~XFS_DIFLAG2_COWEXTSIZE; } if (!verify_mode && flags2 != be64_to_cpu(dino->di_flags2)) { if (!no_modify) { do_warn(_("fixing bad flags2.\n")); dino->di_flags2 = cpu_to_be64(flags2); *dirty = 1; } else do_warn(_("would fix bad flags2.\n")); } } if (verify_mode) return retval; /* * clear the next unlinked field if necessary on a good * inode only during phase 4 -- when checking for inodes * referencing duplicate blocks. then it's safe because * we've done the inode discovery and have found all the inodes * we're going to find. check_dups is set to 1 only during * phase 4. Ugly. */ if (check_dups && !no_modify) *dirty += clear_dinode_unlinked(mp, dino); /* set type and map type info */ switch (di_mode & S_IFMT) { case S_IFDIR: type = XR_INO_DIR; *isa_dir = 1; break; case S_IFREG: if (be16_to_cpu(dino->di_flags) & XFS_DIFLAG_REALTIME) type = XR_INO_RTDATA; else if (lino == mp->m_sb.sb_rbmino) type = XR_INO_RTBITMAP; else if (lino == mp->m_sb.sb_rsumino) type = XR_INO_RTSUM; else type = XR_INO_DATA; break; case S_IFLNK: type = XR_INO_SYMLINK; break; case S_IFCHR: type = XR_INO_CHRDEV; break; case S_IFBLK: type = XR_INO_BLKDEV; break; case S_IFSOCK: type = XR_INO_SOCK; break; case S_IFIFO: type = XR_INO_FIFO; break; default: do_warn(_("bad inode type %#o inode %" PRIu64 "\n"), di_mode & S_IFMT, lino); goto clear_bad_out; } /* * type checks for superblock inodes */ if (process_check_sb_inodes(mp, dino, lino, &type, dirty) != 0) goto clear_bad_out; /* * only regular files with REALTIME or EXTSIZE flags set can have * extsize set, or directories with EXTSZINHERIT. */ if (be32_to_cpu(dino->di_extsize) != 0) { if ((type == XR_INO_RTDATA) || (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) & XFS_DIFLAG_EXTSZINHERIT)) || (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) & XFS_DIFLAG_EXTSIZE))) { /* s'okay */ ; } else { do_warn( _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "), be32_to_cpu(dino->di_extsize), lino); if (!no_modify) { do_warn(_("resetting to zero\n")); dino->di_extsize = 0; *dirty = 1; } else do_warn(_("would reset to zero\n")); } } /* * Only (regular files and directories) with COWEXTSIZE flags * set can have extsize set. */ if (dino->di_version >= 3 && be32_to_cpu(dino->di_cowextsize) != 0) { if ((type == XR_INO_DIR || type == XR_INO_DATA) && (be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_COWEXTSIZE)) { /* s'okay */ ; } else { do_warn( _("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "), be32_to_cpu(dino->di_cowextsize), lino); if (!no_modify) { do_warn(_("resetting to zero\n")); dino->di_cowextsize = 0; *dirty = 1; } else do_warn(_("would reset to zero\n")); } } /* * general size/consistency checks: */ if (process_check_inode_sizes(mp, dino, lino, type) != 0) goto clear_bad_out; /* * check for illegal values of forkoff */ if (process_check_inode_forkoff(mp, dino, lino) != 0) goto clear_bad_out; /* * record the state of the reflink flag */ if (collect_rmaps) record_inode_reflink_flag(mp, dino, agno, ino, lino); /* * check data fork -- if it's bad, clear the inode */ if (process_inode_data_fork(mp, agno, ino, dino, type, dirty, &totblocks, &nextents, &dblkmap, check_dups) != 0) goto bad_out; /* * check attribute fork if necessary. attributes are * always stored in the regular filesystem. */ if (process_inode_attr_fork(mp, agno, ino, dino, type, dirty, &atotblocks, &anextents, check_dups, extra_attr_check, &retval)) goto bad_out; /* * enforce totblocks is 0 for misc types */ if (process_misc_ino_types_blocks(totblocks, lino, type)) goto clear_bad_out; /* * correct space counters if required */ if (process_inode_blocks_and_extents(dino, totblocks + atotblocks, nextents, anextents, lino, dirty) != 0) goto clear_bad_out; /* * do any semantic type-based checking here */ switch (type) { case XR_INO_DIR: if (process_dir2(mp, lino, dino, ino_discovery, dirty, "", parent, dblkmap)) { do_warn( _("problem with directory contents in inode %" PRIu64 "\n"), lino); goto clear_bad_out; } break; case XR_INO_SYMLINK: if (process_symlink(mp, lino, dino, dblkmap) != 0) { do_warn( _("problem with symbolic link in inode %" PRIu64 "\n"), lino); goto clear_bad_out; } break; default: break; } blkmap_free(dblkmap); /* * check nlinks feature, if it's a version 1 inode, * just leave nlinks alone. even if it's set wrong, * it'll be reset when read in. */ *dirty += process_check_inode_nlink_version(dino, lino); return retval; clear_bad_out: if (!no_modify) { *dirty += clear_dinode(mp, dino, lino); ASSERT(*dirty > 0); } bad_out: *used = is_free; *isa_dir = 0; blkmap_free(dblkmap); return 1; } /* * returns 1 if inode is used, 0 if free. * performs any necessary salvaging actions. * note that we leave the generation count alone * because nothing we could set it to would be * guaranteed to be correct so the best guess for * the correct value is just to leave it alone. * * The trick is detecting empty files. For those, * the core and the forks should all be in the "empty" * or zero-length state -- a zero or possibly minimum length * (in the case of dirs) extent list -- although inline directories * and symlinks might be handled differently. So it should be * possible to sanity check them against each other. * * If the forks are an empty extent list though, then forget it. * The file is toast anyway since we can't recover its storage. * * Parameters: * Ins: * mp -- mount structure * dino -- pointer to on-disk inode structure * agno/ino -- inode numbers * free -- whether the map thinks the inode is free (1 == free) * ino_discovery -- whether we should examine directory * contents to discover new inodes * check_dups -- whether we should check to see if the * inode references duplicate blocks * if so, we compare the inode's claimed * blocks against the contents of the * duplicate extent list but we don't * set the bitmap. If not, we set the * bitmap and try and detect multiply * claimed blocks using the bitmap. * Outs: * dirty -- whether we changed the inode (1 == yes) * used -- 1 if the inode is used, 0 if free. In no modify * mode, whether the inode should be used or free * isa_dir -- 1 if the inode is a directory, 0 if not. In * no modify mode, if the inode would be a dir or not. * * Return value -- 0 if the inode is good, 1 if it is/was corrupt */ int process_dinode( xfs_mount_t *mp, xfs_dinode_t *dino, xfs_agnumber_t agno, xfs_agino_t ino, int was_free, int *dirty, int *used, int ino_discovery, int check_dups, int extra_attr_check, int *isa_dir, xfs_ino_t *parent) { const int verify_mode = 0; const int uncertain = 0; #ifdef XR_INODE_TRACE fprintf(stderr, _("processing inode %d/%d\n"), agno, ino); #endif return process_dinode_int(mp, dino, agno, ino, was_free, dirty, used, verify_mode, uncertain, ino_discovery, check_dups, extra_attr_check, isa_dir, parent); } /* * a more cursory check, check inode core, *DON'T* check forks * this basically just verifies whether the inode is an inode * and whether or not it has been totally trashed. returns 0 * if the inode passes the cursory sanity check, 1 otherwise. */ int verify_dinode( xfs_mount_t *mp, xfs_dinode_t *dino, xfs_agnumber_t agno, xfs_agino_t ino) { xfs_ino_t parent; int used = 0; int dirty = 0; int isa_dir = 0; const int verify_mode = 1; const int check_dups = 0; const int ino_discovery = 0; const int uncertain = 0; return process_dinode_int(mp, dino, agno, ino, 0, &dirty, &used, verify_mode, uncertain, ino_discovery, check_dups, 0, &isa_dir, &parent); } /* * like above only for inode on the uncertain list. it sets * the uncertain flag which makes process_dinode_int quieter. * returns 0 if the inode passes the cursory sanity check, 1 otherwise. */ int verify_uncertain_dinode( xfs_mount_t *mp, xfs_dinode_t *dino, xfs_agnumber_t agno, xfs_agino_t ino) { xfs_ino_t parent; int used = 0; int dirty = 0; int isa_dir = 0; const int verify_mode = 1; const int check_dups = 0; const int ino_discovery = 0; const int uncertain = 1; return process_dinode_int(mp, dino, agno, ino, 0, &dirty, &used, verify_mode, uncertain, ino_discovery, check_dups, 0, &isa_dir, &parent); } xfsprogs-4.9.0+nmu1ubuntu2/repair/dinode.h0000644000000000000000000000527013063067172015374 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XR_DINODE_H #define _XR_DINODE_H struct blkmap; struct prefetch_args; int verify_agbno(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t agbno); int verify_dfsbno(xfs_mount_t *mp, xfs_fsblock_t fsbno); void convert_extent( xfs_bmbt_rec_t *rp, xfs_fileoff_t *op, /* starting offset (blockno in file) */ xfs_fsblock_t *sp, /* starting block (fs blockno) */ xfs_filblks_t *cp, /* blockcount */ int *fp); /* extent flag */ int process_bmbt_reclist(xfs_mount_t *mp, xfs_bmbt_rec_t *rp, int *numrecs, int type, xfs_ino_t ino, xfs_rfsblock_t *tot, struct blkmap **blkmapp, __uint64_t *first_key, __uint64_t *last_key, int whichfork); int scan_bmbt_reclist( xfs_mount_t *mp, xfs_bmbt_rec_t *rp, int *numrecs, int type, xfs_ino_t ino, xfs_rfsblock_t *tot, int whichfork); void update_rootino(xfs_mount_t *mp); int process_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_agnumber_t agno, xfs_agino_t ino, int was_free, int *dirty, int *used, int check_dirs, int check_dups, int extra_attr_check, int *isa_dir, xfs_ino_t *parent); int verify_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_agnumber_t agno, xfs_agino_t ino); int verify_uncertain_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_agnumber_t agno, xfs_agino_t ino); int verify_inum(xfs_mount_t *mp, xfs_ino_t ino); int verify_aginum(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t agino); int process_uncertain_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno); void process_aginodes(xfs_mount_t *mp, struct prefetch_args *pf_args, xfs_agnumber_t agno, int check_dirs, int check_dups, int extra_attr_check); void check_uncertain_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno); struct xfs_buf * get_agino_buf( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino, struct xfs_dinode **dipp); void dinode_bmbt_translation_init(void); char * get_forkname(int whichfork); #endif /* _XR_DINODE_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/dir2.c0000644000000000000000000011256313063067173014772 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "incore.h" #include "err_protos.h" #include "dinode.h" #include "dir2.h" #include "bmap.h" #include "da_util.h" #include "prefetch.h" #include "progress.h" /* * Known bad inode list. These are seen when the leaf and node * block linkages are incorrect. */ typedef struct dir2_bad { xfs_ino_t ino; struct dir2_bad *next; } dir2_bad_t; static dir2_bad_t *dir2_bad_list; static void dir2_add_badlist( xfs_ino_t ino) { dir2_bad_t *l; if ((l = malloc(sizeof(dir2_bad_t))) == NULL) { do_error( _("malloc failed (%zu bytes) dir2_add_badlist:ino %" PRIu64 "\n"), sizeof(dir2_bad_t), ino); exit(1); } l->next = dir2_bad_list; dir2_bad_list = l; l->ino = ino; } int dir2_is_badino( xfs_ino_t ino) { dir2_bad_t *l; for (l = dir2_bad_list; l; l = l->next) if (l->ino == ino) return 1; return 0; } /* * Fix up a shortform directory which was in long form (i8count set) * and is now in short form (i8count clear). * Return pointer to the end of the data when done. */ void process_sf_dir2_fixi8( struct xfs_mount *mp, struct xfs_dir2_sf_hdr *sfp, xfs_dir2_sf_entry_t **next_sfep) { xfs_ino_t ino; struct xfs_dir2_sf_hdr *newsfp; xfs_dir2_sf_entry_t *newsfep; struct xfs_dir2_sf_hdr *oldsfp; xfs_dir2_sf_entry_t *oldsfep; int oldsize; newsfp = sfp; oldsize = (intptr_t)*next_sfep - (intptr_t)sfp; oldsfp = malloc(oldsize); if (oldsfp == NULL) { do_error(_("couldn't malloc dir2 shortform copy\n")); exit(1); } memmove(oldsfp, newsfp, oldsize); newsfp->count = oldsfp->count; newsfp->i8count = 0; ino = M_DIROPS(mp)->sf_get_parent_ino(sfp); M_DIROPS(mp)->sf_put_parent_ino(newsfp, ino); oldsfep = xfs_dir2_sf_firstentry(oldsfp); newsfep = xfs_dir2_sf_firstentry(newsfp); while ((int)((char *)oldsfep - (char *)oldsfp) < oldsize) { newsfep->namelen = oldsfep->namelen; xfs_dir2_sf_put_offset(newsfep, xfs_dir2_sf_get_offset(oldsfep)); memmove(newsfep->name, oldsfep->name, newsfep->namelen); ino = M_DIROPS(mp)->sf_get_ino(oldsfp, oldsfep); M_DIROPS(mp)->sf_put_ino(newsfp, newsfep, ino); oldsfep = M_DIROPS(mp)->sf_nextentry(oldsfp, oldsfep); newsfep = M_DIROPS(mp)->sf_nextentry(newsfp, newsfep); } *next_sfep = newsfep; free(oldsfp); } /* * Regenerate legal (minimal) offsets for the shortform directory. */ static void process_sf_dir2_fixoff( xfs_mount_t *mp, xfs_dinode_t *dip) { int i; int offset; xfs_dir2_sf_entry_t *sfep; struct xfs_dir2_sf_hdr *sfp; sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); sfep = xfs_dir2_sf_firstentry(sfp); offset = M_DIROPS(mp)->data_first_offset; for (i = 0; i < sfp->count; i++) { xfs_dir2_sf_put_offset(sfep, offset); offset += M_DIROPS(mp)->data_entsize(sfep->namelen); sfep = M_DIROPS(mp)->sf_nextentry(sfp, sfep); } } /* * this routine performs inode discovery and tries to fix things * in place. available redundancy -- inode data size should match * used directory space in inode. * a non-zero return value means the directory is bogus and should be blasted. */ /* ARGSUSED */ static int process_sf_dir2( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, int ino_discovery, int *dino_dirty, /* out - 1 if dinode buffer dirty */ char *dirname, /* directory pathname */ xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */ int *repair) /* out - 1 if dir was fixed up */ { int bad_offset; int bad_sfnamelen; int i; int i8; __int64_t ino_dir_size; int ino_off; ino_tree_node_t *irec_p; int junkit; char *junkreason = NULL; xfs_ino_t lino; int max_size; char name[MAXNAMELEN + 1]; int namelen; xfs_dir2_sf_entry_t *next_sfep; int num_entries; int offset; struct xfs_dir2_sf_hdr *sfp; xfs_dir2_sf_entry_t *sfep; int tmp_elen; int tmp_len; xfs_dir2_sf_entry_t *tmp_sfep; xfs_ino_t zero = 0; sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); max_size = XFS_DFORK_DSIZE(dip, mp); num_entries = sfp->count; ino_dir_size = be64_to_cpu(dip->di_size); offset = M_DIROPS(mp)->data_first_offset; bad_offset = *repair = 0; ASSERT(ino_dir_size <= max_size); /* * Initialize i8 based on size of parent inode number. */ i8 = (M_DIROPS(mp)->sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM); /* * check for bad entry count */ if (num_entries * M_DIROPS(mp)->sf_entsize(sfp, 1) + xfs_dir2_sf_hdr_size(0) > max_size || num_entries == 0) num_entries = 0xFF; /* * run through entries, stop at first bad entry, don't need * to check for .. since that's encoded in its own field */ next_sfep = xfs_dir2_sf_firstentry(sfp); for (i = 0; i < num_entries && ino_dir_size > (char *)next_sfep - (char *)sfp; i++) { tmp_sfep = NULL; sfep = next_sfep; junkit = 0; bad_sfnamelen = 0; lino = M_DIROPS(mp)->sf_get_ino(sfp, sfep); /* * if entry points to self, junk it since only '.' or '..' * should do that and shortform dirs don't contain either * entry. if inode number is invalid, trash entry. * if entry points to special inodes, trash it. * if inode is unknown but number is valid, * add it to the list of uncertain inodes. don't * have to worry about an entry pointing to a * deleted lost+found inode because the entry was * deleted at the same time that the inode was cleared. */ if (lino == ino) { junkit = 1; junkreason = _("current"); } else if (verify_inum(mp, lino)) { junkit = 1; junkreason = _("invalid"); } else if (lino == mp->m_sb.sb_rbmino) { junkit = 1; junkreason = _("realtime bitmap"); } else if (lino == mp->m_sb.sb_rsumino) { junkit = 1; junkreason = _("realtime summary"); } else if (lino == mp->m_sb.sb_uquotino) { junkit = 1; junkreason = _("user quota"); } else if (lino == mp->m_sb.sb_gquotino) { junkit = 1; junkreason = _("group quota"); } else if (lino == mp->m_sb.sb_pquotino) { junkit = 1; junkreason = _("project quota"); } else if ((irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino), XFS_INO_TO_AGINO(mp, lino))) != NULL) { /* * if inode is marked free and we're in inode * discovery mode, leave the entry alone for now. * if the inode turns out to be used, we'll figure * that out when we scan it. If the inode really * is free, we'll hit this code again in phase 4 * after we've finished inode discovery and blow * out the entry then. */ ino_off = XFS_INO_TO_AGINO(mp, lino) - irec_p->ino_startnum; ASSERT(is_inode_confirmed(irec_p, ino_off)); if (is_inode_free(irec_p, ino_off) && !ino_discovery) { junkit = 1; junkreason = _("free"); } } else if (ino_discovery) { /* * put the inode on the uncertain list. we'll * pull the inode off the list and check it later. * if the inode turns out be bogus, we'll delete * this entry in phase 6. */ add_inode_uncertain(mp, lino, 0); } else { /* * blow the entry out. we know about all * undiscovered entries now (past inode discovery * phase) so this is clearly a bogus entry. */ junkit = 1; junkreason = _("non-existent"); } namelen = sfep->namelen; if (junkit) do_warn( _("entry \"%*.*s\" in shortform directory %" PRIu64 " references %s inode %" PRIu64 "\n"), namelen, namelen, sfep->name, ino, junkreason, lino); /* is dir namelen 0 or does this entry extend past dir size? */ if (namelen == 0) { junkreason = _("is zero length"); bad_sfnamelen = 1; } else if ((intptr_t) sfep - (intptr_t) sfp + M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen) > ino_dir_size) { junkreason = _("extends past end of dir"); bad_sfnamelen = 1; } if (bad_sfnamelen) { do_warn( _("entry #%d %s in shortform dir %" PRIu64), i, junkreason, ino); if (!no_modify) do_warn(_(", junking %d entries\n"), num_entries - i); else do_warn(_(", would junk %d entries\n"), num_entries - i); /* * don't process the rest of the directory, * break out of processing loop */ break; } /* * check for illegal chars in name. * no need to check for bad length because * the length value is stored in a byte * so it can't be too big, it can only wrap */ if (namecheck((char *)&sfep->name[0], namelen)) { /* * junk entry */ do_warn( _("entry contains illegal character in shortform dir %" PRIu64 "\n"), ino); junkit = 1; } if (xfs_dir2_sf_get_offset(sfep) < offset) { do_warn( _("entry contains offset out of order in shortform dir %" PRIu64 "\n"), ino); bad_offset = 1; } offset = xfs_dir2_sf_get_offset(sfep) + M_DIROPS(mp)->data_entsize(namelen); /* * junk the entry by copying up the rest of the * fork over the current entry and decrementing * the entry count. if we're in no_modify mode, * just issue the warning instead. then continue * the loop with the next_sfep pointer set to the * correct place in the fork and other counters * properly set to reflect the deletion if it * happened. */ if (junkit) { memmove(name, sfep->name, namelen); name[namelen] = '\0'; if (!no_modify) { tmp_elen = M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen); be64_add_cpu(&dip->di_size, -tmp_elen); ino_dir_size -= tmp_elen; tmp_sfep = (xfs_dir2_sf_entry_t *) ((intptr_t) sfep + tmp_elen); tmp_len = max_size - ((intptr_t) tmp_sfep - (intptr_t) sfp); memmove(sfep, tmp_sfep, tmp_len); sfp->count -= 1; num_entries--; memset((void *) ((intptr_t) sfep + tmp_len), 0, tmp_elen); /* * reset the tmp value to the current * pointer so we'll process the entry * we just moved up */ tmp_sfep = sfep; /* * WARNING: drop the index i by one * so it matches the decremented count * for accurate comparisons later */ i--; *dino_dirty = 1; *repair = 1; do_warn( _("junking entry \"%s\" in directory inode %" PRIu64 "\n"), name, ino); } else { do_warn( _("would have junked entry \"%s\" in directory inode %" PRIu64 "\n"), name, ino); } } else if (lino > XFS_DIR2_MAX_SHORT_INUM) i8++; /* * go onto next entry unless we've just junked an * entry in which the current entry pointer points * to an unprocessed entry. have to take into zero-len * entries into account in no modify mode since we * calculate size based on next_sfep. */ next_sfep = (tmp_sfep == NULL) ? (xfs_dir2_sf_entry_t *) ((intptr_t) sfep + ((!bad_sfnamelen) ? M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen) : M_DIROPS(mp)->sf_entsize(sfp, namelen))) : tmp_sfep; } /* sync up sizes and entry counts */ if (sfp->count != i) { if (no_modify) { do_warn( _("would have corrected entry count in directory %" PRIu64 " from %d to %d\n"), ino, sfp->count, i); } else { do_warn( _("corrected entry count in directory %" PRIu64 ", was %d, now %d\n"), ino, sfp->count, i); sfp->count = i; *dino_dirty = 1; *repair = 1; } } if (sfp->i8count != i8) { if (no_modify) { do_warn( _("would have corrected i8 count in directory %" PRIu64 " from %d to %d\n"), ino, sfp->i8count, i8); } else { do_warn( _("corrected i8 count in directory %" PRIu64 ", was %d, now %d\n"), ino, sfp->i8count, i8); if (i8 == 0) process_sf_dir2_fixi8(mp, sfp, &next_sfep); else sfp->i8count = i8; *dino_dirty = 1; *repair = 1; } } if ((intptr_t)next_sfep - (intptr_t)sfp != ino_dir_size) { if (no_modify) { do_warn( _("would have corrected directory %" PRIu64 " size from %" PRId64 " to %" PRIdPTR "\n"), ino, ino_dir_size, (intptr_t)next_sfep - (intptr_t)sfp); } else { do_warn( _("corrected directory %" PRIu64 " size, was %" PRId64 ", now %" PRIdPTR "\n"), ino, ino_dir_size, (intptr_t)next_sfep - (intptr_t)sfp); dip->di_size = cpu_to_be64( (intptr_t)next_sfep - (intptr_t)sfp); *dino_dirty = 1; *repair = 1; } } if (offset + (sfp->count + 2) * sizeof(xfs_dir2_leaf_entry_t) + sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize) { do_warn(_("directory %" PRIu64 " offsets too high\n"), ino); bad_offset = 1; } if (bad_offset) { if (no_modify) { do_warn( _("would have corrected entry offsets in directory %" PRIu64 "\n"), ino); } else { do_warn( _("corrected entry offsets in directory %" PRIu64 "\n"), ino); process_sf_dir2_fixoff(mp, dip); *dino_dirty = 1; *repair = 1; } } /* * check parent (..) entry */ *parent = M_DIROPS(mp)->sf_get_parent_ino(sfp); /* * if parent entry is bogus, null it out. we'll fix it later . */ if (verify_inum(mp, *parent)) { do_warn( _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "), *parent, ino); *parent = NULLFSINO; if (!no_modify) { do_warn(_("clearing inode number\n")); M_DIROPS(mp)->sf_put_parent_ino(sfp, zero); *dino_dirty = 1; *repair = 1; } else { do_warn(_("would clear inode number\n")); } } else if (ino == mp->m_sb.sb_rootino && ino != *parent) { /* * root directories must have .. == . */ if (!no_modify) { do_warn( _("corrected root directory %" PRIu64 " .. entry, was %" PRIu64 ", now %" PRIu64 "\n"), ino, *parent, ino); *parent = ino; M_DIROPS(mp)->sf_put_parent_ino(sfp, ino); *dino_dirty = 1; *repair = 1; } else { do_warn( _("would have corrected root directory %" PRIu64 " .. entry from %" PRIu64" to %" PRIu64 "\n"), ino, *parent, ino); } } else if (ino == *parent && ino != mp->m_sb.sb_rootino) { /* * likewise, non-root directories can't have .. pointing * to . */ *parent = NULLFSINO; do_warn( _("bad .. entry in directory inode %" PRIu64 ", points to self, "), ino); if (!no_modify) { do_warn(_("clearing inode number\n")); M_DIROPS(mp)->sf_put_parent_ino(sfp, zero); *dino_dirty = 1; *repair = 1; } else { do_warn(_("would clear inode number\n")); } } return(0); } /* * Process one directory data block. */ /* ARGSUSED */ static int process_dir2_data( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, int ino_discovery, char *dirname, /* directory pathname */ xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */ struct xfs_buf *bp, int *dot, /* out - 1 if there is a dot, else 0 */ int *dotdot, /* out - 1 if there's a dotdot, else 0 */ xfs_dablk_t da_bno, char *endptr, int *dirty) { int badbest; xfs_dir2_data_free_t *bf; int clearino; char *clearreason = NULL; struct xfs_dir2_data_hdr *d; xfs_dir2_data_entry_t *dep; xfs_dir2_data_free_t *dfp; xfs_dir2_data_unused_t *dup; int freeseen; int i; int ino_off; ino_tree_node_t *irec_p; int junkit; int lastfree; int nm_illegal; char *ptr; xfs_ino_t ent_ino; d = bp->b_addr; bf = M_DIROPS(mp)->data_bestfree_p(d); ptr = (char *)M_DIROPS(mp)->data_entry_p(d); badbest = lastfree = freeseen = 0; if (be16_to_cpu(bf[0].length) == 0) { badbest |= be16_to_cpu(bf[0].offset) != 0; freeseen |= 1 << 0; } if (be16_to_cpu(bf[1].length) == 0) { badbest |= be16_to_cpu(bf[1].offset) != 0; freeseen |= 1 << 1; } if (be16_to_cpu(bf[2].length) == 0) { badbest |= be16_to_cpu(bf[2].offset) != 0; freeseen |= 1 << 2; } badbest |= be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length); badbest |= be16_to_cpu(bf[1].length) < be16_to_cpu(bf[2].length); while (ptr < endptr) { dup = (xfs_dir2_data_unused_t *)ptr; /* * If it's unused, look for the space in the bestfree table. * If we find it, account for that, else make sure it doesn't * need to be there. */ if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { if (ptr + be16_to_cpu(dup->length) > endptr || be16_to_cpu(dup->length) == 0 || (be16_to_cpu(dup->length) & (XFS_DIR2_DATA_ALIGN - 1))) break; if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) != (char *)dup - (char *)d) break; badbest |= lastfree != 0; dfp = xfs_dir2_data_freefind(d, bf, dup); if (dfp) { i = dfp - bf; badbest |= (freeseen & (1 << i)) != 0; freeseen |= 1 << i; } else badbest |= be16_to_cpu(dup->length) > be16_to_cpu(bf[2].length); ptr += be16_to_cpu(dup->length); lastfree = 1; continue; } dep = (xfs_dir2_data_entry_t *)ptr; if (ptr + M_DIROPS(mp)->data_entsize(dep->namelen) > endptr) break; if (be16_to_cpu(*M_DIROPS(mp)->data_entry_tag_p(dep)) != (char *)dep - (char *)d) break; ptr += M_DIROPS(mp)->data_entsize(dep->namelen); lastfree = 0; } /* * Dropped out before we processed everything, give up. * Phase 6 will kill this block if we don't kill the inode. */ if (ptr != endptr) { do_warn(_("corrupt block %u in directory inode %" PRIu64 "\n"), da_bno, ino); if (!no_modify) do_warn(_("\twill junk block\n")); else do_warn(_("\twould junk block\n")); return 1; } ptr = (char *)M_DIROPS(mp)->data_entry_p(d); /* * Process the entries now. */ while (ptr < endptr) { dup = (xfs_dir2_data_unused_t *)ptr; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { ptr += be16_to_cpu(dup->length); continue; } dep = (xfs_dir2_data_entry_t *)ptr; ent_ino = be64_to_cpu(dep->inumber); clearino = 1; clearreason = NULL; /* * We may have to blow out an entry because of bad inode * numbers. Do NOT touch the name until after we've computed * the hashvalue and done a namecheck() on the name. * * Conditions must either set clearino to zero or set * clearreason why it's being cleared. */ if (!ino_discovery && dep->name[0] == '/') { /* * Don't do a damned thing. We already found this * (or did it ourselves) during phase 3. */ clearino = 0; } else if (verify_inum(mp, ent_ino)) { /* * Bad inode number. Clear the inode number and the * entry will get removed later. We don't trash the * directory since it's still structurally intact. */ clearreason = _("invalid"); } else if (ent_ino == mp->m_sb.sb_rbmino) { clearreason = _("realtime bitmap"); } else if (ent_ino == mp->m_sb.sb_rsumino) { clearreason = _("realtime summary"); } else if (ent_ino == mp->m_sb.sb_uquotino) { clearreason = _("user quota"); } else if (ent_ino == mp->m_sb.sb_gquotino) { clearreason = _("group quota"); } else if (ent_ino == mp->m_sb.sb_pquotino) { clearreason = _("project quota"); } else { irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, ent_ino), XFS_INO_TO_AGINO(mp, ent_ino)); if (irec_p == NULL) { if (ino_discovery) { add_inode_uncertain(mp, ent_ino, 0); clearino = 0; } else clearreason = _("non-existent"); } else { /* * Inode recs should have only confirmed * inodes in them. */ ino_off = XFS_INO_TO_AGINO(mp, ent_ino) - irec_p->ino_startnum; ASSERT(is_inode_confirmed(irec_p, ino_off)); /* * If inode is marked free and we're in inode * discovery mode, leave the entry alone for * now. If the inode turns out to be used, * we'll figure that out when we scan it. * If the inode really is free, we'll hit this * code again in phase 4 after we've finished * inode discovery and blow out the entry then. */ if (!ino_discovery && is_inode_free(irec_p, ino_off)) clearreason = _("free"); else clearino = 0; } } ASSERT((clearino == 0 && clearreason == NULL) || (clearino != 0 && clearreason != NULL)); if (clearino) do_warn( _("entry \"%*.*s\" at block %d offset %" PRIdPTR " in directory inode %" PRIu64 " references %s inode %" PRIu64 "\n"), dep->namelen, dep->namelen, dep->name, da_bno, (intptr_t)ptr - (intptr_t)d, ino, clearreason, ent_ino); /* * We have a special dot & dotdot fixer-upper below which can * sort out the proper inode number, so don't clear it. */ if ((dep->namelen == 1 && dep->name[0] == '.') || (dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.')) { clearino = 0; clearreason = NULL; } /* * If the name length is 0 (illegal) make it 1 and blast * the entry. */ if (dep->namelen == 0) { do_warn( _("entry at block %u offset %" PRIdPTR " in directory inode %" PRIu64 "has 0 namelength\n"), da_bno, (intptr_t)ptr - (intptr_t)d, ino); if (!no_modify) dep->namelen = 1; clearino = 1; } /* * If needed to clear the inode number, do it now. */ if (clearino) { if (!no_modify) { do_warn( _("\tclearing inode number in entry at offset %" PRIdPTR "...\n"), (intptr_t)ptr - (intptr_t)d); dep->name[0] = '/'; *dirty = 1; } else { do_warn( _("\twould clear inode number in entry at offset %" PRIdPTR "...\n"), (intptr_t)ptr - (intptr_t)d); } } /* * Only complain about illegal names in phase 3 (when inode * discovery is turned on). Otherwise, we'd complain a lot * during phase 4. */ junkit = dep->name[0] == '/'; nm_illegal = namecheck((char *)dep->name, dep->namelen); if (ino_discovery && nm_illegal) { do_warn( _("entry at block %u offset %" PRIdPTR " in directory inode %" PRIu64 " has illegal name \"%*.*s\": "), da_bno, (intptr_t)ptr - (intptr_t)d, ino, dep->namelen, dep->namelen, dep->name); junkit = 1; } /* * Ensure we write back bad entries for later processing */ if (!no_modify && dep->name[0] == '/') { *dirty = 1; junkit = 0; } /* * Special .. entry processing. */ if (dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.') { if (!*dotdot) { (*dotdot)++; *parent = ent_ino; /* * What if .. == .? Legal only in the root * inode. Blow out entry and set parent to * NULLFSINO otherwise. */ if (ino == ent_ino && ino != mp->m_sb.sb_rootino) { *parent = NULLFSINO; do_warn( _("bad .. entry in directory inode %" PRIu64 ", points to self: "), ino); junkit = 1; } /* * We have to make sure that . == .. in the * root inode. */ else if (ino != ent_ino && ino == mp->m_sb.sb_rootino) { do_warn( _("bad .. entry in root directory inode %" PRIu64 ", was %" PRIu64 ": "), ino, ent_ino); if (!no_modify) { do_warn(_("correcting\n")); dep->inumber = cpu_to_be64(ino); *dirty = 1; } else { do_warn(_("would correct\n")); } *parent = ino; } } /* * Can't fix the directory unless we know which .. * entry is the right one. Both have valid inode * numbers or we wouldn't be here. So since both * seem equally valid, trash this one. */ else { do_warn( _("multiple .. entries in directory inode %" PRIu64 ": "), ino); junkit = 1; } } /* * Special . entry processing. */ else if (dep->namelen == 1 && dep->name[0] == '.') { if (!*dot) { (*dot)++; if (ent_ino != ino) { do_warn( _("bad . entry in directory inode %" PRIu64 ", was %" PRIu64 ": "), ino, ent_ino); if (!no_modify) { do_warn(_("correcting\n")); dep->inumber = cpu_to_be64(ino); *dirty = 1; } else { do_warn(_("would correct\n")); } } } else { do_warn( _("multiple . entries in directory inode %" PRIu64 ": "), ino); junkit = 1; } } /* * All other entries -- make sure only . references self. */ else if (ent_ino == ino) { do_warn( _("entry \"%*.*s\" in directory inode %" PRIu64 " points to self: "), dep->namelen, dep->namelen, dep->name, ino); junkit = 1; } /* * Clear junked entries. */ if (junkit) { if (!no_modify) { dep->name[0] = '/'; *dirty = 1; do_warn(_("clearing entry\n")); } else { do_warn(_("would clear entry\n")); } } /* * Advance to the next entry. */ ptr += M_DIROPS(mp)->data_entsize(dep->namelen); } /* * Check the bestfree table. */ if (freeseen != 7 || badbest) { do_warn( _("bad bestfree table in block %u in directory inode %" PRIu64 ": "), da_bno, ino); if (!no_modify) { do_warn(_("repairing table\n")); libxfs_dir2_data_freescan(mp->m_dir_geo, M_DIROPS(mp), d, &i); *dirty = 1; } else { do_warn(_("would repair table\n")); } } return 0; } /* * Process a block-format directory. */ /* ARGSUSED */ static int process_block_dir2( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, int ino_discovery, int *dino_dirty, /* out - 1 if dinode buffer dirty */ char *dirname, /* directory pathname */ xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */ blkmap_t *blkmap, int *dot, /* out - 1 if there is a dot, else 0 */ int *dotdot, /* out - 1 if there's a dotdot, else 0 */ int *repair) /* out - 1 if something was fixed */ { struct xfs_dir2_data_hdr *block; xfs_dir2_leaf_entry_t *blp; bmap_ext_t *bmp; struct xfs_buf *bp; xfs_dir2_block_tail_t *btp; int nex; int rval; bmap_ext_t lbmp; int dirty = 0; *repair = *dot = *dotdot = 0; *parent = NULLFSINO; nex = blkmap_getn(blkmap, mp->m_dir_geo->datablk, mp->m_dir_geo->fsbcount, &bmp, &lbmp); if (nex == 0) { do_warn( _("block %u for directory inode %" PRIu64 " is missing\n"), mp->m_dir_geo->datablk, ino); return 1; } bp = da_read_buf(mp, nex, bmp, &xfs_dir3_block_buf_ops); if (bmp != &lbmp) free(bmp); if (bp == NULL) { do_warn( _("can't read block %u for directory inode %" PRIu64 "\n"), mp->m_dir_geo->datablk, ino); return 1; } /* * Verify the block */ block = bp->b_addr; if (!(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC)) do_warn( _("bad directory block magic # %#x in block %u for directory inode %" PRIu64 "\n"), be32_to_cpu(block->magic), mp->m_dir_geo->datablk, ino); /* * process the data area * this also checks & fixes the bestfree */ btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); blp = xfs_dir2_block_leaf_p(btp); /* * Don't let this go past the end of the block. */ if ((char *)blp > (char *)btp) blp = (xfs_dir2_leaf_entry_t *)btp; rval = process_dir2_data(mp, ino, dip, ino_discovery, dirname, parent, bp, dot, dotdot, mp->m_dir_geo->datablk, (char *)blp, &dirty); /* If block looks ok but CRC didn't match, make sure to recompute it. */ if (!rval && bp->b_error == -EFSBADCRC) dirty = 1; if (dirty && !no_modify) { *repair = 1; libxfs_writebuf(bp, 0); } else libxfs_putbuf(bp); return rval; } /* * Validates leaf contents, node format directories only. * magic number and sibling pointers checked by caller. * Returns 0 if block is ok, 1 if the block is bad. * Looking for: out of order hash values, bad stale counts. */ static int process_leaf_block_dir2( xfs_mount_t *mp, xfs_dir2_leaf_t *leaf, xfs_dablk_t da_bno, xfs_ino_t ino, xfs_dahash_t last_hashval, xfs_dahash_t *next_hashval) { int i; int stale; struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf); ents = M_DIROPS(mp)->leaf_ents_p(leaf); for (i = stale = 0; i < leafhdr.count; i++) { if ((char *)&ents[i] >= (char *)leaf + mp->m_dir_geo->blksize) { do_warn( _("bad entry count in block %u of directory inode %" PRIu64 "\n"), da_bno, ino); return 1; } if (be32_to_cpu(ents[i].address) == XFS_DIR2_NULL_DATAPTR) stale++; else if (be32_to_cpu(ents[i].hashval) < last_hashval) { do_warn( _("bad hash ordering in block %u of directory inode %" PRIu64 "\n"), da_bno, ino); return 1; } *next_hashval = last_hashval = be32_to_cpu(ents[i].hashval); } if (stale != leafhdr.stale) { do_warn( _("bad stale count in block %u of directory inode %" PRIu64 "\n"), da_bno, ino); return 1; } return 0; } /* * Returns 0 if the directory is ok, 1 if it has to be rebuilt. */ static int process_leaf_level_dir2( xfs_mount_t *mp, da_bt_cursor_t *da_cursor, int *repair) { bmap_ext_t *bmp; struct xfs_buf *bp; int buf_dirty; xfs_dahash_t current_hashval; xfs_dablk_t da_bno; xfs_dahash_t greatest_hashval; xfs_ino_t ino; xfs_dir2_leaf_t *leaf; int nex; xfs_dablk_t prev_bno; bmap_ext_t lbmp; struct xfs_dir3_icleaf_hdr leafhdr; da_bno = da_cursor->level[0].bno; ino = da_cursor->ino; prev_bno = 0; bmp = NULL; current_hashval = 0; greatest_hashval = 0; buf_dirty = 0; do { nex = blkmap_getn(da_cursor->blkmap, da_bno, mp->m_dir_geo->fsbcount, &bmp, &lbmp); /* * Directory code uses 0 as the NULL block pointer since 0 * is the root block and no directory block pointer can point * to the root block of the btree. */ ASSERT(da_bno != 0); if (nex == 0) { do_warn( _("can't map block %u for directory inode %" PRIu64 "\n"), da_bno, ino); goto error_out; } bp = da_read_buf(mp, nex, bmp, &xfs_dir3_leafn_buf_ops); if (bmp != &lbmp) free(bmp); bmp = NULL; if (bp == NULL) { do_warn( _("can't read file block %u for directory inode %" PRIu64 "\n"), da_bno, ino); goto error_out; } leaf = bp->b_addr; M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf); /* * Check magic number for leaf directory btree block. */ if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC)) { do_warn( _("bad directory leaf magic # %#x for directory inode %" PRIu64 " block %u\n"), leafhdr.magic, ino, da_bno); libxfs_putbuf(bp); goto error_out; } buf_dirty = 0; /* * For each block, process the block, verify its path, * then get next block. Update cursor values along the way. */ if (process_leaf_block_dir2(mp, leaf, da_bno, ino, current_hashval, &greatest_hashval)) { libxfs_putbuf(bp); goto error_out; } /* * Index can be set to hdr.count so match the indices of the * interior blocks -- which at the end of the block will point * to 1 after the final real entry in the block. */ da_cursor->level[0].hashval = greatest_hashval; da_cursor->level[0].bp = bp; da_cursor->level[0].bno = da_bno; da_cursor->level[0].index = leafhdr.count; da_cursor->level[0].dirty = buf_dirty; if (leafhdr.back != prev_bno) { do_warn( _("bad sibling back pointer for block %u in directory inode %" PRIu64 "\n"), da_bno, ino); libxfs_putbuf(bp); goto error_out; } prev_bno = da_bno; da_bno = leafhdr.forw; if (da_bno != 0) { if (verify_da_path(mp, da_cursor, 0, XFS_DATA_FORK)) { libxfs_putbuf(bp); goto error_out; } } current_hashval = greatest_hashval; /* * If block looks ok but CRC didn't match, make sure to * recompute it. */ if (!no_modify && bp->b_error == -EFSBADCRC) buf_dirty = 1; ASSERT(buf_dirty == 0 || (buf_dirty && !no_modify)); if (buf_dirty && !no_modify) { *repair = 1; libxfs_writebuf(bp, 0); } else libxfs_putbuf(bp); } while (da_bno != 0); if (verify_final_da_path(mp, da_cursor, 0, XFS_DATA_FORK)) { /* * Verify the final path up (right-hand-side) if still ok. */ do_warn(_("bad hash path in directory %" PRIu64 "\n"), ino); goto error_out; } /* * Redundant but just for testing. */ release_da_cursor(mp, da_cursor, 0); return 0; error_out: /* * Release all buffers holding interior btree blocks. */ err_release_da_cursor(mp, da_cursor, 0); if (bmp && (bmp != &lbmp)) free(bmp); return 1; } /* * Return 1 if the directory's leaf/node space is corrupted and * needs to be rebuilt, 0 if it's ok. */ static int process_node_dir2( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, blkmap_t *blkmap, int *repair) { xfs_dablk_t bno; da_bt_cursor_t da_cursor; /* * Try again -- traverse down left-side of tree until we hit the * left-most leaf block setting up the btree cursor along the way. * Then walk the leaf blocks left-to-right, calling a parent * verification routine each time we traverse a block. */ memset(&da_cursor, 0, sizeof(da_cursor)); da_cursor.ino = ino; da_cursor.dip = dip; da_cursor.blkmap = blkmap; /* * Now process interior node. */ if (traverse_int_dablock(mp, &da_cursor, &bno, XFS_DATA_FORK) == 0) return 1; /* * Skip directories with a root marked XFS_DIR2_LEAFN_MAGIC */ if (bno == 0) { release_da_cursor(mp, &da_cursor, 0); return 0; } else { /* * Now pass cursor and bno into leaf-block processing routine. * The leaf dir level routine checks the interior paths up to * the root including the final right-most path. */ return process_leaf_level_dir2(mp, &da_cursor, repair); } } /* * Process leaf and node directories. * Process the data blocks then, if it's a node directory, check * the consistency of those blocks. */ static int process_leaf_node_dir2( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, int ino_discovery, char *dirname, /* directory pathname */ xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */ blkmap_t *blkmap, int *dot, /* out - 1 if there is a dot, else 0 */ int *dotdot, /* out - 1 if there's a dotdot, else 0 */ int *repair, /* out - 1 if something was fixed */ int isnode) /* node directory not leaf */ { bmap_ext_t *bmp; struct xfs_buf *bp; struct xfs_dir2_data_hdr *data; xfs_fileoff_t dbno; int good; int i; xfs_fileoff_t ndbno; int nex; int t; bmap_ext_t lbmp; int dirty = 0; *repair = *dot = *dotdot = good = 0; *parent = NULLFSINO; ndbno = NULLFILEOFF; while ((dbno = blkmap_next_off(blkmap, ndbno, &t)) < mp->m_dir_geo->leafblk) { nex = blkmap_getn(blkmap, dbno, mp->m_dir_geo->fsbcount, &bmp, &lbmp); /* Advance through map to last dfs block in this dir block */ ndbno = dbno; while (ndbno < dbno + mp->m_dir_geo->fsbcount - 1) { ndbno = blkmap_next_off(blkmap, ndbno, &t); } if (nex == 0) { do_warn( _("block %" PRIu64 " for directory inode %" PRIu64 " is missing\n"), dbno, ino); continue; } bp = da_read_buf(mp, nex, bmp, &xfs_dir3_data_buf_ops); if (bmp != &lbmp) free(bmp); if (bp == NULL) { do_warn( _("can't read block %" PRIu64 " for directory inode %" PRIu64 "\n"), dbno, ino); continue; } data = bp->b_addr; if (!(be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC || be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC)) do_warn( _("bad directory block magic # %#x in block %" PRIu64 " for directory inode %" PRIu64 "\n"), be32_to_cpu(data->magic), dbno, ino); i = process_dir2_data(mp, ino, dip, ino_discovery, dirname, parent, bp, dot, dotdot, (xfs_dablk_t)dbno, (char *)data + mp->m_dir_geo->blksize, &dirty); if (i == 0) { good++; /* Maybe just CRC is wrong. Make sure we correct it. */ if (bp->b_error == -EFSBADCRC) dirty = 1; } if (dirty && !no_modify) { *repair = 1; libxfs_writebuf(bp, 0); } else libxfs_putbuf(bp); } if (good == 0) return 1; if (!isnode) return 0; if (dir2_is_badino(ino)) return 0; if (process_node_dir2(mp, ino, dip, blkmap, repair)) dir2_add_badlist(ino); return 0; } /* * Returns 1 if things are bad (directory needs to be junked) * and 0 if things are ok. If ino_discovery is 1, add unknown * inodes to uncertain inode list. */ int process_dir2( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, int ino_discovery, int *dino_dirty, char *dirname, xfs_ino_t *parent, blkmap_t *blkmap) { int dot; int dotdot; xfs_fileoff_t last; int repair; int res; *parent = NULLFSINO; dot = dotdot = 0; last = 0; /* * branch off depending on the type of inode. This routine * is only called ONCE so all the subordinate routines will * fix '.' and junk '..' if they're bogus. */ if (blkmap) last = blkmap_last_off(blkmap); if (be64_to_cpu(dip->di_size) <= XFS_DFORK_DSIZE(dip, mp) && dip->di_format == XFS_DINODE_FMT_LOCAL) { dot = dotdot = 1; res = process_sf_dir2(mp, ino, dip, ino_discovery, dino_dirty, dirname, parent, &repair); } else if (last == mp->m_dir_geo->fsbcount && (dip->di_format == XFS_DINODE_FMT_EXTENTS || dip->di_format == XFS_DINODE_FMT_BTREE)) { res = process_block_dir2(mp, ino, dip, ino_discovery, dino_dirty, dirname, parent, blkmap, &dot, &dotdot, &repair); } else if (last >= mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount && (dip->di_format == XFS_DINODE_FMT_EXTENTS || dip->di_format == XFS_DINODE_FMT_BTREE)) { res = process_leaf_node_dir2(mp, ino, dip, ino_discovery, dirname, parent, blkmap, &dot, &dotdot, &repair, last > mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount); } else { do_warn(_("bad size/format for directory %" PRIu64 "\n"), ino); return 1; } /* * bad . entries in all directories will be fixed up in phase 6 */ if (dot == 0) { do_warn(_("no . entry for directory %" PRIu64 "\n"), ino); } /* * shortform dirs always have a .. entry. .. for all longform * directories will get fixed in phase 6. .. for other shortform * dirs also get fixed there. .. for a shortform root was * fixed in place since we know what it should be */ if (dotdot == 0 && ino != mp->m_sb.sb_rootino) { do_warn(_("no .. entry for directory %" PRIu64 "\n"), ino); } else if (dotdot == 0 && ino == mp->m_sb.sb_rootino) { do_warn(_("no .. entry for root directory %" PRIu64 "\n"), ino); need_root_dotdot = 1; } ASSERT((ino != mp->m_sb.sb_rootino && ino != *parent) || (ino == mp->m_sb.sb_rootino && (ino == *parent || need_root_dotdot == 1))); return res; } xfsprogs-4.9.0+nmu1ubuntu2/repair/dir2.h0000644000000000000000000000217513063067173014774 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XR_DIR2_H #define _XR_DIR2_H struct blkmap; struct bmap_ext; int process_dir2( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, int ino_discovery, int *dirty, char *dirname, xfs_ino_t *parent, struct blkmap *blkmap); void process_sf_dir2_fixi8( struct xfs_mount *mp, struct xfs_dir2_sf_hdr *sfp, xfs_dir2_sf_entry_t **next_sfep); int dir2_is_badino( xfs_ino_t ino); #endif /* _XR_DIR2_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/err_protos.h0000644000000000000000000000221113063067173016321 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* abort, internal error */ void __attribute__((noreturn)) do_abort(char const *, ...) __attribute__((format(printf,1,2))); /* abort, system error */ void __attribute__((noreturn)) do_error(char const *, ...) __attribute__((format(printf,1,2))); /* issue warning */ void do_warn(char const *, ...) __attribute__((format(printf,1,2))); /* issue log message */ void do_log(char const *, ...) __attribute__((format(printf,1,2))); xfsprogs-4.9.0+nmu1ubuntu2/repair/globals.c0000644000000000000000000000142113063067173015543 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #define EXTERN #include "globals.h" xfsprogs-4.9.0+nmu1ubuntu2/repair/globals.h0000644000000000000000000001325713063067172015561 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XFS_REPAIR_GLOBAL_H #define _XFS_REPAIR_GLOBAL_H #ifndef EXTERN #define EXTERN extern #endif /* useful macros */ #define rounddown(x, y) (((x)/(y))*(y)) /* error flags */ #define XR_OK 0 /* good */ #define XR_BAD_MAGIC 1 /* bad magic number */ #define XR_BAD_BLOCKSIZE 2 /* bad block size */ #define XR_BAD_BLOCKLOG 3 /* bad sb_blocklog field */ #define XR_BAD_VERSION 4 /* bad version number */ #define XR_BAD_INPROGRESS 5 /* in progress set */ #define XR_BAD_FS_SIZE_DATA 6 /* ag sizes, number, fs size mismatch */ #define XR_BAD_INO_SIZE_DATA 7 /* bad inode size or perblock fields */ #define XR_BAD_SECT_SIZE_DATA 8 /* bad sector size info */ #define XR_AGF_GEO_MISMATCH 9 /* agf info conflicts with sb */ #define XR_AGI_GEO_MISMATCH 10 /* agf info conflicts with sb */ #define XR_SB_GEO_MISMATCH 11 /* sb geo conflicts with fs sb geo */ #define XR_EOF 12 /* seeked beyond EOF */ #define XR_BAD_RT_GEO_DATA 13 /* realtime geometry inconsistent */ #define XR_BAD_INO_MAX_PCT 14 /* max % of inodes > 100% */ #define XR_BAD_INO_ALIGN 15 /* bad inode alignment value */ #define XR_INSUFF_SEC_SB 16 /* not enough matching secondary sbs */ #define XR_BAD_SB_UNIT 17 /* bad stripe unit */ #define XR_BAD_SB_WIDTH 18 /* bad stripe width */ #define XR_BAD_SVN 19 /* bad shared version number */ #define XR_BAD_CRC 20 /* Bad CRC */ #define XR_BAD_ERR_CODE 21 /* Bad error code */ /* XFS filesystem (il)legal values */ #define XR_LOG2BSIZE_MIN 9 /* min/max fs blocksize (log2) */ #define XR_LOG2BSIZE_MAX 16 /* 2^XR_* == blocksize */ #define NUM_AGH_SECTS 4 /* # of components in an ag header */ /* global variables for xfs_repair */ /* arguments and argument flag variables */ EXTERN char *fs_name; /* name of filesystem */ EXTERN int verbose; /* verbose flag, mostly for debugging */ /* for reading stuff in manually (bypassing libsim) */ EXTERN char *iobuf; /* large buffer */ EXTERN int iobuf_size; EXTERN char *smallbuf; /* small (1-4 page) buffer */ EXTERN int smallbuf_size; EXTERN int sbbuf_size; /* direct I/O info */ EXTERN int minio_align; /* min I/O size and alignment */ EXTERN int mem_align; /* memory alignment */ EXTERN int max_iosize; /* max I/O size */ /* file descriptors */ EXTERN int fs_fd; /* filesystem fd */ /* command-line flags */ EXTERN int verbose; EXTERN int no_modify; EXTERN int dangerously; /* live dangerously ... fix ro mount */ EXTERN int isa_file; EXTERN int zap_log; EXTERN int dumpcore; /* abort, not exit on fatal errs */ EXTERN int delete_attr_ok; /* can clear attrs w/o clearing files */ EXTERN int force_geo; /* can set geo on low confidence info */ EXTERN int assume_xfs; /* assume we have an xfs fs */ EXTERN int pre_65_beta; /* fs was mkfs'ed by a version earlier * than 6.5-beta */ EXTERN char *log_name; /* Name of log device */ EXTERN int log_spec; /* Log dev specified as option */ EXTERN char *rt_name; /* Name of realtime device */ EXTERN int rt_spec; /* Realtime dev specified as option */ EXTERN int convert_lazy_count; /* Convert lazy-count mode on/off */ EXTERN int lazy_count; /* What to set if to if converting */ /* misc status variables */ EXTERN int primary_sb_modified; EXTERN int bad_ino_btree; EXTERN int copied_sunit; EXTERN int fs_is_dirty; /* for hunting down the root inode */ EXTERN int need_root_inode; EXTERN int need_root_dotdot; EXTERN int need_rbmino; EXTERN int need_rsumino; EXTERN int lost_quotas; EXTERN int have_uquotino; EXTERN int have_gquotino; EXTERN int have_pquotino; EXTERN int lost_uquotino; EXTERN int lost_gquotino; EXTERN int lost_pquotino; EXTERN xfs_agino_t first_prealloc_ino; EXTERN xfs_agino_t last_prealloc_ino; EXTERN xfs_agblock_t bnobt_root; EXTERN xfs_agblock_t bcntbt_root; EXTERN xfs_agblock_t inobt_root; /* configuration vars -- fs geometry dependent */ EXTERN int inodes_per_block; EXTERN int inodes_per_cluster; EXTERN unsigned int glob_agcount; EXTERN int chunks_pblock; /* # of 64-ino chunks per allocation */ EXTERN int max_symlink_blocks; EXTERN __int64_t fs_max_file_offset; /* realtime info */ EXTERN xfs_rtword_t *btmcompute; EXTERN xfs_suminfo_t *sumcompute; /* inode tree records have full or partial backptr fields ? */ EXTERN int full_ino_ex_data;/* * if 1, use ino_ex_data_t component * of ino_un union, if 0, use * parent_list_t component. see * incore.h for more details */ #define ORPHANAGE "lost+found" /* superblock counters */ EXTERN __uint64_t sb_icount; /* allocated (made) inodes */ EXTERN __uint64_t sb_ifree; /* free inodes */ EXTERN __uint64_t sb_fdblocks; /* free data blocks */ EXTERN __uint64_t sb_frextents; /* free realtime extents */ /* superblock geometry info */ EXTERN xfs_extlen_t sb_inoalignmt; EXTERN __uint32_t sb_unit; EXTERN __uint32_t sb_width; struct aglock { pthread_mutex_t lock __attribute__((__aligned__(64))); }; EXTERN struct aglock *ag_locks; EXTERN int report_interval; EXTERN __uint64_t *prog_rpt_done; EXTERN int ag_stride; EXTERN int thread_count; #endif /* _XFS_REPAIR_GLOBAL_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/incore.c0000644000000000000000000001644613063067172015413 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "btree.h" #include "globals.h" #include "incore.h" #include "agheader.h" #include "protos.h" #include "err_protos.h" #include "threads.h" /* * The following manages the in-core bitmap of the entire filesystem * using extents in a btree. * * The btree items will point to one of the state values below, * rather than storing the value itself in the pointer. */ static int states[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; static struct btree_root **ag_bmap; static void update_bmap( struct btree_root *bmap, unsigned long offset, xfs_extlen_t blen, void *new_state) { unsigned long end = offset + blen; int *cur_state; unsigned long cur_key; int *next_state; unsigned long next_key; int *prev_state; cur_state = btree_find(bmap, offset, &cur_key); if (!cur_state) return; if (offset == cur_key) { /* if the start is the same as the "item" extent */ if (cur_state == new_state) return; /* * Note: this may be NULL if we are updating the map for * the superblock. */ prev_state = btree_peek_prev(bmap, NULL); next_state = btree_peek_next(bmap, &next_key); if (next_key > end) { /* different end */ if (new_state == prev_state) { /* #1: prev has same state, move offset up */ btree_update_key(bmap, offset, end); return; } /* #4: insert new extent after, update current value */ btree_update_value(bmap, offset, new_state); btree_insert(bmap, end, cur_state); return; } /* same end (and same start) */ if (new_state == next_state) { /* next has same state */ if (new_state == prev_state) { /* #3: merge prev & next */ btree_delete(bmap, offset); btree_delete(bmap, end); return; } /* #8: merge next */ btree_update_value(bmap, offset, new_state); btree_delete(bmap, end); return; } /* same start, same end, next has different state */ if (new_state == prev_state) { /* #5: prev has same state */ btree_delete(bmap, offset); return; } /* #6: update value only */ btree_update_value(bmap, offset, new_state); return; } /* different start, offset is in the middle of "cur" */ prev_state = btree_peek_prev(bmap, NULL); ASSERT(prev_state != NULL); if (prev_state == new_state) return; if (end == cur_key) { /* end is at the same point as the current extent */ if (new_state == cur_state) { /* #7: move next extent down */ btree_update_key(bmap, end, offset); return; } /* #9: different start, same end, add new extent */ btree_insert(bmap, offset, new_state); return; } /* #2: insert an extent into the middle of another extent */ btree_insert(bmap, offset, new_state); btree_insert(bmap, end, prev_state); } void set_bmap_ext( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t blen, int state) { update_bmap(ag_bmap[agno], agbno, blen, &states[state]); } int get_bmap_ext( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_agblock_t maxbno, xfs_extlen_t *blen) { int *statep; unsigned long key; statep = btree_find(ag_bmap[agno], agbno, &key); if (!statep) return -1; if (key == agbno) { if (blen) { if (!btree_peek_next(ag_bmap[agno], &key)) return -1; *blen = MIN(maxbno, key) - agbno; } return *statep; } statep = btree_peek_prev(ag_bmap[agno], NULL); if (!statep) return -1; if (blen) *blen = MIN(maxbno, key) - agbno; return *statep; } static uint64_t *rt_bmap; static size_t rt_bmap_size; /* block records fit into __uint64_t's units */ #define XR_BB_UNIT 64 /* number of bits/unit */ #define XR_BB 4 /* bits per block record */ #define XR_BB_NUM (XR_BB_UNIT/XR_BB) /* number of records per unit */ #define XR_BB_MASK 0xF /* block record mask */ /* * these work in real-time extents (e.g. fsbno == rt extent number) */ int get_rtbmap( xfs_rtblock_t bno) { return (*(rt_bmap + bno / XR_BB_NUM) >> ((bno % XR_BB_NUM) * XR_BB)) & XR_BB_MASK; } void set_rtbmap( xfs_rtblock_t bno, int state) { *(rt_bmap + bno / XR_BB_NUM) = ((*(rt_bmap + bno / XR_BB_NUM) & (~((__uint64_t) XR_BB_MASK << ((bno % XR_BB_NUM) * XR_BB)))) | (((__uint64_t) state) << ((bno % XR_BB_NUM) * XR_BB))); } static void reset_rt_bmap(void) { if (rt_bmap) memset(rt_bmap, 0x22, rt_bmap_size); /* XR_E_FREE */ } static void init_rt_bmap( xfs_mount_t *mp) { if (mp->m_sb.sb_rextents == 0) return; rt_bmap_size = roundup(mp->m_sb.sb_rextents / (NBBY / XR_BB), sizeof(__uint64_t)); rt_bmap = memalign(sizeof(__uint64_t), rt_bmap_size); if (!rt_bmap) { do_error( _("couldn't allocate realtime block map, size = %" PRIu64 "\n"), mp->m_sb.sb_rextents); return; } } static void free_rt_bmap(xfs_mount_t *mp) { free(rt_bmap); rt_bmap = NULL; } void reset_bmaps(xfs_mount_t *mp) { xfs_agnumber_t agno; xfs_agblock_t ag_size; int ag_hdr_block; ag_hdr_block = howmany(4 * mp->m_sb.sb_sectsize, mp->m_sb.sb_blocksize); ag_size = mp->m_sb.sb_agblocks; for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { if (agno == mp->m_sb.sb_agcount - 1) ag_size = (xfs_extlen_t)(mp->m_sb.sb_dblocks - (xfs_rfsblock_t)mp->m_sb.sb_agblocks * agno); #ifdef BTREE_STATS if (btree_find(ag_bmap[agno], 0, NULL)) { printf("ag_bmap[%d] btree stats:\n", i); btree_print_stats(ag_bmap[agno], stdout); } #endif /* * We always insert an item for the first block having a * given state. So the code below means: * * block 0..ag_hdr_block-1: XR_E_INUSE_FS * ag_hdr_block..ag_size: XR_E_UNKNOWN * ag_size... XR_E_BAD_STATE */ btree_clear(ag_bmap[agno]); btree_insert(ag_bmap[agno], 0, &states[XR_E_INUSE_FS]); btree_insert(ag_bmap[agno], ag_hdr_block, &states[XR_E_UNKNOWN]); btree_insert(ag_bmap[agno], ag_size, &states[XR_E_BAD_STATE]); } if (mp->m_sb.sb_logstart != 0) { set_bmap_ext(XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart), XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart), mp->m_sb.sb_logblocks, XR_E_INUSE_FS); } reset_rt_bmap(); } void init_bmaps(xfs_mount_t *mp) { xfs_agnumber_t i; ag_bmap = calloc(mp->m_sb.sb_agcount, sizeof(struct btree_root *)); if (!ag_bmap) do_error(_("couldn't allocate block map btree roots\n")); ag_locks = calloc(mp->m_sb.sb_agcount, sizeof(struct aglock)); if (!ag_locks) do_error(_("couldn't allocate block map locks\n")); for (i = 0; i < mp->m_sb.sb_agcount; i++) { btree_init(&ag_bmap[i]); pthread_mutex_init(&ag_locks[i].lock, NULL); } init_rt_bmap(mp); reset_bmaps(mp); } void free_bmaps(xfs_mount_t *mp) { xfs_agnumber_t i; for (i = 0; i < mp->m_sb.sb_agcount; i++) btree_destroy(ag_bmap[i]); free(ag_bmap); ag_bmap = NULL; free_rt_bmap(mp); } xfsprogs-4.9.0+nmu1ubuntu2/repair/incore.h0000644000000000000000000004511213063067172015410 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef XFS_REPAIR_INCORE_H #define XFS_REPAIR_INCORE_H #include "avl.h" /* * contains definition information. implementation (code) * is spread out in separate files. */ /* * block map -- track state of each filesystem block. */ void init_bmaps(xfs_mount_t *mp); void reset_bmaps(xfs_mount_t *mp); void free_bmaps(xfs_mount_t *mp); void set_bmap_ext(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t blen, int state); int get_bmap_ext(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_agblock_t maxbno, xfs_extlen_t *blen); void set_rtbmap(xfs_rtblock_t bno, int state); int get_rtbmap(xfs_rtblock_t bno); static inline void set_bmap(xfs_agnumber_t agno, xfs_agblock_t agbno, int state) { set_bmap_ext(agno, agbno, 1, state); } static inline int get_bmap(xfs_agnumber_t agno, xfs_agblock_t agbno) { return get_bmap_ext(agno, agbno, agbno + 1, NULL); } /* * extent tree definitions * right now, there are 3 trees per AG, a bno tree, a bcnt tree * and a tree for dup extents. If the code is modified in the * future to use an extent tree instead of a bitmask for tracking * fs blocks, then we could lose the dup extent tree if we labelled * each extent with the inode that owned it. */ typedef unsigned char extent_state_t; typedef struct extent_tree_node { avlnode_t avl_node; xfs_agblock_t ex_startblock; /* starting block (agbno) */ xfs_extlen_t ex_blockcount; /* number of blocks in extent */ extent_state_t ex_state; /* see state flags below */ struct extent_tree_node *next; /* for bcnt extent lists */ struct extent_tree_node *last; /* for bcnt extent list anchors */ #if 0 xfs_ino_t ex_inode; /* owner, NULL if free or */ /* multiply allocated */ #endif } extent_tree_node_t; typedef struct rt_extent_tree_node { avlnode_t avl_node; xfs_rtblock_t rt_startblock; /* starting realtime block */ xfs_extlen_t rt_blockcount; /* number of blocks in extent */ extent_state_t rt_state; /* see state flags below */ #if 0 xfs_ino_t ex_inode; /* owner, NULL if free or */ /* multiply allocated */ #endif } rt_extent_tree_node_t; /* extent states, prefix with XR_ to avoid conflict with buffer cache defines */ #define XR_E_UNKNOWN 0 /* unknown state */ #define XR_E_FREE1 1 /* free block (marked by one fs space tree) */ #define XR_E_FREE 2 /* free block (marked by both fs space trees) */ #define XR_E_INUSE 3 /* extent used by file/dir data or metadata */ #define XR_E_INUSE_FS 4 /* extent used by fs ag header or log */ #define XR_E_MULT 5 /* extent is multiply referenced */ #define XR_E_INO 6 /* extent used by inodes (inode blocks) */ #define XR_E_FS_MAP 7 /* extent used by fs space/inode maps */ #define XR_E_INUSE1 8 /* used block (marked by rmap btree) */ #define XR_E_INUSE_FS1 9 /* used by fs ag header or log (rmap btree) */ #define XR_E_INO1 10 /* used by inodes (marked by rmap btree) */ #define XR_E_FS_MAP1 11 /* used by fs space/inode maps (rmap btree) */ #define XR_E_REFC 12 /* used by fs ag reference count btree */ #define XR_E_COW 13 /* leftover cow extent */ #define XR_E_BAD_STATE 14 /* separate state bit, OR'ed into high (4th) bit of ex_state field */ #define XR_E_WRITTEN 0x8 /* extent has been written out, can't reclaim */ #define good_state(state) (((state) & (~XR_E_WRITTEN)) >= XR_E_UNKNOWN && \ ((state) & (~XR_E_WRITTEN) < XF_E_BAD_STATE)) #define written(state) ((state) & XR_E_WRITTEN) #define set_written(state) (state) &= XR_E_WRITTEN /* * bno extent tree functions */ void add_bno_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount); extent_tree_node_t * findfirst_bno_extent(xfs_agnumber_t agno); extent_tree_node_t * find_bno_extent(xfs_agnumber_t agno, xfs_agblock_t agbno); extent_tree_node_t * findfirst_bno_extent(xfs_agnumber_t agno); #define findnext_bno_extent(exent_ptr) \ ((extent_tree_node_t *) ((exent_ptr)->avl_node.avl_nextino)) void get_bno_extent(xfs_agnumber_t agno, extent_tree_node_t *ext); /* * bcnt tree functions */ void add_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount); extent_tree_node_t * findfirst_bcnt_extent(xfs_agnumber_t agno); extent_tree_node_t * find_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t agbno); extent_tree_node_t * findbiggest_bcnt_extent(xfs_agnumber_t agno); extent_tree_node_t * findnext_bcnt_extent(xfs_agnumber_t agno, extent_tree_node_t *ext); extent_tree_node_t * get_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount); /* * duplicate extent tree functions */ int add_dup_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount); int search_dup_extent(xfs_agnumber_t agno, xfs_agblock_t start_agbno, xfs_agblock_t end_agbno); void add_rt_dup_extent(xfs_rtblock_t startblock, xfs_extlen_t blockcount); int search_rt_dup_extent(xfs_mount_t *mp, xfs_rtblock_t bno); /* * extent/tree recyling and deletion routines */ /* * return an extent node to the extent node free list */ void release_extent_tree_node(extent_tree_node_t *node); /* * recycle all the nodes in the per-AG tree */ void release_dup_extent_tree(xfs_agnumber_t agno); void release_agbno_extent_tree(xfs_agnumber_t agno); void release_agbcnt_extent_tree(xfs_agnumber_t agno); /* * realtime duplicate extent tree - this one actually frees the memory */ void free_rt_dup_extent_tree(xfs_mount_t *mp); void incore_ext_init(xfs_mount_t *); /* * per-AG extent trees shutdown routine -- all (bno, bcnt and dup) * at once. this one actually frees the memory instead of just recyling * the nodes. */ void incore_ext_teardown(xfs_mount_t *mp); void incore_ino_init(xfs_mount_t *); int count_bno_extents(xfs_agnumber_t); int count_bno_extents_blocks(xfs_agnumber_t, uint *); int count_bcnt_extents(xfs_agnumber_t); /* * inode definitions */ /* inode types */ #define XR_INO_UNKNOWN 0 /* unknown */ #define XR_INO_DIR 1 /* directory */ #define XR_INO_RTDATA 2 /* realtime file */ #define XR_INO_RTBITMAP 3 /* realtime bitmap inode */ #define XR_INO_RTSUM 4 /* realtime summary inode */ #define XR_INO_DATA 5 /* regular file */ #define XR_INO_SYMLINK 6 /* symlink */ #define XR_INO_CHRDEV 7 /* character device */ #define XR_INO_BLKDEV 8 /* block device */ #define XR_INO_SOCK 9 /* socket */ #define XR_INO_FIFO 10 /* fifo */ #define XR_INO_MOUNTPOINT 11 /* mountpoint */ /* inode allocation tree */ /* * Inodes in the inode allocation trees are allocated in chunks. * Those groups can be easily duplicated in our trees. * Disconnected inodes are harder. We can do one of two * things in that case: if we know the inode allocation btrees * are good, then we can disallow directory references to unknown * inode chunks. If the inode allocation trees have been trashed or * we feel like being aggressive, then as we hit unknown inodes, * we can search on the disk for all contiguous inodes and see if * they fit into chunks. Before putting them into the inode tree, * we can scan each inode starting at the earliest inode to see which * ones are good. This protects us from the pathalogical case of * inodes appearing in user-data. We still may have to mark the * inodes as "possibly fake" so that if a file claims the blocks, * we decide to believe the inodes, especially if they're not * connected. */ #define PLIST_CHUNK_SIZE 4 typedef xfs_ino_t parent_entry_t; struct nlink_ops; typedef struct parent_list { __uint64_t pmask; parent_entry_t *pentries; #ifdef DEBUG short cnt; #endif } parent_list_t; union ino_nlink { __uint8_t *un8; __uint16_t *un16; __uint32_t *un32; }; typedef struct ino_ex_data { __uint64_t ino_reached; /* bit == 1 if reached */ __uint64_t ino_processed; /* reference checked bit mask */ parent_list_t *parents; union ino_nlink counted_nlinks;/* counted nlinks in P6 */ } ino_ex_data_t; typedef struct ino_tree_node { avlnode_t avl_node; xfs_agino_t ino_startnum; /* starting inode # */ xfs_inofree_t ir_free; /* inode free bit mask */ __uint64_t ir_sparse; /* sparse inode bitmask */ __uint64_t ino_confirmed; /* confirmed bitmask */ __uint64_t ino_isa_dir; /* bit == 1 if a directory */ __uint64_t ino_was_rl; /* bit == 1 if reflink flag set */ __uint64_t ino_is_rl; /* bit == 1 if reflink flag should be set */ __uint8_t nlink_size; union ino_nlink disk_nlinks; /* on-disk nlinks, set in P3 */ union { ino_ex_data_t *ex_data; /* phases 6,7 */ parent_list_t *plist; /* phases 2-5 */ } ino_un; __uint8_t *ftypes; /* phases 3,6 */ } ino_tree_node_t; #define INOS_PER_IREC (sizeof(__uint64_t) * NBBY) #define IREC_MASK(i) ((__uint64_t)1 << (i)) void add_ino_ex_data(xfs_mount_t *mp); /* * return an inode record to the free inode record pool */ void free_inode_rec(xfs_agnumber_t agno, ino_tree_node_t *ino_rec); /* * get pulls the inode record from the good inode tree */ void get_inode_rec(struct xfs_mount *mp, xfs_agnumber_t agno, ino_tree_node_t *ino_rec); extern avltree_desc_t **inode_tree_ptrs; static inline int get_inode_offset(struct xfs_mount *mp, xfs_ino_t ino, ino_tree_node_t *irec) { return XFS_INO_TO_AGINO(mp, ino) - irec->ino_startnum; } static inline ino_tree_node_t * findfirst_inode_rec(xfs_agnumber_t agno) { return((ino_tree_node_t *) inode_tree_ptrs[agno]->avl_firstino); } static inline ino_tree_node_t * find_inode_rec(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino) { /* * Is the AG inside the file system */ if (agno >= mp->m_sb.sb_agcount) return NULL; return((ino_tree_node_t *) avl_findrange(inode_tree_ptrs[agno], ino)); } void find_inode_rec_range(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t start_ino, xfs_agino_t end_ino, ino_tree_node_t **first, ino_tree_node_t **last); /* * set inode states -- setting an inode to used or free also * automatically marks it as "existing". Note -- all the inode * add/set/get routines assume a valid inode number. */ ino_tree_node_t *set_inode_used_alloc(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino); ino_tree_node_t *set_inode_free_alloc(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino); void print_inode_list(xfs_agnumber_t agno); void print_uncertain_inode_list(xfs_agnumber_t agno); /* * separate trees for uncertain inodes (they may not exist). */ ino_tree_node_t *findfirst_uncertain_inode_rec(xfs_agnumber_t agno); ino_tree_node_t *find_uncertain_inode_rec(xfs_agnumber_t agno, xfs_agino_t ino); void add_inode_uncertain(xfs_mount_t *mp, xfs_ino_t ino, int free); void add_aginode_uncertain(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino, int free); void get_uncertain_inode_rec(struct xfs_mount *mp, xfs_agnumber_t agno, ino_tree_node_t *ino_rec); void clear_uncertain_ino_cache(xfs_agnumber_t agno); /* * return next in-order inode tree node. takes an "ino_tree_node_t *" */ #define next_ino_rec(ino_node_ptr) \ ((ino_tree_node_t *) ((ino_node_ptr)->avl_node.avl_nextino)) /* * return the next linked inode (forward avl tree link)-- meant to be used * by linked list routines (uncertain inode routines/records) */ #define next_link_rec(ino_node_ptr) \ ((ino_tree_node_t *) ((ino_node_ptr)->avl_node.avl_forw)) /* * finobt helpers */ static inline bool inode_rec_has_free(struct ino_tree_node *ino_rec) { /* must have real, allocated inodes for finobt */ return ino_rec->ir_free & ~ino_rec->ir_sparse; } static inline ino_tree_node_t * findfirst_free_inode_rec(xfs_agnumber_t agno) { ino_tree_node_t *ino_rec; ino_rec = findfirst_inode_rec(agno); while (ino_rec && !inode_rec_has_free(ino_rec)) ino_rec = next_ino_rec(ino_rec); return ino_rec; } static inline ino_tree_node_t * next_free_ino_rec(ino_tree_node_t *ino_rec) { ino_rec = next_ino_rec(ino_rec); while (ino_rec && !inode_rec_has_free(ino_rec)) ino_rec = next_ino_rec(ino_rec); return ino_rec; } /* * Has an inode been processed for phase 6 (reference count checking)? * * add_inode_refchecked() is set on an inode when it gets traversed * during the reference count phase (6). It's set so that if the inode * is a directory, it's traversed (and it's links counted) only once. */ static inline void add_inode_refchecked(struct ino_tree_node *irec, int offset) { irec->ino_un.ex_data->ino_processed |= IREC_MASK(offset); } static inline int is_inode_refchecked(struct ino_tree_node *irec, int offset) { return (irec->ino_un.ex_data->ino_processed & IREC_MASK(offset)) != 0; } /* * set/test is inode known to be valid (although perhaps corrupt) */ static inline void set_inode_confirmed(struct ino_tree_node *irec, int offset) { irec->ino_confirmed |= IREC_MASK(offset); } static inline int is_inode_confirmed(struct ino_tree_node *irec, int offset) { return (irec->ino_confirmed & IREC_MASK(offset)) != 0; } /* * set/clear/test is inode a directory inode */ static inline void set_inode_isadir(struct ino_tree_node *irec, int offset) { irec->ino_isa_dir |= IREC_MASK(offset); } static inline void clear_inode_isadir(struct ino_tree_node *irec, int offset) { irec->ino_isa_dir &= ~IREC_MASK(offset); } static inline int inode_isadir(struct ino_tree_node *irec, int offset) { return (irec->ino_isa_dir & IREC_MASK(offset)) != 0; } /* * set/clear/test is inode free or used */ static inline void set_inode_free(struct ino_tree_node *irec, int offset) { set_inode_confirmed(irec, offset); irec->ir_free |= XFS_INOBT_MASK(offset); } static inline void set_inode_used(struct ino_tree_node *irec, int offset) { set_inode_confirmed(irec, offset); irec->ir_free &= ~XFS_INOBT_MASK(offset); } static inline int is_inode_free(struct ino_tree_node *irec, int offset) { return (irec->ir_free & XFS_INOBT_MASK(offset)) != 0; } /* * set/test is inode sparse (not physically allocated) */ static inline void set_inode_sparse(struct ino_tree_node *irec, int offset) { irec->ir_sparse |= XFS_INOBT_MASK(offset); } static inline bool is_inode_sparse(struct ino_tree_node *irec, int offset) { return irec->ir_sparse & XFS_INOBT_MASK(offset); } /* * set/clear/test was inode marked as reflinked */ static inline void set_inode_was_rl(struct ino_tree_node *irec, int offset) { irec->ino_was_rl |= IREC_MASK(offset); } static inline void clear_inode_was_rl(struct ino_tree_node *irec, int offset) { irec->ino_was_rl &= ~IREC_MASK(offset); } static inline int inode_was_rl(struct ino_tree_node *irec, int offset) { return (irec->ino_was_rl & IREC_MASK(offset)) != 0; } /* * set/clear/test should inode be marked as reflinked */ static inline void set_inode_is_rl(struct ino_tree_node *irec, int offset) { irec->ino_is_rl |= IREC_MASK(offset); } static inline void clear_inode_is_rl(struct ino_tree_node *irec, int offset) { irec->ino_is_rl &= ~IREC_MASK(offset); } static inline int inode_is_rl(struct ino_tree_node *irec, int offset) { return (irec->ino_is_rl & IREC_MASK(offset)) != 0; } /* * add_inode_reached() is set on inode I only if I has been reached * by an inode P claiming to be the parent and if I is a directory, * the .. link in the I says that P is I's parent. * * add_inode_ref() is called every time a link to an inode is * detected and drop_inode_ref() is called every time a link to * an inode that we've counted is removed. */ void add_inode_ref(struct ino_tree_node *irec, int offset); void drop_inode_ref(struct ino_tree_node *irec, int offset); __uint32_t num_inode_references(struct ino_tree_node *irec, int offset); void set_inode_disk_nlinks(struct ino_tree_node *irec, int offset, __uint32_t nlinks); __uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int offset); static inline int is_inode_reached(struct ino_tree_node *irec, int offset) { ASSERT(irec->ino_un.ex_data != NULL); return (irec->ino_un.ex_data->ino_reached & IREC_MASK(offset)) != 0; } static inline void add_inode_reached(struct ino_tree_node *irec, int offset) { add_inode_ref(irec, offset); irec->ino_un.ex_data->ino_reached |= IREC_MASK(offset); } /* * get/set inode filetype. Only used if the superblock feature bit is set * which allocates irec->ftypes. */ static inline void set_inode_ftype(struct ino_tree_node *irec, int ino_offset, __uint8_t ftype) { if (irec->ftypes) irec->ftypes[ino_offset] = ftype; } static inline __uint8_t get_inode_ftype( struct ino_tree_node *irec, int ino_offset) { if (!irec->ftypes) return XFS_DIR3_FT_UNKNOWN; return irec->ftypes[ino_offset]; } /* * set/get inode number of parent -- works for directory inodes only */ void set_inode_parent(ino_tree_node_t *irec, int ino_offset, xfs_ino_t ino); xfs_ino_t get_inode_parent(ino_tree_node_t *irec, int ino_offset); /* * Allocate extra inode data */ void alloc_ex_data(ino_tree_node_t *irec); /* * bmap cursor for tracking and fixing bmap btrees. All xfs btrees number * the levels with 0 being the leaf and every level up being 1 greater. */ #define XR_MAX_BMLEVELS 10 /* XXX - rcc need to verify number */ typedef struct bm_level_state { xfs_fsblock_t fsbno; xfs_fsblock_t left_fsbno; xfs_fsblock_t right_fsbno; __uint64_t first_key; __uint64_t last_key; /* int level; __uint64_t prev_last_key; xfs_buf_t *bp; xfs_bmbt_block_t *block; */ } bm_level_state_t; typedef struct bm_cursor { int num_levels; xfs_ino_t ino; xfs_dinode_t *dip; bm_level_state_t level[XR_MAX_BMLEVELS]; } bmap_cursor_t; void init_bm_cursor(bmap_cursor_t *cursor, int num_level); /* * On-disk inobt record helpers. The sparse inode record format has a single * byte freecount. The older format has a 32-bit freecount and thus byte * conversion is necessary. */ static inline int inorec_get_freecount( struct xfs_mount *mp, struct xfs_inobt_rec *rp) { if (xfs_sb_version_hassparseinodes(&mp->m_sb)) return rp->ir_u.sp.ir_freecount; return be32_to_cpu(rp->ir_u.f.ir_freecount); } static inline void inorec_set_freecount( struct xfs_mount *mp, struct xfs_inobt_rec *rp, int freecount) { if (xfs_sb_version_hassparseinodes(&mp->m_sb)) rp->ir_u.sp.ir_freecount = freecount; else rp->ir_u.f.ir_freecount = cpu_to_be32(freecount); } #endif /* XFS_REPAIR_INCORE_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/incore_bmc.c0000644000000000000000000000244013063067172016221 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "incore.h" #include "agheader.h" #include "protos.h" #include "err_protos.h" void init_bm_cursor(bmap_cursor_t *cursor, int num_levels) { int i; memset(cursor, 0, sizeof(bmap_cursor_t)); cursor->ino = NULLFSINO; cursor->num_levels = num_levels; for (i = 0; i < XR_MAX_BMLEVELS; i++) { cursor->level[i].fsbno = NULLFSBLOCK; cursor->level[i].right_fsbno = NULLFSBLOCK; cursor->level[i].left_fsbno = NULLFSBLOCK; cursor->level[i].first_key = NULLFILEOFF; cursor->level[i].last_key = NULLFILEOFF; } } xfsprogs-4.9.0+nmu1ubuntu2/repair/incore_ext.c0000644000000000000000000005142513063067173016270 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "btree.h" #include "globals.h" #include "incore.h" #include "agheader.h" #include "protos.h" #include "err_protos.h" #include "avl64.h" #include "threads.h" /* * note: there are 4 sets of incore things handled here: * block bitmaps, extent trees, uncertain inode list, * and inode tree. The tree-based code uses the AVL * tree package used by the IRIX kernel VM code * (sys/avl.h). The inode list code uses the same records * as the inode tree code for convenience. The bitmaps * and bitmap operators are mostly macros defined in incore.h. * There are one of everything per AG except for extent * trees. There's one duplicate extent tree, one bno and * one bcnt extent tree per AG. Not all of the above exist * through all phases. The duplicate extent tree gets trashed * at the end of phase 4. The bno/bcnt trees don't appear until * phase 5. The uncertain inode list goes away at the end of * phase 3. The inode tree and bno/bnct trees go away after phase 5. */ static avl64tree_desc_t *rt_ext_tree_ptr; /* dup extent tree for rt */ static pthread_mutex_t rt_ext_tree_lock; static struct btree_root **dup_extent_trees; /* per ag dup extent trees */ static pthread_mutex_t *dup_extent_tree_locks; static avltree_desc_t **extent_bno_ptrs; /* * array of extent tree ptrs * one per ag for free extents * sorted by starting block * number */ static avltree_desc_t **extent_bcnt_ptrs; /* * array of extent tree ptrs * one per ag for free extents * sorted by size */ /* * duplicate extent tree functions */ void release_dup_extent_tree( xfs_agnumber_t agno) { pthread_mutex_lock(&dup_extent_tree_locks[agno]); btree_clear(dup_extent_trees[agno]); pthread_mutex_unlock(&dup_extent_tree_locks[agno]); } int add_dup_extent( xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount) { int ret; #ifdef XR_DUP_TRACE fprintf(stderr, "Adding dup extent - %d/%d %d\n", agno, startblock, blockcount); #endif pthread_mutex_lock(&dup_extent_tree_locks[agno]); ret = btree_insert(dup_extent_trees[agno], startblock, (void *)(uintptr_t)(startblock + blockcount)); pthread_mutex_unlock(&dup_extent_tree_locks[agno]); return ret; } int search_dup_extent( xfs_agnumber_t agno, xfs_agblock_t start_agbno, xfs_agblock_t end_agbno) { unsigned long bno; int ret; pthread_mutex_lock(&dup_extent_tree_locks[agno]); if (!btree_find(dup_extent_trees[agno], start_agbno, &bno)) { ret = 0; goto out; /* this really shouldn't happen */ } if (bno < end_agbno) { ret = 1; goto out; } ret = (uintptr_t)btree_peek_prev(dup_extent_trees[agno], NULL) > start_agbno; out: pthread_mutex_unlock(&dup_extent_tree_locks[agno]); return ret; } /* * extent tree stuff is avl trees of duplicate extents, * sorted in order by block number. there is one tree per ag. */ static extent_tree_node_t * mk_extent_tree_nodes(xfs_agblock_t new_startblock, xfs_extlen_t new_blockcount, extent_state_t new_state) { extent_tree_node_t *new; new = malloc(sizeof(*new)); if (!new) do_error(_("couldn't allocate new extent descriptor.\n")); new->avl_node.avl_nextino = NULL; new->ex_startblock = new_startblock; new->ex_blockcount = new_blockcount; new->ex_state = new_state; new->next = NULL; new->last = NULL; return new; } void release_extent_tree_node(extent_tree_node_t *node) { free(node); } /* * routines to recycle all nodes in a tree. it walks the tree * and puts all nodes back on the free list so the nodes can be * reused. the duplicate and bno/bcnt extent trees for each AG * are recycled after they're no longer needed to save memory */ void release_extent_tree(avltree_desc_t *tree) { extent_tree_node_t *ext; extent_tree_node_t *tmp; extent_tree_node_t *lext; extent_tree_node_t *ltmp; if (tree->avl_firstino == NULL) return; ext = (extent_tree_node_t *) tree->avl_firstino; while (ext != NULL) { tmp = (extent_tree_node_t *) ext->avl_node.avl_nextino; /* * ext->next is guaranteed to be set only in bcnt trees */ if (ext->next != NULL) { lext = ext->next; while (lext != NULL) { ltmp = lext->next; release_extent_tree_node(lext); lext = ltmp; } } release_extent_tree_node(ext); ext = tmp; } tree->avl_root = tree->avl_firstino = NULL; return; } /* * top-level (visible) routines */ void release_agbno_extent_tree(xfs_agnumber_t agno) { release_extent_tree(extent_bno_ptrs[agno]); return; } void release_agbcnt_extent_tree(xfs_agnumber_t agno) { release_extent_tree(extent_bcnt_ptrs[agno]); return; } /* * the next 4 routines manage the trees of free extents -- 2 trees * per AG. The first tree is sorted by block number. The second * tree is sorted by extent size. This is the bno tree. */ void add_bno_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount) { extent_tree_node_t *ext; ASSERT(extent_bno_ptrs != NULL); ASSERT(extent_bno_ptrs[agno] != NULL); ext = mk_extent_tree_nodes(startblock, blockcount, XR_E_FREE); if (avl_insert(extent_bno_ptrs[agno], (avlnode_t *) ext) == NULL) { do_error(_("duplicate bno extent range\n")); } } extent_tree_node_t * findfirst_bno_extent(xfs_agnumber_t agno) { ASSERT(extent_bno_ptrs != NULL); ASSERT(extent_bno_ptrs[agno] != NULL); return((extent_tree_node_t *) extent_bno_ptrs[agno]->avl_firstino); } extent_tree_node_t * find_bno_extent(xfs_agnumber_t agno, xfs_agblock_t startblock) { ASSERT(extent_bno_ptrs != NULL); ASSERT(extent_bno_ptrs[agno] != NULL); return((extent_tree_node_t *) avl_find(extent_bno_ptrs[agno], startblock)); } /* * delete a node that's in the tree (pointer obtained by a find routine) */ void get_bno_extent(xfs_agnumber_t agno, extent_tree_node_t *ext) { ASSERT(extent_bno_ptrs != NULL); ASSERT(extent_bno_ptrs[agno] != NULL); avl_delete(extent_bno_ptrs[agno], &ext->avl_node); return; } /* * normalizing constant for bcnt size -> address conversion (see avl ops) * used by the AVL tree code to convert sizes and must be used when * doing an AVL search in the tree (e.g. avl_findrange(s)) */ #define MAXBCNT 0xFFFFFFFF #define BCNT_ADDR(cnt) ((unsigned int) MAXBCNT - (cnt)) /* * the next 4 routines manage the trees of free extents -- 2 trees * per AG. The first tree is sorted by block number. The second * tree is sorted by extent size. This is the bcnt tree. */ void add_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount) { extent_tree_node_t *ext, *prev, *current, *top; xfs_agblock_t tmp_startblock; xfs_extlen_t tmp_blockcount; extent_state_t tmp_state; ASSERT(extent_bcnt_ptrs != NULL); ASSERT(extent_bcnt_ptrs[agno] != NULL); ext = mk_extent_tree_nodes(startblock, blockcount, XR_E_FREE); ASSERT(ext->next == NULL); #ifdef XR_BCNT_TRACE fprintf(stderr, "adding bcnt: agno = %d, start = %u, count = %u\n", agno, startblock, blockcount); #endif if ((current = (extent_tree_node_t *) avl_find(extent_bcnt_ptrs[agno], blockcount)) != NULL) { /* * avl tree code doesn't handle dups so insert * onto linked list in increasing startblock order * * when called from mk_incore_fstree, * startblock is in increasing order. * current is an "anchor" node. * quick check if the new ext goes to the end. * if so, append at the end, using the last field * of the "anchor". */ ASSERT(current->last != NULL); if (startblock > current->last->ex_startblock) { current->last->next = ext; current->last = ext; return; } /* * scan, to find the proper location for new entry. * this scan is *very* expensive and gets worse with * with increasing entries. */ top = prev = current; while (current != NULL && startblock > current->ex_startblock) { prev = current; current = current->next; } if (top == current) { ASSERT(top == prev); /* * new entry should be ahead of current. * to keep the avl tree intact, * swap the values of to-be-inserted element * and the values of the head of the list. * then insert as the 2nd element on the list. * * see the comment in get_bcnt_extent() * as to why we have to do this. */ tmp_startblock = top->ex_startblock; tmp_blockcount = top->ex_blockcount; tmp_state = top->ex_state; top->ex_startblock = ext->ex_startblock; top->ex_blockcount = ext->ex_blockcount; top->ex_state = ext->ex_state; ext->ex_startblock = tmp_startblock; ext->ex_blockcount = tmp_blockcount; ext->ex_state = tmp_state; current = top->next; prev = top; } prev->next = ext; ext->next = current; return; } if (avl_insert(extent_bcnt_ptrs[agno], (avlnode_t *) ext) == NULL) { do_error(_(": duplicate bno extent range\n")); } ext->last = ext; /* ext is an "anchor" node */ return; } extent_tree_node_t * findfirst_bcnt_extent(xfs_agnumber_t agno) { ASSERT(extent_bcnt_ptrs != NULL); ASSERT(extent_bcnt_ptrs[agno] != NULL); return((extent_tree_node_t *) extent_bcnt_ptrs[agno]->avl_firstino); } extent_tree_node_t * findbiggest_bcnt_extent(xfs_agnumber_t agno) { ASSERT(extent_bcnt_ptrs != NULL); ASSERT(extent_bcnt_ptrs[agno] != NULL); return((extent_tree_node_t *) avl_lastino(extent_bcnt_ptrs[agno]->avl_root)); } extent_tree_node_t * findnext_bcnt_extent(xfs_agnumber_t agno, extent_tree_node_t *ext) { avlnode_t *nextino; if (ext->next != NULL) { ASSERT(ext->ex_blockcount == ext->next->ex_blockcount); ASSERT(ext->ex_startblock < ext->next->ex_startblock); return(ext->next); } else { /* * have to look at the top of the list to get the * correct avl_nextino pointer since that pointer * is maintained and altered by the AVL code. */ nextino = avl_find(extent_bcnt_ptrs[agno], ext->ex_blockcount); ASSERT(nextino != NULL); if (nextino->avl_nextino != NULL) { ASSERT(ext->ex_blockcount < ((extent_tree_node_t *) nextino->avl_nextino)->ex_blockcount); } return((extent_tree_node_t *) nextino->avl_nextino); } } /* * this is meant to be called after you walk the bno tree to * determine exactly which extent you want (so you'll know the * desired value for startblock when you call this routine). */ extent_tree_node_t * get_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount) { extent_tree_node_t *ext, *prev, *top; xfs_agblock_t tmp_startblock; xfs_extlen_t tmp_blockcount; extent_state_t tmp_state; prev = NULL; ASSERT(extent_bcnt_ptrs != NULL); ASSERT(extent_bcnt_ptrs[agno] != NULL); if ((ext = (extent_tree_node_t *) avl_find(extent_bcnt_ptrs[agno], blockcount)) == NULL) return(NULL); top = ext; if (ext->next != NULL) { /* * pull it off the list */ while (ext != NULL && startblock != ext->ex_startblock) { prev = ext; ext = ext->next; } ASSERT(ext != NULL); if (ext == top) { /* * this node is linked into the tree so we * swap the core values so we can delete * the next item on the list instead of * the head of the list. This is because * the rest of the tree undoubtedly has * pointers to the piece of memory that * is the head of the list so pulling * the item out of the list and hence * the avl tree would be a bad idea. * * (cheaper than the alternative, a tree * delete of this node followed by a tree * insert of the next node on the list). */ tmp_startblock = ext->next->ex_startblock; tmp_blockcount = ext->next->ex_blockcount; tmp_state = ext->next->ex_state; ext->next->ex_startblock = ext->ex_startblock; ext->next->ex_blockcount = ext->ex_blockcount; ext->next->ex_state = ext->ex_state; ext->ex_startblock = tmp_startblock; ext->ex_blockcount = tmp_blockcount; ext->ex_state = tmp_state; ext = ext->next; prev = top; } /* * now, a simple list deletion */ prev->next = ext->next; ext->next = NULL; } else { /* * no list, just one node. simply delete */ avl_delete(extent_bcnt_ptrs[agno], &ext->avl_node); } ASSERT(ext->ex_startblock == startblock); ASSERT(ext->ex_blockcount == blockcount); return(ext); } static uintptr_t avl_ext_start(avlnode_t *node) { return((uintptr_t) ((extent_tree_node_t *) node)->ex_startblock); } static uintptr_t avl_ext_end(avlnode_t *node) { return((uintptr_t) ( ((extent_tree_node_t *) node)->ex_startblock + ((extent_tree_node_t *) node)->ex_blockcount)); } /* * convert size to an address for the AVL tree code -- the bigger the size, * the lower the address so the biggest extent will be first in the tree */ static uintptr_t avl_ext_bcnt_start(avlnode_t *node) { /* return((uintptr_t) (BCNT_ADDR(((extent_tree_node_t *) node)->ex_blockcount))); */ return((uintptr_t) ((extent_tree_node_t *)node)->ex_blockcount); } static uintptr_t avl_ext_bcnt_end(avlnode_t *node) { /* return((uintptr_t) (BCNT_ADDR(((extent_tree_node_t *) node)->ex_blockcount))); */ return((uintptr_t) ((extent_tree_node_t *)node)->ex_blockcount); } avlops_t avl_extent_bcnt_tree_ops = { avl_ext_bcnt_start, avl_ext_bcnt_end }; avlops_t avl_extent_tree_ops = { avl_ext_start, avl_ext_end }; /* * for real-time extents -- have to dup code since realtime extent * startblocks can be 64-bit values. */ static rt_extent_tree_node_t * mk_rt_extent_tree_nodes(xfs_rtblock_t new_startblock, xfs_extlen_t new_blockcount, extent_state_t new_state) { rt_extent_tree_node_t *new; new = malloc(sizeof(*new)); if (!new) do_error(_("couldn't allocate new extent descriptor.\n")); new->avl_node.avl_nextino = NULL; new->rt_startblock = new_startblock; new->rt_blockcount = new_blockcount; new->rt_state = new_state; return new; } #if 0 void release_rt_extent_tree_node(rt_extent_tree_node_t *node) { free(node); } void release_rt_extent_tree() { extent_tree_node_t *ext; extent_tree_node_t *tmp; extent_tree_node_t *lext; extent_tree_node_t *ltmp; avl64tree_desc_t *tree; tree = rt_extent_tree_ptr; if (tree->avl_firstino == NULL) return; ext = (extent_tree_node_t *) tree->avl_firstino; while (ext != NULL) { tmp = (extent_tree_node_t *) ext->avl_node.avl_nextino; release_rt_extent_tree_node(ext); ext = tmp; } tree->avl_root = tree->avl_firstino = NULL; return; } #endif /* * don't need release functions for realtime tree teardown * since we only have one tree, not one per AG */ /* ARGSUSED */ void free_rt_dup_extent_tree(xfs_mount_t *mp) { ASSERT(mp->m_sb.sb_rblocks != 0); free(rt_ext_tree_ptr); rt_ext_tree_ptr = NULL; } /* * add a duplicate real-time extent */ void add_rt_dup_extent(xfs_rtblock_t startblock, xfs_extlen_t blockcount) { rt_extent_tree_node_t *first, *last, *ext, *next_ext; xfs_rtblock_t new_startblock; xfs_extlen_t new_blockcount; pthread_mutex_lock(&rt_ext_tree_lock); avl64_findranges(rt_ext_tree_ptr, startblock - 1, startblock + blockcount + 1, (avl64node_t **) &first, (avl64node_t **) &last); /* * find adjacent and overlapping extent blocks */ if (first == NULL && last == NULL) { /* nothing, just make and insert new extent */ ext = mk_rt_extent_tree_nodes(startblock, blockcount, XR_E_MULT); if (avl64_insert(rt_ext_tree_ptr, (avl64node_t *) ext) == NULL) { do_error(_("duplicate extent range\n")); } pthread_mutex_unlock(&rt_ext_tree_lock); return; } ASSERT(first != NULL && last != NULL); /* * find the new composite range, delete old extent nodes * as we go */ new_startblock = startblock; new_blockcount = blockcount; for (ext = first; ext != (rt_extent_tree_node_t *) last->avl_node.avl_nextino; ext = next_ext) { /* * preserve the next inorder node */ next_ext = (rt_extent_tree_node_t *) ext->avl_node.avl_nextino; /* * just bail if the new extent is contained within an old one */ if (ext->rt_startblock <= startblock && ext->rt_blockcount >= blockcount) { pthread_mutex_unlock(&rt_ext_tree_lock); return; } /* * now check for overlaps and adjacent extents */ if (ext->rt_startblock + ext->rt_blockcount >= startblock || ext->rt_startblock <= startblock + blockcount) { if (ext->rt_startblock < new_startblock) new_startblock = ext->rt_startblock; if (ext->rt_startblock + ext->rt_blockcount > new_startblock + new_blockcount) new_blockcount = ext->rt_startblock + ext->rt_blockcount - new_startblock; avl64_delete(rt_ext_tree_ptr, (avl64node_t *) ext); continue; } } ext = mk_rt_extent_tree_nodes(new_startblock, new_blockcount, XR_E_MULT); if (avl64_insert(rt_ext_tree_ptr, (avl64node_t *) ext) == NULL) { do_error(_("duplicate extent range\n")); } pthread_mutex_unlock(&rt_ext_tree_lock); return; } /* * returns 1 if block is a dup, 0 if not */ /* ARGSUSED */ int search_rt_dup_extent(xfs_mount_t *mp, xfs_rtblock_t bno) { int ret; pthread_mutex_lock(&rt_ext_tree_lock); if (avl64_findrange(rt_ext_tree_ptr, bno) != NULL) ret = 1; else ret = 0; pthread_mutex_unlock(&rt_ext_tree_lock); return(ret); } static __uint64_t avl64_rt_ext_start(avl64node_t *node) { return(((rt_extent_tree_node_t *) node)->rt_startblock); } static __uint64_t avl64_ext_end(avl64node_t *node) { return(((rt_extent_tree_node_t *) node)->rt_startblock + ((rt_extent_tree_node_t *) node)->rt_blockcount); } avl64ops_t avl64_extent_tree_ops = { avl64_rt_ext_start, avl64_ext_end }; void incore_ext_init(xfs_mount_t *mp) { int i; xfs_agnumber_t agcount = mp->m_sb.sb_agcount; pthread_mutex_init(&rt_ext_tree_lock, NULL); dup_extent_trees = calloc(agcount, sizeof(struct btree_root *)); if (!dup_extent_trees) do_error(_("couldn't malloc dup extent tree descriptor table\n")); dup_extent_tree_locks = calloc(agcount, sizeof(pthread_mutex_t)); if (!dup_extent_tree_locks) do_error(_("couldn't malloc dup extent tree descriptor table\n")); if ((extent_bno_ptrs = malloc(agcount * sizeof(avltree_desc_t *))) == NULL) do_error( _("couldn't malloc free by-bno extent tree descriptor table\n")); if ((extent_bcnt_ptrs = malloc(agcount * sizeof(avltree_desc_t *))) == NULL) do_error( _("couldn't malloc free by-bcnt extent tree descriptor table\n")); for (i = 0; i < agcount; i++) { if ((extent_bno_ptrs[i] = malloc(sizeof(avltree_desc_t))) == NULL) do_error( _("couldn't malloc bno extent tree descriptor\n")); if ((extent_bcnt_ptrs[i] = malloc(sizeof(avltree_desc_t))) == NULL) do_error( _("couldn't malloc bcnt extent tree descriptor\n")); } for (i = 0; i < agcount; i++) { btree_init(&dup_extent_trees[i]); pthread_mutex_init(&dup_extent_tree_locks[i], NULL); avl_init_tree(extent_bno_ptrs[i], &avl_extent_tree_ops); avl_init_tree(extent_bcnt_ptrs[i], &avl_extent_bcnt_tree_ops); } if ((rt_ext_tree_ptr = malloc(sizeof(avl64tree_desc_t))) == NULL) do_error(_("couldn't malloc dup rt extent tree descriptor\n")); avl64_init_tree(rt_ext_tree_ptr, &avl64_extent_tree_ops); } /* * this routine actually frees all the memory used to track per-AG trees */ void incore_ext_teardown(xfs_mount_t *mp) { xfs_agnumber_t i; for (i = 0; i < mp->m_sb.sb_agcount; i++) { btree_destroy(dup_extent_trees[i]); free(extent_bno_ptrs[i]); free(extent_bcnt_ptrs[i]); } free(dup_extent_trees); free(extent_bcnt_ptrs); free(extent_bno_ptrs); dup_extent_trees = NULL; extent_bcnt_ptrs = NULL; extent_bno_ptrs = NULL; } int count_extents(xfs_agnumber_t agno, avltree_desc_t *tree, int whichtree) { extent_tree_node_t *node; int i = 0; node = (extent_tree_node_t *) tree->avl_firstino; while (node != NULL) { i++; if (whichtree) node = findnext_bcnt_extent(agno, node); else node = findnext_bno_extent(node); } return(i); } int count_bno_extents_blocks(xfs_agnumber_t agno, uint *numblocks) { __uint64_t nblocks; extent_tree_node_t *node; int i = 0; ASSERT(agno < glob_agcount); nblocks = 0; node = (extent_tree_node_t *) extent_bno_ptrs[agno]->avl_firstino; while (node != NULL) { nblocks += node->ex_blockcount; i++; node = findnext_bno_extent(node); } *numblocks = nblocks; return(i); } int count_bno_extents(xfs_agnumber_t agno) { ASSERT(agno < glob_agcount); return(count_extents(agno, extent_bno_ptrs[agno], 0)); } int count_bcnt_extents(xfs_agnumber_t agno) { ASSERT(agno < glob_agcount); return(count_extents(agno, extent_bcnt_ptrs[agno], 1)); } xfsprogs-4.9.0+nmu1ubuntu2/repair/incore_ino.c0000644000000000000000000004604613063067172016257 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "incore.h" #include "agheader.h" #include "protos.h" #include "threads.h" #include "err_protos.h" /* * array of inode tree ptrs, one per ag */ avltree_desc_t **inode_tree_ptrs; /* * ditto for uncertain inodes */ static avltree_desc_t **inode_uncertain_tree_ptrs; /* memory optimised nlink counting for all inodes */ static void * alloc_nlink_array(__uint8_t nlink_size) { void *ptr; ptr = calloc(XFS_INODES_PER_CHUNK, nlink_size); if (!ptr) do_error(_("could not allocate nlink array\n")); return ptr; } static void nlink_grow_8_to_16(ino_tree_node_t *irec) { __uint16_t *new_nlinks; int i; irec->nlink_size = sizeof(__uint16_t); new_nlinks = alloc_nlink_array(irec->nlink_size); for (i = 0; i < XFS_INODES_PER_CHUNK; i++) new_nlinks[i] = irec->disk_nlinks.un8[i]; free(irec->disk_nlinks.un8); irec->disk_nlinks.un16 = new_nlinks; if (full_ino_ex_data) { new_nlinks = alloc_nlink_array(irec->nlink_size); for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { new_nlinks[i] = irec->ino_un.ex_data->counted_nlinks.un8[i]; } free(irec->ino_un.ex_data->counted_nlinks.un8); irec->ino_un.ex_data->counted_nlinks.un16 = new_nlinks; } } static void nlink_grow_16_to_32(ino_tree_node_t *irec) { __uint32_t *new_nlinks; int i; irec->nlink_size = sizeof(__uint32_t); new_nlinks = alloc_nlink_array(irec->nlink_size); for (i = 0; i < XFS_INODES_PER_CHUNK; i++) new_nlinks[i] = irec->disk_nlinks.un16[i]; free(irec->disk_nlinks.un16); irec->disk_nlinks.un32 = new_nlinks; if (full_ino_ex_data) { new_nlinks = alloc_nlink_array(irec->nlink_size); for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { new_nlinks[i] = irec->ino_un.ex_data->counted_nlinks.un16[i]; } free(irec->ino_un.ex_data->counted_nlinks.un16); irec->ino_un.ex_data->counted_nlinks.un32 = new_nlinks; } } void add_inode_ref(struct ino_tree_node *irec, int ino_offset) { ASSERT(irec->ino_un.ex_data != NULL); switch (irec->nlink_size) { case sizeof(__uint8_t): if (irec->ino_un.ex_data->counted_nlinks.un8[ino_offset] < 0xff) { irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]++; break; } nlink_grow_8_to_16(irec); /*FALLTHRU*/ case sizeof(__uint16_t): if (irec->ino_un.ex_data->counted_nlinks.un16[ino_offset] < 0xffff) { irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]++; break; } nlink_grow_16_to_32(irec); /*FALLTHRU*/ case sizeof(__uint32_t): irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]++; break; default: ASSERT(0); } } void drop_inode_ref(struct ino_tree_node *irec, int ino_offset) { __uint32_t refs = 0; ASSERT(irec->ino_un.ex_data != NULL); switch (irec->nlink_size) { case sizeof(__uint8_t): ASSERT(irec->ino_un.ex_data->counted_nlinks.un8[ino_offset] > 0); refs = --irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]; break; case sizeof(__uint16_t): ASSERT(irec->ino_un.ex_data->counted_nlinks.un16[ino_offset] > 0); refs = --irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]; break; case sizeof(__uint32_t): ASSERT(irec->ino_un.ex_data->counted_nlinks.un32[ino_offset] > 0); refs = --irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]; break; default: ASSERT(0); } if (refs == 0) irec->ino_un.ex_data->ino_reached &= ~IREC_MASK(ino_offset); } __uint32_t num_inode_references(struct ino_tree_node *irec, int ino_offset) { ASSERT(irec->ino_un.ex_data != NULL); switch (irec->nlink_size) { case sizeof(__uint8_t): return irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]; case sizeof(__uint16_t): return irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]; case sizeof(__uint32_t): return irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]; default: ASSERT(0); } return 0; } void set_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset, __uint32_t nlinks) { switch (irec->nlink_size) { case sizeof(__uint8_t): if (nlinks < 0xff) { irec->disk_nlinks.un8[ino_offset] = nlinks; break; } nlink_grow_8_to_16(irec); /*FALLTHRU*/ case sizeof(__uint16_t): if (nlinks < 0xffff) { irec->disk_nlinks.un16[ino_offset] = nlinks; break; } nlink_grow_16_to_32(irec); /*FALLTHRU*/ case sizeof(__uint32_t): irec->disk_nlinks.un32[ino_offset] = nlinks; break; default: ASSERT(0); } } __uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset) { switch (irec->nlink_size) { case sizeof(__uint8_t): return irec->disk_nlinks.un8[ino_offset]; case sizeof(__uint16_t): return irec->disk_nlinks.un16[ino_offset]; case sizeof(__uint32_t): return irec->disk_nlinks.un32[ino_offset]; default: ASSERT(0); } return 0; } static __uint8_t * alloc_ftypes_array( struct xfs_mount *mp) { __uint8_t *ptr; if (!xfs_sb_version_hasftype(&mp->m_sb)) return NULL; ptr = calloc(XFS_INODES_PER_CHUNK, sizeof(*ptr)); if (!ptr) do_error(_("could not allocate ftypes array\n")); return ptr; } /* * Next is the uncertain inode list -- a sorted (in ascending order) * list of inode records sorted on the starting inode number. There * is one list per ag. */ /* * Common code for creating inode records for use by trees and lists. * called only from add_inodes and add_inodes_uncertain * * IMPORTANT: all inodes (inode records) start off as free and * unconfirmed. */ static struct ino_tree_node * alloc_ino_node( struct xfs_mount *mp, xfs_agino_t starting_ino) { struct ino_tree_node *irec; irec = malloc(sizeof(*irec)); if (!irec) do_error(_("inode map malloc failed\n")); irec->avl_node.avl_nextino = NULL; irec->avl_node.avl_forw = NULL; irec->avl_node.avl_back = NULL; irec->ino_startnum = starting_ino; irec->ino_confirmed = 0; irec->ino_isa_dir = 0; irec->ino_was_rl = 0; irec->ino_is_rl = 0; irec->ir_free = (xfs_inofree_t) - 1; irec->ir_sparse = 0; irec->ino_un.ex_data = NULL; irec->nlink_size = sizeof(__uint8_t); irec->disk_nlinks.un8 = alloc_nlink_array(irec->nlink_size); irec->ftypes = alloc_ftypes_array(mp); return irec; } static void free_nlink_array(union ino_nlink nlinks, __uint8_t nlink_size) { switch (nlink_size) { case sizeof(__uint8_t): free(nlinks.un8); break; case sizeof(__uint16_t): free(nlinks.un16); break; case sizeof(__uint32_t): free(nlinks.un32); break; default: ASSERT(0); } } static void free_ino_tree_node( struct ino_tree_node *irec) { irec->avl_node.avl_nextino = NULL; irec->avl_node.avl_forw = NULL; irec->avl_node.avl_back = NULL; free_nlink_array(irec->disk_nlinks, irec->nlink_size); if (irec->ino_un.ex_data != NULL) { if (full_ino_ex_data) { free(irec->ino_un.ex_data->parents); free_nlink_array(irec->ino_un.ex_data->counted_nlinks, irec->nlink_size); } free(irec->ino_un.ex_data); } free(irec->ftypes); free(irec); } /* * last referenced cache for uncertain inodes */ static ino_tree_node_t **last_rec; /* * ok, the uncertain inodes are a set of trees just like the * good inodes but all starting inode records are (arbitrarily) * aligned on XFS_CHUNK_PER_INODE boundaries to prevent overlaps. * this means we may have partials records in the tree (e.g. records * without 64 confirmed uncertain inodes). Tough. * * free is set to 1 if the inode is thought to be free, 0 if used */ void add_aginode_uncertain( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino, int free) { ino_tree_node_t *ino_rec; xfs_agino_t s_ino; int offset; ASSERT(agno < glob_agcount); ASSERT(last_rec != NULL); s_ino = rounddown(ino, XFS_INODES_PER_CHUNK); /* * check for a cache hit */ if (last_rec[agno] != NULL && last_rec[agno]->ino_startnum == s_ino) { offset = ino - s_ino; if (free) set_inode_free(last_rec[agno], offset); else set_inode_used(last_rec[agno], offset); return; } /* * check to see if record containing inode is already in the tree. * if not, add it */ ino_rec = (ino_tree_node_t *) avl_findrange(inode_uncertain_tree_ptrs[agno], s_ino); if (!ino_rec) { ino_rec = alloc_ino_node(mp, s_ino); if (!avl_insert(inode_uncertain_tree_ptrs[agno], &ino_rec->avl_node)) do_error( _("add_aginode_uncertain - duplicate inode range\n")); } if (free) set_inode_free(ino_rec, ino - s_ino); else set_inode_used(ino_rec, ino - s_ino); /* * set cache entry */ last_rec[agno] = ino_rec; } /* * like add_aginode_uncertain() only it needs an xfs_mount_t * * to perform the inode number conversion. */ void add_inode_uncertain(xfs_mount_t *mp, xfs_ino_t ino, int free) { add_aginode_uncertain(mp, XFS_INO_TO_AGNO(mp, ino), XFS_INO_TO_AGINO(mp, ino), free); } /* * pull the indicated inode record out of the uncertain inode tree */ void get_uncertain_inode_rec(struct xfs_mount *mp, xfs_agnumber_t agno, ino_tree_node_t *ino_rec) { ASSERT(inode_tree_ptrs != NULL); ASSERT(agno < mp->m_sb.sb_agcount); ASSERT(inode_tree_ptrs[agno] != NULL); avl_delete(inode_uncertain_tree_ptrs[agno], &ino_rec->avl_node); ino_rec->avl_node.avl_nextino = NULL; ino_rec->avl_node.avl_forw = NULL; ino_rec->avl_node.avl_back = NULL; } ino_tree_node_t * findfirst_uncertain_inode_rec(xfs_agnumber_t agno) { return((ino_tree_node_t *) inode_uncertain_tree_ptrs[agno]->avl_firstino); } ino_tree_node_t * find_uncertain_inode_rec(xfs_agnumber_t agno, xfs_agino_t ino) { return((ino_tree_node_t *) avl_findrange(inode_uncertain_tree_ptrs[agno], ino)); } void clear_uncertain_ino_cache(xfs_agnumber_t agno) { last_rec[agno] = NULL; } /* * Next comes the inode trees. One per AG, AVL trees of inode records, each * inode record tracking 64 inodes */ /* * Set up an inode tree record for a group of inodes that will include the * requested inode. * * This does NOT do error-check for duplicate records. The caller is * responsible for checking that. Ino must be the start of an * XFS_INODES_PER_CHUNK (64) inode chunk * * Each inode resides in a 64-inode chunk which can be part one or more chunks * (MAX(64, inodes-per-block). The fs allocates in chunks (as opposed to 1 * chunk) when a block can hold more than one chunk (inodes per block > 64). * Allocating in one chunk pieces causes us problems when it takes more than * one fs block to contain an inode chunk because the chunks can start on * *any* block boundary. So we assume that the caller has a clue because at * this level, we don't. */ static struct ino_tree_node * add_inode( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino) { struct ino_tree_node *irec; irec = alloc_ino_node(mp, agino); if (!avl_insert(inode_tree_ptrs[agno], &irec->avl_node)) do_warn(_("add_inode - duplicate inode range\n")); return irec; } /* * pull the indicated inode record out of the inode tree */ void get_inode_rec(struct xfs_mount *mp, xfs_agnumber_t agno, ino_tree_node_t *ino_rec) { ASSERT(inode_tree_ptrs != NULL); ASSERT(agno < mp->m_sb.sb_agcount); ASSERT(inode_tree_ptrs[agno] != NULL); avl_delete(inode_tree_ptrs[agno], &ino_rec->avl_node); ino_rec->avl_node.avl_nextino = NULL; ino_rec->avl_node.avl_forw = NULL; ino_rec->avl_node.avl_back = NULL; } /* * free the designated inode record (return it to the free pool) */ /* ARGSUSED */ void free_inode_rec(xfs_agnumber_t agno, ino_tree_node_t *ino_rec) { free_ino_tree_node(ino_rec); } void find_inode_rec_range(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t start_ino, xfs_agino_t end_ino, ino_tree_node_t **first, ino_tree_node_t **last) { *first = *last = NULL; /* * Is the AG inside the file system ? */ if (agno < mp->m_sb.sb_agcount) avl_findranges(inode_tree_ptrs[agno], start_ino, end_ino, (avlnode_t **) first, (avlnode_t **) last); } /* * if ino doesn't exist, it must be properly aligned -- on a * filesystem block boundary or XFS_INODES_PER_CHUNK boundary, * whichever alignment is larger. */ ino_tree_node_t * set_inode_used_alloc(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino) { ino_tree_node_t *ino_rec; /* * check alignment -- the only way to detect this * is too see if the chunk overlaps another chunk * already in the tree */ ino_rec = add_inode(mp, agno, ino); ASSERT(ino_rec != NULL); ASSERT(ino >= ino_rec->ino_startnum && ino - ino_rec->ino_startnum < XFS_INODES_PER_CHUNK); set_inode_used(ino_rec, ino - ino_rec->ino_startnum); return(ino_rec); } ino_tree_node_t * set_inode_free_alloc(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino) { ino_tree_node_t *ino_rec; ino_rec = add_inode(mp, agno, ino); ASSERT(ino_rec != NULL); ASSERT(ino >= ino_rec->ino_startnum && ino - ino_rec->ino_startnum < XFS_INODES_PER_CHUNK); set_inode_free(ino_rec, ino - ino_rec->ino_startnum); return(ino_rec); } void print_inode_list_int(xfs_agnumber_t agno, int uncertain) { ino_tree_node_t *ino_rec; if (!uncertain) { fprintf(stderr, _("good inode list is --\n")); ino_rec = findfirst_inode_rec(agno); } else { fprintf(stderr, _("uncertain inode list is --\n")); ino_rec = findfirst_uncertain_inode_rec(agno); } if (ino_rec == NULL) { fprintf(stderr, _("agno %d -- no inodes\n"), agno); return; } printf(_("agno %d\n"), agno); while(ino_rec != NULL) { fprintf(stderr, _("\tptr = %lx, start = 0x%x, free = 0x%llx, confirmed = 0x%llx\n"), (unsigned long)ino_rec, ino_rec->ino_startnum, (unsigned long long)ino_rec->ir_free, (unsigned long long)ino_rec->ino_confirmed); if (ino_rec->ino_startnum == 0) ino_rec = ino_rec; ino_rec = next_ino_rec(ino_rec); } } void print_inode_list(xfs_agnumber_t agno) { print_inode_list_int(agno, 0); } void print_uncertain_inode_list(xfs_agnumber_t agno) { print_inode_list_int(agno, 1); } /* * set parent -- use a bitmask and a packed array. The bitmask * indicate which inodes have an entry in the array. An inode that * is the Nth bit set in the mask is stored in the Nth location in * the array where N starts at 0. */ void set_inode_parent( ino_tree_node_t *irec, int offset, xfs_ino_t parent) { parent_list_t *ptbl; int i; int cnt; int target; __uint64_t bitmask; parent_entry_t *tmp; if (full_ino_ex_data) ptbl = irec->ino_un.ex_data->parents; else ptbl = irec->ino_un.plist; if (ptbl == NULL) { ptbl = (parent_list_t *)malloc(sizeof(parent_list_t)); if (!ptbl) do_error(_("couldn't malloc parent list table\n")); if (full_ino_ex_data) irec->ino_un.ex_data->parents = ptbl; else irec->ino_un.plist = ptbl; ptbl->pmask = 1ULL << offset; ptbl->pentries = (xfs_ino_t*)memalign(sizeof(xfs_ino_t), sizeof(xfs_ino_t)); if (!ptbl->pentries) do_error(_("couldn't memalign pentries table\n")); #ifdef DEBUG ptbl->cnt = 1; #endif ptbl->pentries[0] = parent; return; } if (ptbl->pmask & (1ULL << offset)) { bitmask = 1ULL; target = 0; for (i = 0; i < offset; i++) { if (ptbl->pmask & bitmask) target++; bitmask <<= 1; } #ifdef DEBUG ASSERT(target < ptbl->cnt); #endif ptbl->pentries[target] = parent; return; } bitmask = 1ULL; cnt = target = 0; for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { if (ptbl->pmask & bitmask) { cnt++; if (i < offset) target++; } bitmask <<= 1; } #ifdef DEBUG ASSERT(cnt == ptbl->cnt); #endif ASSERT(cnt >= target); tmp = (xfs_ino_t*)memalign(sizeof(xfs_ino_t), (cnt + 1) * sizeof(xfs_ino_t)); if (!tmp) do_error(_("couldn't memalign pentries table\n")); memmove(tmp, ptbl->pentries, target * sizeof(parent_entry_t)); if (cnt > target) memmove(tmp + target + 1, ptbl->pentries + target, (cnt - target) * sizeof(parent_entry_t)); free(ptbl->pentries); ptbl->pentries = tmp; #ifdef DEBUG ptbl->cnt++; #endif ptbl->pentries[target] = parent; ptbl->pmask |= (1ULL << offset); } xfs_ino_t get_inode_parent(ino_tree_node_t *irec, int offset) { __uint64_t bitmask; parent_list_t *ptbl; int i; int target; if (full_ino_ex_data) ptbl = irec->ino_un.ex_data->parents; else ptbl = irec->ino_un.plist; if (ptbl->pmask & (1ULL << offset)) { bitmask = 1ULL; target = 0; for (i = 0; i < offset; i++) { if (ptbl->pmask & bitmask) target++; bitmask <<= 1; } #ifdef DEBUG ASSERT(target < ptbl->cnt); #endif return(ptbl->pentries[target]); } return(0LL); } void alloc_ex_data(ino_tree_node_t *irec) { parent_list_t *ptbl; ptbl = irec->ino_un.plist; irec->ino_un.ex_data = (ino_ex_data_t *)calloc(1, sizeof(ino_ex_data_t)); if (irec->ino_un.ex_data == NULL) do_error(_("could not malloc inode extra data\n")); irec->ino_un.ex_data->parents = ptbl; switch (irec->nlink_size) { case sizeof(__uint8_t): irec->ino_un.ex_data->counted_nlinks.un8 = alloc_nlink_array(irec->nlink_size); break; case sizeof(__uint16_t): irec->ino_un.ex_data->counted_nlinks.un16 = alloc_nlink_array(irec->nlink_size); break; case sizeof(__uint32_t): irec->ino_un.ex_data->counted_nlinks.un32 = alloc_nlink_array(irec->nlink_size); break; default: ASSERT(0); } } void add_ino_ex_data(xfs_mount_t *mp) { ino_tree_node_t *ino_rec; xfs_agnumber_t i; for (i = 0; i < mp->m_sb.sb_agcount; i++) { ino_rec = findfirst_inode_rec(i); while (ino_rec != NULL) { alloc_ex_data(ino_rec); ino_rec = next_ino_rec(ino_rec); } } full_ino_ex_data = 1; } static uintptr_t avl_ino_start(avlnode_t *node) { return((uintptr_t) ((ino_tree_node_t *) node)->ino_startnum); } static uintptr_t avl_ino_end(avlnode_t *node) { return((uintptr_t) ( ((ino_tree_node_t *) node)->ino_startnum + XFS_INODES_PER_CHUNK)); } avlops_t avl_ino_tree_ops = { avl_ino_start, avl_ino_end }; void incore_ino_init(xfs_mount_t *mp) { int i; int agcount = mp->m_sb.sb_agcount; if ((inode_tree_ptrs = malloc(agcount * sizeof(avltree_desc_t *))) == NULL) do_error(_("couldn't malloc inode tree descriptor table\n")); if ((inode_uncertain_tree_ptrs = malloc(agcount * sizeof(avltree_desc_t *))) == NULL) do_error( _("couldn't malloc uncertain ino tree descriptor table\n")); for (i = 0; i < agcount; i++) { if ((inode_tree_ptrs[i] = malloc(sizeof(avltree_desc_t))) == NULL) do_error(_("couldn't malloc inode tree descriptor\n")); if ((inode_uncertain_tree_ptrs[i] = malloc(sizeof(avltree_desc_t))) == NULL) do_error( _("couldn't malloc uncertain ino tree descriptor\n")); } for (i = 0; i < agcount; i++) { avl_init_tree(inode_tree_ptrs[i], &avl_ino_tree_ops); avl_init_tree(inode_uncertain_tree_ptrs[i], &avl_ino_tree_ops); } if ((last_rec = malloc(sizeof(ino_tree_node_t *) * agcount)) == NULL) do_error(_("couldn't malloc uncertain inode cache area\n")); memset(last_rec, 0, sizeof(ino_tree_node_t *) * agcount); full_ino_ex_data = 0; } xfsprogs-4.9.0+nmu1ubuntu2/repair/init.c0000644000000000000000000000562413063067172015073 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "globals.h" #include "agheader.h" #include "protos.h" #include "err_protos.h" #include "pthread.h" #include "avl.h" #include "bmap.h" #include "incore.h" #include "prefetch.h" #include static void ts_create(void) { pthread_key_create(&dblkmap_key, NULL); pthread_key_create(&ablkmap_key, NULL); } static void increase_rlimit(void) { struct rlimit rl; /* Increase limits */ if (getrlimit(RLIMIT_FSIZE, &rl) == -1) { perror("getrlimit"); fprintf(stderr, _("getrlimit(RLIMIT_FSIZE) failed!\n")); exit(1); } if (rl.rlim_cur != RLIM_INFINITY) { rl.rlim_max = rl.rlim_cur = RLIM_INFINITY; if (setrlimit(RLIMIT_FSIZE, &rl) == -1) { perror("setrlimit"); fprintf(stderr, _("setrlimit failed - current: %lld, max: %lld\n"), (unsigned long long)rl.rlim_cur, (unsigned long long)rl.rlim_max); exit(1); } } } void xfs_init(libxfs_init_t *args) { memset(args, 0, sizeof(libxfs_init_t)); if (isa_file) { args->disfile = 1; args->dname = fs_name; args->volname = NULL; } else { args->disfile = 0; args->volname = fs_name; args->dname = NULL; } if (log_spec) { /* External log specified */ args->logname = log_name; args->lisfile = (isa_file?1:0); /* XXX assume data file also means log file */ /* REVISIT: Need to do fs sanity / log validity checking */ } if (rt_spec) { /* RT device specified */ args->rtname = rt_name; args->risfile = (isa_file?1:0); /* XXX assume data file also means rt file */ } args->usebuflock = do_prefetch; args->setblksize = 0; args->isdirect = LIBXFS_DIRECT; if (no_modify) args->isreadonly = (LIBXFS_ISREADONLY | LIBXFS_ISINACTIVE); else if (dangerously) args->isreadonly = (LIBXFS_ISINACTIVE | LIBXFS_DANGEROUSLY); else args->isreadonly = LIBXFS_EXCLUSIVELY; if (!libxfs_init(args)) { /* would -d be an option? */ if (!no_modify && !dangerously) { args->isreadonly = (LIBXFS_ISINACTIVE | LIBXFS_DANGEROUSLY); if (libxfs_init(args)) fprintf(stderr, _("Unmount or use the dangerous (-d) option to repair a read-only mounted filesystem\n")); } do_error(_("couldn't initialize XFS library\n")); } ts_create(); increase_rlimit(); pftrace_init(); } xfsprogs-4.9.0+nmu1ubuntu2/repair/phase1.c0000644000000000000000000001027413063067173015307 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "globals.h" #include "agheader.h" #include "protos.h" #include "err_protos.h" static void no_sb(void) { do_warn(_("Sorry, could not find valid secondary superblock\n")); do_warn(_("Exiting now.\n")); exit(1); } char * alloc_ag_buf(int size) { char *bp; bp = (char *)memalign(libxfs_device_alignment(), size); if (!bp) do_error(_("could not allocate ag header buffer (%d bytes)\n"), size); return(bp); } /* * this has got to be big enough to hold 4 sectors */ #define MAX_SECTSIZE (512 * 1024) /* ARGSUSED */ void phase1(xfs_mount_t *mp) { xfs_sb_t *sb; char *ag_bp; int rval; do_log(_("Phase 1 - find and verify superblock...\n")); primary_sb_modified = 0; need_root_inode = 0; need_root_dotdot = 0; need_rbmino = 0; need_rsumino = 0; lost_quotas = 0; /* * get AG 0 into ag header buf */ ag_bp = alloc_ag_buf(MAX_SECTSIZE); sb = (xfs_sb_t *) ag_bp; rval = get_sb(sb, 0LL, MAX_SECTSIZE, 0); if (rval == XR_EOF) do_error(_("error reading primary superblock\n")); /* * is this really an sb, verify internal consistency */ if (rval != XR_OK) { do_warn(_("bad primary superblock - %s !!!\n"), err_string(rval)); if (!find_secondary_sb(sb)) no_sb(); primary_sb_modified = 1; } else if ((rval = verify_set_primary_sb(sb, 0, &primary_sb_modified)) != XR_OK) { do_warn(_("couldn't verify primary superblock - %s !!!\n"), err_string(rval)); if (!find_secondary_sb(sb)) no_sb(); primary_sb_modified = 1; } /* * Check bad_features2 and make sure features2 the same as * bad_features (ORing the two together). Leave bad_features2 * set so older kernels can still use it and not mount unsupported * filesystems when it reads bad_features2. */ if (sb->sb_bad_features2 != 0 && sb->sb_bad_features2 != sb->sb_features2) { sb->sb_features2 |= sb->sb_bad_features2; sb->sb_bad_features2 = sb->sb_features2; primary_sb_modified = 1; do_warn(_("superblock has a features2 mismatch, correcting\n")); } /* * apply any version changes or conversions after the primary * superblock has been verified or repaired * * Send output to stdout as do_log and everything else in repair * is sent to stderr and there is no "quiet" option. xfs_admin * will filter stderr but not stdout. This situation must be improved. */ if (convert_lazy_count) { if (lazy_count && !xfs_sb_version_haslazysbcount(sb)) { sb->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; sb->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT; sb->sb_bad_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT; primary_sb_modified = 1; printf(_("Enabling lazy-counters\n")); } else if (!lazy_count && xfs_sb_version_haslazysbcount(sb)) { if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) { printf( _("Cannot disable lazy-counters on V5 fs\n")); exit(1); } sb->sb_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT; sb->sb_bad_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT; printf(_("Disabling lazy-counters\n")); primary_sb_modified = 1; } else { printf(_("Lazy-counters are already %s\n"), lazy_count ? _("enabled") : _("disabled")); exit(0); /* no conversion required, exit */ } } if (primary_sb_modified) { if (!no_modify) { do_warn(_("writing modified primary superblock\n")); write_primary_sb(sb, sb->sb_sectsize); } else { do_warn(_("would write modified primary superblock\n")); } } /* * misc. global var initialization */ sb_ifree = sb_icount = sb_fdblocks = sb_frextents = 0; free(sb); } xfsprogs-4.9.0+nmu1ubuntu2/repair/phase2.c0000644000000000000000000001566413063067172015317 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "protos.h" #include "err_protos.h" #include "incore.h" #include "progress.h" #include "scan.h" void set_mp(xfs_mount_t *mpp); /* workaround craziness in the xlog routines */ int xlog_recover_do_trans(struct xlog *log, xlog_recover_t *t, int p) { return 0; } static void zero_log( struct xfs_mount *mp) { int error; xfs_daddr_t head_blk; xfs_daddr_t tail_blk; struct xlog *log = mp->m_log; memset(log, 0, sizeof(struct xlog)); x.logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); x.logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); x.lbsize = BBSIZE; if (xfs_sb_version_hassector(&mp->m_sb)) x.lbsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT); log->l_dev = mp->m_logdev_targp; log->l_logBBsize = x.logBBsize; log->l_logBBstart = x.logBBstart; log->l_sectBBsize = BTOBB(x.lbsize); log->l_mp = mp; if (xfs_sb_version_hassector(&mp->m_sb)) { log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; ASSERT(log->l_sectbb_log <= mp->m_sectbb_log); /* for larger sector sizes, must have v2 or external log */ ASSERT(log->l_sectbb_log == 0 || log->l_logBBstart == 0 || xfs_sb_version_haslogv2(&mp->m_sb)); ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT); } log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; /* * Find the log head and tail and alert the user to the situation if the * log appears corrupted or contains data. In either case, we do not * proceed past this point unless the user explicitly requests to zap * the log. */ error = xlog_find_tail(log, &head_blk, &tail_blk); if (error) { do_warn( _("zero_log: cannot find log head/tail (xlog_find_tail=%d)\n"), error); if (!no_modify && !zap_log) do_warn(_( "ERROR: The log head and/or tail cannot be discovered. Attempt to mount the\n" "filesystem to replay the log or use the -L option to destroy the log and\n" "attempt a repair.\n")); exit(2); } else { if (verbose) { do_warn( _("zero_log: head block %" PRId64 " tail block %" PRId64 "\n"), head_blk, tail_blk); } if (!no_modify && head_blk != tail_blk) { if (zap_log) { do_warn(_( "ALERT: The filesystem has valuable metadata changes in a log which is being\n" "destroyed because the -L option was used.\n")); } else { do_warn(_( "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running xfs_repair. If you are unable to mount the filesystem, then use\n" "the -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n")); exit(2); } } } /* * Only clear the log when explicitly requested. Doing so is unnecessary * unless something is wrong. Further, this resets the current LSN of * the filesystem and creates more work for repair of v5 superblock * filesystems. */ if (!no_modify && zap_log) { libxfs_log_clear(log->l_dev, NULL, XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart), (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks), &mp->m_sb.sb_uuid, xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1, mp->m_sb.sb_logsunit, XLOG_FMT, XLOG_INIT_CYCLE, true); /* update the log data structure with new state */ error = xlog_find_tail(log, &head_blk, &tail_blk); if (error || head_blk != tail_blk) do_error(_("failed to clear log")); } /* * Finally, seed the max LSN from the current state of the log if this * is a v5 filesystem. */ if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_max_lsn = log->l_last_sync_lsn; } /* * ok, at this point, the fs is mounted but the root inode may be * trashed and the ag headers haven't been checked. So we have * a valid xfs_mount_t and superblock but that's about it. That * means we can use macros that use mount/sb fields in calculations * but I/O or btree routines that depend on space maps or inode maps * being correct are verboten. */ void phase2( struct xfs_mount *mp, int scan_threads) { int j; ino_tree_node_t *ino_rec; /* now we can start using the buffer cache routines */ set_mp(mp); /* Check whether this fs has internal or external log */ if (mp->m_sb.sb_logstart == 0) { if (!x.logname) do_error(_("This filesystem has an external log. " "Specify log device with the -l option.\n")); do_log(_("Phase 2 - using external log on %s\n"), x.logname); } else do_log(_("Phase 2 - using internal log\n")); /* Zero log if applicable */ do_log(_(" - zero log...\n")); zero_log(mp); do_log(_(" - scan filesystem freespace and inode maps...\n")); bad_ino_btree = 0; set_progress_msg(PROG_FMT_SCAN_AG, (__uint64_t) glob_agcount); scan_ags(mp, scan_threads); print_final_rpt(); /* * make sure we know about the root inode chunk */ if ((ino_rec = find_inode_rec(mp, 0, mp->m_sb.sb_rootino)) == NULL) { ASSERT(mp->m_sb.sb_rbmino == mp->m_sb.sb_rootino + 1 && mp->m_sb.sb_rsumino == mp->m_sb.sb_rootino + 2); do_warn(_("root inode chunk not found\n")); /* * mark the first 3 used, the rest are free */ ino_rec = set_inode_used_alloc(mp, 0, (xfs_agino_t) mp->m_sb.sb_rootino); set_inode_used(ino_rec, 1); set_inode_used(ino_rec, 2); for (j = 3; j < XFS_INODES_PER_CHUNK; j++) set_inode_free(ino_rec, j); /* * also mark blocks */ set_bmap_ext(0, XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino), mp->m_ialloc_blks, XR_E_INO); } else { do_log(_(" - found root inode chunk\n")); /* * blocks are marked, just make sure they're in use */ if (is_inode_free(ino_rec, 0)) { do_warn(_("root inode marked free, ")); set_inode_used(ino_rec, 0); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } if (is_inode_free(ino_rec, 1)) { do_warn(_("realtime bitmap inode marked free, ")); set_inode_used(ino_rec, 1); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } if (is_inode_free(ino_rec, 2)) { do_warn(_("realtime summary inode marked free, ")); set_inode_used(ino_rec, 2); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } } } xfsprogs-4.9.0+nmu1ubuntu2/repair/phase3.c0000644000000000000000000001037313063067172015310 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "threads.h" #include "prefetch.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "progress.h" #include "bmap.h" #include "threads.h" static void process_agi_unlinked( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_buf *bp; struct xfs_agi *agip; xfs_agnumber_t i; int agi_dirty = 0; bp = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), mp->m_sb.sb_sectsize/BBSIZE, 0, &xfs_agi_buf_ops); if (!bp) do_error(_("cannot read agi block %" PRId64 " for ag %u\n"), XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), agno); agip = XFS_BUF_TO_AGI(bp); ASSERT(be32_to_cpu(agip->agi_seqno) == agno); for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) { if (agip->agi_unlinked[i] != cpu_to_be32(NULLAGINO)) { agip->agi_unlinked[i] = cpu_to_be32(NULLAGINO); agi_dirty = 1; } } if (agi_dirty) libxfs_writebuf(bp, 0); else libxfs_putbuf(bp); } static void process_ag_func( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { /* * turn on directory processing (inode discovery) and * attribute processing (extra_attr_check) */ wait_for_inode_prefetch(arg); do_log(_(" - agno = %d\n"), agno); process_aginodes(wq->mp, arg, agno, 1, 0, 1); blkmap_free_final(); cleanup_inode_prefetch(arg); } static void process_ags( xfs_mount_t *mp) { do_inode_prefetch(mp, ag_stride, process_ag_func, false, false); } static void do_uncertain_aginodes( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { int *count = arg; *count = process_uncertain_aginodes(wq->mp, agno); #ifdef XR_INODE_TRACE fprintf(stderr, "\t\t phase 3 - ag %d process_uncertain_inodes returns %d\n", *count, j); #endif PROG_RPT_INC(prog_rpt_done[agno], 1); } void phase3( struct xfs_mount *mp, int scan_threads) { int i, j; int *counts; work_queue_t wq; do_log(_("Phase 3 - for each AG...\n")); if (!no_modify) do_log(_(" - scan and clear agi unlinked lists...\n")); else do_log(_(" - scan (but don't clear) agi unlinked lists...\n")); set_progress_msg(PROG_FMT_AGI_UNLINKED, (__uint64_t) glob_agcount); /* first clear the agi unlinked AGI list */ if (!no_modify) { for (i = 0; i < mp->m_sb.sb_agcount; i++) process_agi_unlinked(mp, i); } /* now look at possibly bogus inodes */ for (i = 0; i < mp->m_sb.sb_agcount; i++) { check_uncertain_aginodes(mp, i); PROG_RPT_INC(prog_rpt_done[i], 1); } print_final_rpt(); /* ok, now that the tree's ok, let's take a good look */ do_log(_( " - process known inodes and perform inode discovery...\n")); set_progress_msg(PROG_FMT_PROCESS_INO, (__uint64_t) mp->m_sb.sb_icount); process_ags(mp); print_final_rpt(); /* * process newly discovered inode chunks */ do_log(_(" - process newly discovered inodes...\n")); set_progress_msg(PROG_FMT_NEW_INODES, (__uint64_t) glob_agcount); counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount); if (!counts) { do_abort(_("no memory for uncertain inode counts\n")); return; } do { /* * have to loop until no ag has any uncertain * inodes */ j = 0; memset(counts, 0, mp->m_sb.sb_agcount * sizeof(*counts)); create_work_queue(&wq, mp, scan_threads); for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, do_uncertain_aginodes, i, &counts[i]); destroy_work_queue(&wq); /* tally up the counts */ for (i = 0; i < mp->m_sb.sb_agcount; i++) j += counts[i]; } while (j != 0); free(counts); print_final_rpt(); } xfsprogs-4.9.0+nmu1ubuntu2/repair/phase4.c0000644000000000000000000002474213063067172015316 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "threads.h" #include "prefetch.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "bmap.h" #include "versions.h" #include "dir2.h" #include "progress.h" #include "slab.h" #include "rmap.h" bool collect_rmaps; /* * null out quota inode fields in sb if they point to non-existent inodes. * this isn't as redundant as it looks since it's possible that the sb field * might be set but the imap and inode(s) agree that the inode is * free in which case they'd never be cleared so the fields wouldn't * be cleared by process_dinode(). */ static void quotino_check(xfs_mount_t *mp) { ino_tree_node_t *irec; if (mp->m_sb.sb_uquotino != NULLFSINO && mp->m_sb.sb_uquotino != 0) { if (verify_inum(mp, mp->m_sb.sb_uquotino)) irec = NULL; else irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_uquotino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)); if (irec == NULL || is_inode_free(irec, mp->m_sb.sb_uquotino - irec->ino_startnum)) { mp->m_sb.sb_uquotino = NULLFSINO; lost_uquotino = 1; } else lost_uquotino = 0; } if (mp->m_sb.sb_gquotino != NULLFSINO && mp->m_sb.sb_gquotino != 0) { if (verify_inum(mp, mp->m_sb.sb_gquotino)) irec = NULL; else irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_gquotino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)); if (irec == NULL || is_inode_free(irec, mp->m_sb.sb_gquotino - irec->ino_startnum)) { mp->m_sb.sb_gquotino = NULLFSINO; lost_gquotino = 1; } else lost_gquotino = 0; } if (mp->m_sb.sb_pquotino != NULLFSINO && mp->m_sb.sb_pquotino != 0) { if (verify_inum(mp, mp->m_sb.sb_pquotino)) irec = NULL; else irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_pquotino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino)); if (irec == NULL || is_inode_free(irec, mp->m_sb.sb_pquotino - irec->ino_startnum)) { mp->m_sb.sb_pquotino = NULLFSINO; lost_pquotino = 1; } else lost_pquotino = 0; } } static void quota_sb_check(xfs_mount_t *mp) { /* * if the sb says we have quotas and we lost both, * signal a superblock downgrade. that will cause * the quota flags to get zeroed. (if we only lost * one quota inode, do nothing and complain later.) * * if the sb says we have quotas but we didn't start out * with any quota inodes, signal a superblock downgrade. * * The sb downgrades are so that older systems can mount * the filesystem. * * if the sb says we don't have quotas but it looks like * we do have quota inodes, then signal a superblock upgrade. * * if the sb says we don't have quotas and we have no * quota inodes, then leave will enough alone. */ if (fs_quotas && (mp->m_sb.sb_uquotino == NULLFSINO || mp->m_sb.sb_uquotino == 0) && (mp->m_sb.sb_gquotino == NULLFSINO || mp->m_sb.sb_gquotino == 0) && (mp->m_sb.sb_pquotino == NULLFSINO || mp->m_sb.sb_pquotino == 0)) { lost_quotas = 1; fs_quotas = 0; } else if (!verify_inum(mp, mp->m_sb.sb_uquotino) && !verify_inum(mp, mp->m_sb.sb_gquotino) && !verify_inum(mp, mp->m_sb.sb_pquotino)) { fs_quotas = 1; } } static void process_ag_func( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { wait_for_inode_prefetch(arg); do_log(_(" - agno = %d\n"), agno); process_aginodes(wq->mp, arg, agno, 0, 1, 0); blkmap_free_final(); cleanup_inode_prefetch(arg); /* * now recycle the per-AG duplicate extent records */ release_dup_extent_tree(agno); } static void process_ags( xfs_mount_t *mp) { xfs_agnumber_t i; int error; do_inode_prefetch(mp, ag_stride, process_ag_func, true, false); for (i = 0; i < mp->m_sb.sb_agcount; i++) { error = rmap_finish_collecting_fork_recs(mp, i); if (error) do_error( _("unable to finish adding attr/data fork reverse-mapping data for AG %u.\n"), i); } } static void check_rmap_btrees( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { int error; error = rmap_add_fixed_ag_rec(wq->mp, agno); if (error) do_error( _("unable to add AG %u metadata reverse-mapping data.\n"), agno); error = rmap_fold_raw_recs(wq->mp, agno); if (error) do_error( _("unable to merge AG %u metadata reverse-mapping data.\n"), agno); error = rmaps_verify_btree(wq->mp, agno); if (error) do_error( _("%s while checking reverse-mappings"), strerror(-error)); } static void compute_ag_refcounts( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { int error; error = compute_refcounts(wq->mp, agno); if (error) do_error( _("%s while computing reference count records.\n"), strerror(-error)); } static void process_inode_reflink_flags( struct work_queue *wq, xfs_agnumber_t agno, void *arg) { int error; error = fix_inode_reflink_flags(wq->mp, agno); if (error) do_error( _("%s while fixing inode reflink flags.\n"), strerror(-error)); } static void check_refcount_btrees( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { int error; error = check_refcounts(wq->mp, agno); if (error) do_error( _("%s while checking reference counts"), strerror(-error)); } static void process_rmap_data( struct xfs_mount *mp) { struct work_queue wq; xfs_agnumber_t i; if (!rmap_needs_work(mp)) return; create_work_queue(&wq, mp, libxfs_nproc()); for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, check_rmap_btrees, i, NULL); destroy_work_queue(&wq); if (!xfs_sb_version_hasreflink(&mp->m_sb)) return; create_work_queue(&wq, mp, libxfs_nproc()); for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, compute_ag_refcounts, i, NULL); destroy_work_queue(&wq); create_work_queue(&wq, mp, libxfs_nproc()); for (i = 0; i < mp->m_sb.sb_agcount; i++) { queue_work(&wq, process_inode_reflink_flags, i, NULL); queue_work(&wq, check_refcount_btrees, i, NULL); } destroy_work_queue(&wq); } void phase4(xfs_mount_t *mp) { ino_tree_node_t *irec; xfs_rtblock_t bno; xfs_rtblock_t rt_start; xfs_extlen_t rt_len; xfs_agnumber_t i; xfs_agblock_t j; xfs_agblock_t ag_end; xfs_extlen_t blen; int ag_hdr_len = 4 * mp->m_sb.sb_sectsize; int ag_hdr_block; int bstate; if (rmap_needs_work(mp)) collect_rmaps = true; ag_hdr_block = howmany(ag_hdr_len, mp->m_sb.sb_blocksize); do_log(_("Phase 4 - check for duplicate blocks...\n")); do_log(_(" - setting up duplicate extent list...\n")); set_progress_msg(PROG_FMT_DUP_EXTENT, (__uint64_t) glob_agcount); irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)); /* * we always have a root inode, even if it's free... * if the root is free, forget it, lost+found is already gone */ if (is_inode_free(irec, 0) || !inode_isadir(irec, 0)) { need_root_inode = 1; if (no_modify) do_warn(_("root inode would be lost\n")); else do_warn(_("root inode lost\n")); } for (i = 0; i < mp->m_sb.sb_agcount; i++) { ag_end = (i < mp->m_sb.sb_agcount - 1) ? mp->m_sb.sb_agblocks : mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * i; /* * set up duplicate extent list for this ag */ for (j = ag_hdr_block; j < ag_end; j += blen) { bstate = get_bmap_ext(i, j, ag_end, &blen); switch (bstate) { case XR_E_BAD_STATE: default: do_warn( _("unknown block state, ag %d, block %d\n"), i, j); /* fall through .. */ case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: case XR_E_INUSE: case XR_E_INUSE_FS: case XR_E_INO: case XR_E_FS_MAP: break; case XR_E_MULT: add_dup_extent(i, j, blen); break; } } PROG_RPT_INC(prog_rpt_done[i], 1); } print_final_rpt(); /* * initialize realtime bitmap */ rt_start = 0; rt_len = 0; for (bno = 0; bno < mp->m_sb.sb_rextents; bno++) { bstate = get_rtbmap(bno); switch (bstate) { case XR_E_BAD_STATE: default: do_warn( _("unknown rt extent state, extent %" PRIu64 "\n"), bno); /* fall through .. */ case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: case XR_E_INUSE: case XR_E_INUSE_FS: case XR_E_INO: case XR_E_FS_MAP: if (rt_start == 0) continue; else { /* * add extent and reset extent state */ add_rt_dup_extent(rt_start, rt_len); rt_start = 0; rt_len = 0; } break; case XR_E_MULT: if (rt_start == 0) { rt_start = bno; rt_len = 1; } else if (rt_len == MAXEXTLEN) { /* * large extent case */ add_rt_dup_extent(rt_start, rt_len); rt_start = bno; rt_len = 1; } else rt_len++; break; } } /* * catch tail-case, extent hitting the end of the ag */ if (rt_start != 0) add_rt_dup_extent(rt_start, rt_len); /* * initialize bitmaps for all AGs */ reset_bmaps(mp); do_log(_(" - check for inodes claiming duplicate blocks...\n")); set_progress_msg(PROG_FMT_DUP_BLOCKS, (__uint64_t) mp->m_sb.sb_icount); /* * ok, now process the inodes -- signal 2-pass check per inode. * first pass checks if the inode conflicts with a known * duplicate extent. if so, the inode is cleared and second * pass is skipped. second pass sets the block bitmap * for all blocks claimed by the inode. directory * and attribute processing is turned OFF since we did that * already in phase 3. */ process_ags(mp); /* * Process all the reverse-mapping data that we collected. This * involves checking the rmap data against the btree, computing * reference counts based on the rmap data, and checking the counts * against the refcount btree. */ process_rmap_data(mp); print_final_rpt(); /* * free up memory used to track trealtime duplicate extents */ if (rt_start != 0) free_rt_dup_extent_tree(mp); /* * ensure consistency of quota inode pointers in superblock, * make sure they point to real inodes */ quotino_check(mp); quota_sb_check(mp); } xfsprogs-4.9.0+nmu1ubuntu2/repair/phase5.c0000644000000000000000000021311613063067172015312 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "rt.h" #include "versions.h" #include "threads.h" #include "progress.h" #include "slab.h" #include "rmap.h" /* * we maintain the current slice (path from root to leaf) * of the btree incore. when we need a new block, we ask * the block allocator for the address of a block on that * level, map the block in, and set up the appropriate * pointers (child, silbing, etc.) and keys that should * point to the new block. */ typedef struct bt_stat_level { /* * set in setup_cursor routine and maintained in the tree-building * routines */ xfs_buf_t *buf_p; /* 2 buffer pointers to ... */ xfs_buf_t *prev_buf_p; xfs_agblock_t agbno; /* current block being filled */ xfs_agblock_t prev_agbno; /* previous block */ /* * set in calculate/init cursor routines for each btree level */ int num_recs_tot; /* # tree recs in level */ int num_blocks; /* # tree blocks in level */ int num_recs_pb; /* num_recs_tot / num_blocks */ int modulo; /* num_recs_tot % num_blocks */ } bt_stat_level_t; typedef struct bt_status { int init; /* cursor set up once? */ int num_levels; /* # of levels in btree */ xfs_extlen_t num_tot_blocks; /* # blocks alloc'ed for tree */ xfs_extlen_t num_free_blocks;/* # blocks currently unused */ xfs_agblock_t root; /* root block */ /* * list of blocks to be used to set up this tree * and pointer to the first unused block on the list */ xfs_agblock_t *btree_blocks; /* block list */ xfs_agblock_t *free_btree_blocks; /* first unused block */ /* * per-level status info */ bt_stat_level_t level[XFS_BTREE_MAXLEVELS]; uint64_t owner; /* owner */ } bt_status_t; /* * extra metadata for the agi */ struct agi_stat { xfs_agino_t first_agino; xfs_agino_t count; xfs_agino_t freecount; }; static __uint64_t *sb_icount_ag; /* allocated inodes per ag */ static __uint64_t *sb_ifree_ag; /* free inodes per ag */ static __uint64_t *sb_fdblocks_ag; /* free data blocks per ag */ static int mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) { int in_extent; int num_extents; xfs_agblock_t extent_start; xfs_extlen_t extent_len; xfs_agblock_t agbno; xfs_agblock_t ag_end; uint free_blocks; xfs_extlen_t blen; int bstate; /* * scan the bitmap for the ag looking for continuous * extents of free blocks. At this point, we know * that blocks in the bitmap are either set to an * "in use" state or set to unknown (0) since the * bmaps were zero'ed in phase 4 and only blocks * being used by inodes, inode bmaps, ag headers, * and the files themselves were put into the bitmap. * */ ASSERT(agno < mp->m_sb.sb_agcount); extent_start = extent_len = 0; in_extent = 0; num_extents = free_blocks = 0; if (agno < mp->m_sb.sb_agcount - 1) ag_end = mp->m_sb.sb_agblocks; else ag_end = mp->m_sb.sb_dblocks - (xfs_rfsblock_t)mp->m_sb.sb_agblocks * (mp->m_sb.sb_agcount - 1); /* * ok, now find the number of extents, keep track of the * largest extent. */ for (agbno = 0; agbno < ag_end; agbno += blen) { bstate = get_bmap_ext(agno, agbno, ag_end, &blen); if (bstate < XR_E_INUSE) { free_blocks += blen; if (in_extent == 0) { /* * found the start of a free extent */ in_extent = 1; num_extents++; extent_start = agbno; extent_len = blen; } else { extent_len += blen; } } else { if (in_extent) { /* * free extent ends here, add extent to the * 2 incore extent (avl-to-be-B+) trees */ in_extent = 0; #if defined(XR_BLD_FREE_TRACE) && defined(XR_BLD_ADD_EXTENT) fprintf(stderr, "adding extent %u [%u %u]\n", agno, extent_start, extent_len); #endif add_bno_extent(agno, extent_start, extent_len); add_bcnt_extent(agno, extent_start, extent_len); } } } if (in_extent) { /* * free extent ends here */ #if defined(XR_BLD_FREE_TRACE) && defined(XR_BLD_ADD_EXTENT) fprintf(stderr, "adding extent %u [%u %u]\n", agno, extent_start, extent_len); #endif add_bno_extent(agno, extent_start, extent_len); add_bcnt_extent(agno, extent_start, extent_len); } return(num_extents); } static xfs_agblock_t get_next_blockaddr(xfs_agnumber_t agno, int level, bt_status_t *curs) { ASSERT(curs->free_btree_blocks < curs->btree_blocks + curs->num_tot_blocks); ASSERT(curs->num_free_blocks > 0); curs->num_free_blocks--; return(*curs->free_btree_blocks++); } /* * set up the dynamically allocated block allocation data in the btree * cursor that depends on the info in the static portion of the cursor. * allocates space from the incore bno/bcnt extent trees and sets up * the first path up the left side of the tree. Also sets up the * cursor pointer to the btree root. called by init_freespace_cursor() * and init_ino_cursor() */ static void setup_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *curs) { int j; unsigned int u; xfs_extlen_t big_extent_len; xfs_agblock_t big_extent_start; extent_tree_node_t *ext_ptr; extent_tree_node_t *bno_ext_ptr; xfs_extlen_t blocks_allocated; xfs_agblock_t *agb_ptr; int error; /* * get the number of blocks we need to allocate, then * set up block number array, set the free block pointer * to the first block in the array, and null the array */ big_extent_len = curs->num_tot_blocks; blocks_allocated = 0; ASSERT(big_extent_len > 0); if ((curs->btree_blocks = malloc(sizeof(xfs_agblock_t) * big_extent_len)) == NULL) do_error(_("could not set up btree block array\n")); agb_ptr = curs->free_btree_blocks = curs->btree_blocks; for (j = 0; j < curs->num_free_blocks; j++, agb_ptr++) *agb_ptr = NULLAGBLOCK; /* * grab the smallest extent and use it up, then get the * next smallest. This mimics the init_*_cursor code. */ ext_ptr = findfirst_bcnt_extent(agno); agb_ptr = curs->btree_blocks; /* * set up the free block array */ while (blocks_allocated < big_extent_len) { if (!ext_ptr) do_error( _("error - not enough free space in filesystem\n")); /* * use up the extent we've got */ for (u = 0; u < ext_ptr->ex_blockcount && blocks_allocated < big_extent_len; u++) { ASSERT(agb_ptr < curs->btree_blocks + curs->num_tot_blocks); *agb_ptr++ = ext_ptr->ex_startblock + u; blocks_allocated++; } error = rmap_add_ag_rec(mp, agno, ext_ptr->ex_startblock, u, curs->owner); if (error) do_error(_("could not set up btree rmaps: %s\n"), strerror(-error)); /* * if we only used part of this last extent, then we * need only to reset the extent in the extent * trees and we're done */ if (u < ext_ptr->ex_blockcount) { big_extent_start = ext_ptr->ex_startblock + u; big_extent_len = ext_ptr->ex_blockcount - u; ASSERT(big_extent_len > 0); bno_ext_ptr = find_bno_extent(agno, ext_ptr->ex_startblock); ASSERT(bno_ext_ptr != NULL); get_bno_extent(agno, bno_ext_ptr); release_extent_tree_node(bno_ext_ptr); ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); release_extent_tree_node(ext_ptr); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "releasing extent: %u [%u %u]\n", agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); fprintf(stderr, "blocks_allocated = %d\n", blocks_allocated); #endif add_bno_extent(agno, big_extent_start, big_extent_len); add_bcnt_extent(agno, big_extent_start, big_extent_len); return; } /* * delete the used-up extent from both extent trees and * find next biggest extent */ #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "releasing extent: %u [%u %u]\n", agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); #endif bno_ext_ptr = find_bno_extent(agno, ext_ptr->ex_startblock); ASSERT(bno_ext_ptr != NULL); get_bno_extent(agno, bno_ext_ptr); release_extent_tree_node(bno_ext_ptr); ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); ASSERT(ext_ptr != NULL); release_extent_tree_node(ext_ptr); ext_ptr = findfirst_bcnt_extent(agno); } #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "blocks_allocated = %d\n", blocks_allocated); #endif } static void write_cursor(bt_status_t *curs) { int i; for (i = 0; i < curs->num_levels; i++) { #if defined(XR_BLD_FREE_TRACE) || defined(XR_BLD_INO_TRACE) fprintf(stderr, "writing bt block %u\n", curs->level[i].agbno); #endif if (curs->level[i].prev_buf_p != NULL) { ASSERT(curs->level[i].prev_agbno != NULLAGBLOCK); #if defined(XR_BLD_FREE_TRACE) || defined(XR_BLD_INO_TRACE) fprintf(stderr, "writing bt prev block %u\n", curs->level[i].prev_agbno); #endif libxfs_writebuf(curs->level[i].prev_buf_p, 0); } libxfs_writebuf(curs->level[i].buf_p, 0); } } static void finish_cursor(bt_status_t *curs) { ASSERT(curs->num_free_blocks == 0); free(curs->btree_blocks); } /* * We need to leave some free records in the tree for the corner case of * setting up the AGFL. This may require allocation of blocks, and as * such can require insertion of new records into the tree (e.g. moving * a record in the by-count tree when a long extent is shortened). If we * pack the records into the leaves with no slack space, this requires a * leaf split to occur and a block to be allocated from the free list. * If we don't have any blocks on the free list (because we are setting * it up!), then we fail, and the filesystem will fail with the same * failure at runtime. Hence leave a couple of records slack space in * each block to allow immediate modification of the tree without * requiring splits to be done. * * XXX(hch): any reason we don't just look at mp->m_alloc_mxr? */ #define XR_ALLOC_BLOCK_MAXRECS(mp, level) \ (libxfs_allocbt_maxrecs((mp), (mp)->m_sb.sb_blocksize, (level) == 0) - 2) /* * this calculates a freespace cursor for an ag. * btree_curs is an in/out. returns the number of * blocks that will show up in the AGFL. */ static int calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t *extents, bt_status_t *btree_curs) { xfs_extlen_t blocks_needed; /* a running count */ xfs_extlen_t blocks_allocated_pt; /* per tree */ xfs_extlen_t blocks_allocated_total; /* for both trees */ xfs_agblock_t num_extents; int i; int extents_used; int extra_blocks; bt_stat_level_t *lptr; bt_stat_level_t *p_lptr; extent_tree_node_t *ext_ptr; int level; num_extents = *extents; extents_used = 0; ASSERT(num_extents != 0); lptr = &btree_curs->level[0]; btree_curs->init = 1; /* * figure out how much space we need for the leaf level * of the tree and set up the cursor for the leaf level * (note that the same code is duplicated further down) */ lptr->num_blocks = howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0)); lptr->num_recs_pb = num_extents / lptr->num_blocks; lptr->modulo = num_extents % lptr->num_blocks; lptr->num_recs_tot = num_extents; level = 1; #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "%s 0 %d %d %d %d\n", __func__, lptr->num_blocks, lptr->num_recs_pb, lptr->modulo, lptr->num_recs_tot); #endif /* * if we need more levels, set them up. # of records * per level is the # of blocks in the level below it */ if (lptr->num_blocks > 1) { for (; btree_curs->level[level - 1].num_blocks > 1 && level < XFS_BTREE_MAXLEVELS; level++) { lptr = &btree_curs->level[level]; p_lptr = &btree_curs->level[level - 1]; lptr->num_blocks = howmany(p_lptr->num_blocks, XR_ALLOC_BLOCK_MAXRECS(mp, level)); lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; lptr->num_recs_pb = p_lptr->num_blocks / lptr->num_blocks; lptr->num_recs_tot = p_lptr->num_blocks; #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "%s %d %d %d %d %d\n", __func__, level, lptr->num_blocks, lptr->num_recs_pb, lptr->modulo, lptr->num_recs_tot); #endif } } ASSERT(lptr->num_blocks == 1); btree_curs->num_levels = level; /* * ok, now we have a hypothetical cursor that * will work for both the bno and bcnt trees. * now figure out if using up blocks to set up the * trees will perturb the shape of the freespace tree. * if so, we've over-allocated. the freespace trees * as they will be *after* accounting for the free space * we've used up will need fewer blocks to to represent * than we've allocated. We can use the AGFL to hold * XFS_AGFL_SIZE (sector/xfs_agfl_t) blocks but that's it. * Thus we limit things to XFS_AGFL_SIZE/2 for each of the 2 btrees. * if the number of extra blocks is more than that, * we'll have to be called again. */ for (blocks_needed = 0, i = 0; i < level; i++) { blocks_needed += btree_curs->level[i].num_blocks; } /* * record the # of blocks we've allocated */ blocks_allocated_pt = blocks_needed; blocks_needed *= 2; blocks_allocated_total = blocks_needed; /* * figure out how many free extents will be used up by * our space allocation */ if ((ext_ptr = findfirst_bcnt_extent(agno)) == NULL) do_error(_("can't rebuild fs trees -- not enough free space " "on ag %u\n"), agno); while (ext_ptr != NULL && blocks_needed > 0) { if (ext_ptr->ex_blockcount <= blocks_needed) { blocks_needed -= ext_ptr->ex_blockcount; extents_used++; } else { blocks_needed = 0; } ext_ptr = findnext_bcnt_extent(agno, ext_ptr); #ifdef XR_BLD_FREE_TRACE if (ext_ptr != NULL) { fprintf(stderr, "got next extent [%u %u]\n", ext_ptr->ex_startblock, ext_ptr->ex_blockcount); } else { fprintf(stderr, "out of extents\n"); } #endif } if (blocks_needed > 0) do_error(_("ag %u - not enough free space to build freespace " "btrees\n"), agno); ASSERT(num_extents >= extents_used); num_extents -= extents_used; /* * see if the number of leaf blocks will change as a result * of the number of extents changing */ if (howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0)) != btree_curs->level[0].num_blocks) { /* * yes -- recalculate the cursor. If the number of * excess (overallocated) blocks is < XFS_AGFL_SIZE/2, we're ok. * we can put those into the AGFL. we don't try * and get things to converge exactly (reach a * state with zero excess blocks) because there * exist pathological cases which will never * converge. first, check for the zero-case. */ if (num_extents == 0) { /* * ok, we've used up all the free blocks * trying to lay out the leaf level. go * to a one block (empty) btree and put the * already allocated blocks into the AGFL */ if (btree_curs->level[0].num_blocks != 1) { /* * we really needed more blocks because * the old tree had more than one level. * this is bad. */ do_warn(_("not enough free blocks left to " "describe all free blocks in AG " "%u\n"), agno); } #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "ag %u -- no free extents, alloc'ed %d\n", agno, blocks_allocated_pt); #endif lptr->num_blocks = 1; lptr->modulo = 0; lptr->num_recs_pb = 0; lptr->num_recs_tot = 0; btree_curs->num_levels = 1; /* * don't reset the allocation stats, assume * they're all extra blocks * don't forget to return the total block count * not the per-tree block count. these are the * extras that will go into the AGFL. subtract * two for the root blocks. */ btree_curs->num_tot_blocks = blocks_allocated_pt; btree_curs->num_free_blocks = blocks_allocated_pt; *extents = 0; return(blocks_allocated_total - 2); } lptr = &btree_curs->level[0]; lptr->num_blocks = howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0)); lptr->num_recs_pb = num_extents / lptr->num_blocks; lptr->modulo = num_extents % lptr->num_blocks; lptr->num_recs_tot = num_extents; level = 1; /* * if we need more levels, set them up */ if (lptr->num_blocks > 1) { for (level = 1; btree_curs->level[level-1].num_blocks > 1 && level < XFS_BTREE_MAXLEVELS; level++) { lptr = &btree_curs->level[level]; p_lptr = &btree_curs->level[level-1]; lptr->num_blocks = howmany(p_lptr->num_blocks, XR_ALLOC_BLOCK_MAXRECS(mp, level)); lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; lptr->num_recs_pb = p_lptr->num_blocks / lptr->num_blocks; lptr->num_recs_tot = p_lptr->num_blocks; } } ASSERT(lptr->num_blocks == 1); btree_curs->num_levels = level; /* * now figure out the number of excess blocks */ for (blocks_needed = 0, i = 0; i < level; i++) { blocks_needed += btree_curs->level[i].num_blocks; } blocks_needed *= 2; ASSERT(blocks_allocated_total >= blocks_needed); extra_blocks = blocks_allocated_total - blocks_needed; } else { if (extents_used > 0) { /* * reset the leaf level geometry to account * for consumed extents. we can leave the * rest of the cursor alone since the number * of leaf blocks hasn't changed. */ lptr = &btree_curs->level[0]; lptr->num_recs_pb = num_extents / lptr->num_blocks; lptr->modulo = num_extents % lptr->num_blocks; lptr->num_recs_tot = num_extents; } extra_blocks = 0; } btree_curs->num_tot_blocks = blocks_allocated_pt; btree_curs->num_free_blocks = blocks_allocated_pt; *extents = num_extents; return(extra_blocks); } static void prop_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, xfs_agblock_t startblock, xfs_extlen_t blockcount, int level, __uint32_t magic) { struct xfs_btree_block *bt_hdr; xfs_alloc_key_t *bt_key; xfs_alloc_ptr_t *bt_ptr; xfs_agblock_t agbno; bt_stat_level_t *lptr; __uint32_t crc_magic; if (magic == XFS_ABTB_MAGIC) crc_magic = XFS_ABTB_CRC_MAGIC; else crc_magic = XFS_ABTC_CRC_MAGIC; level++; if (level >= btree_curs->num_levels) return; lptr = &btree_curs->level[level]; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { /* * only happens once when initializing the * left-hand side of the tree. */ prop_freespace_cursor(mp, agno, btree_curs, startblock, blockcount, level, magic); } if (be16_to_cpu(bt_hdr->bb_numrecs) == lptr->num_recs_pb + (lptr->modulo > 0)) { /* * write out current prev block, grab us a new block, * and set the rightsib pointer of current block */ #ifdef XR_BLD_FREE_TRACE fprintf(stderr, " %d ", lptr->prev_agbno); #endif if (lptr->prev_agbno != NULLAGBLOCK) { ASSERT(lptr->prev_buf_p != NULL); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_agbno = lptr->agbno;; lptr->prev_buf_p = lptr->buf_p; agbno = get_next_blockaddr(agno, level, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); lptr->agbno = agbno; if (lptr->modulo) lptr->modulo--; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_allocbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, lptr->buf_p, crc_magic, level, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, lptr->buf_p, magic, level, 0, agno, 0); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); /* * propagate extent record for first extent in new block up */ prop_freespace_cursor(mp, agno, btree_curs, startblock, blockcount, level, magic); } /* * add extent info to current block */ be16_add_cpu(&bt_hdr->bb_numrecs, 1); bt_key = XFS_ALLOC_KEY_ADDR(mp, bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs)); bt_ptr = XFS_ALLOC_PTR_ADDR(mp, bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs), mp->m_alloc_mxr[1]); bt_key->ar_startblock = cpu_to_be32(startblock); bt_key->ar_blockcount = cpu_to_be32(blockcount); *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); } /* * rebuilds a freespace tree given a cursor and magic number of type * of tree to build (bno or bcnt). returns the number of free blocks * represented by the tree. */ static xfs_extlen_t build_freespace_tree(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, __uint32_t magic) { xfs_agnumber_t i; xfs_agblock_t j; struct xfs_btree_block *bt_hdr; xfs_alloc_rec_t *bt_rec; int level; xfs_agblock_t agbno; extent_tree_node_t *ext_ptr; bt_stat_level_t *lptr; xfs_extlen_t freeblks; __uint32_t crc_magic; #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "in build_freespace_tree, agno = %d\n", agno); #endif level = btree_curs->num_levels; freeblks = 0; ASSERT(level > 0); if (magic == XFS_ABTB_MAGIC) crc_magic = XFS_ABTB_CRC_MAGIC; else crc_magic = XFS_ABTC_CRC_MAGIC; /* * initialize the first block on each btree level */ for (i = 0; i < level; i++) { lptr = &btree_curs->level[i]; agbno = get_next_blockaddr(agno, i, btree_curs); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); if (i == btree_curs->num_levels - 1) btree_curs->root = agbno; lptr->agbno = agbno; lptr->prev_agbno = NULLAGBLOCK; lptr->prev_buf_p = NULL; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_allocbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, lptr->buf_p, crc_magic, i, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, lptr->buf_p, magic, i, 0, agno, 0); } /* * run along leaf, setting up records. as we have to switch * blocks, call the prop_freespace_cursor routine to set up the new * pointers for the parent. that can recurse up to the root * if required. set the sibling pointers for leaf level here. */ if (magic == XFS_ABTB_MAGIC) ext_ptr = findfirst_bno_extent(agno); else ext_ptr = findfirst_bcnt_extent(agno); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "bft, agno = %d, start = %u, count = %u\n", agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); #endif lptr = &btree_curs->level[0]; for (i = 0; i < btree_curs->level[0].num_blocks; i++) { /* * block initialization, lay in block header */ lptr->buf_p->b_ops = &xfs_allocbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, lptr->buf_p, crc_magic, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, lptr->buf_p, magic, 0, 0, agno, 0); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb + (lptr->modulo > 0)); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "bft, bb_numrecs = %d\n", be16_to_cpu(bt_hdr->bb_numrecs)); #endif if (lptr->modulo > 0) lptr->modulo--; /* * initialize values in the path up to the root if * this is a multi-level btree */ if (btree_curs->num_levels > 1) prop_freespace_cursor(mp, agno, btree_curs, ext_ptr->ex_startblock, ext_ptr->ex_blockcount, 0, magic); bt_rec = (xfs_alloc_rec_t *) ((char *)bt_hdr + XFS_ALLOC_BLOCK_LEN(mp)); for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { ASSERT(ext_ptr != NULL); bt_rec[j].ar_startblock = cpu_to_be32( ext_ptr->ex_startblock); bt_rec[j].ar_blockcount = cpu_to_be32( ext_ptr->ex_blockcount); freeblks += ext_ptr->ex_blockcount; if (magic == XFS_ABTB_MAGIC) ext_ptr = findnext_bno_extent(ext_ptr); else ext_ptr = findnext_bcnt_extent(agno, ext_ptr); #if 0 #ifdef XR_BLD_FREE_TRACE if (ext_ptr == NULL) fprintf(stderr, "null extent pointer, j = %d\n", j); else fprintf(stderr, "bft, agno = %d, start = %u, count = %u\n", agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); #endif #endif } if (ext_ptr != NULL) { /* * get next leaf level block */ if (lptr->prev_buf_p != NULL) { #ifdef XR_BLD_FREE_TRACE fprintf(stderr, " writing fst agbno %u\n", lptr->prev_agbno); #endif ASSERT(lptr->prev_agbno != NULLAGBLOCK); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_buf_p = lptr->buf_p; lptr->prev_agbno = lptr->agbno; lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), XFS_FSB_TO_BB(mp, 1)); } } return(freeblks); } /* * XXX(hch): any reason we don't just look at mp->m_inobt_mxr? */ #define XR_INOBT_BLOCK_MAXRECS(mp, level) \ libxfs_inobt_maxrecs((mp), (mp)->m_sb.sb_blocksize, \ (level) == 0) /* * we don't have to worry here about how chewing up free extents * may perturb things because inode tree building happens before * freespace tree building. */ static void init_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, __uint64_t *num_inos, __uint64_t *num_free_inos, int finobt) { __uint64_t ninos; __uint64_t nfinos; int rec_nfinos; int rec_ninos; ino_tree_node_t *ino_rec; int num_recs; int level; bt_stat_level_t *lptr; bt_stat_level_t *p_lptr; xfs_extlen_t blocks_allocated; int i; *num_inos = *num_free_inos = 0; ninos = nfinos = 0; lptr = &btree_curs->level[0]; btree_curs->init = 1; btree_curs->owner = XFS_RMAP_OWN_INOBT; /* * build up statistics */ ino_rec = findfirst_inode_rec(agno); for (num_recs = 0; ino_rec != NULL; ino_rec = next_ino_rec(ino_rec)) { rec_ninos = 0; rec_nfinos = 0; for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { ASSERT(is_inode_confirmed(ino_rec, i)); /* * sparse inodes are not factored into superblock (free) * inode counts */ if (is_inode_sparse(ino_rec, i)) continue; if (is_inode_free(ino_rec, i)) rec_nfinos++; rec_ninos++; } /* * finobt only considers records with free inodes */ if (finobt && !rec_nfinos) continue; nfinos += rec_nfinos; ninos += rec_ninos; num_recs++; } if (num_recs == 0) { /* * easy corner-case -- no inode records */ lptr->num_blocks = 1; lptr->modulo = 0; lptr->num_recs_pb = 0; lptr->num_recs_tot = 0; btree_curs->num_levels = 1; btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; setup_cursor(mp, agno, btree_curs); return; } blocks_allocated = lptr->num_blocks = howmany(num_recs, XR_INOBT_BLOCK_MAXRECS(mp, 0)); lptr->modulo = num_recs % lptr->num_blocks; lptr->num_recs_pb = num_recs / lptr->num_blocks; lptr->num_recs_tot = num_recs; level = 1; if (lptr->num_blocks > 1) { for (; btree_curs->level[level-1].num_blocks > 1 && level < XFS_BTREE_MAXLEVELS; level++) { lptr = &btree_curs->level[level]; p_lptr = &btree_curs->level[level - 1]; lptr->num_blocks = howmany(p_lptr->num_blocks, XR_INOBT_BLOCK_MAXRECS(mp, level)); lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; lptr->num_recs_pb = p_lptr->num_blocks / lptr->num_blocks; lptr->num_recs_tot = p_lptr->num_blocks; blocks_allocated += lptr->num_blocks; } } ASSERT(lptr->num_blocks == 1); btree_curs->num_levels = level; btree_curs->num_tot_blocks = btree_curs->num_free_blocks = blocks_allocated; setup_cursor(mp, agno, btree_curs); *num_inos = ninos; *num_free_inos = nfinos; return; } static void prop_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, xfs_agino_t startino, int level) { struct xfs_btree_block *bt_hdr; xfs_inobt_key_t *bt_key; xfs_inobt_ptr_t *bt_ptr; xfs_agblock_t agbno; bt_stat_level_t *lptr; level++; if (level >= btree_curs->num_levels) return; lptr = &btree_curs->level[level]; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { /* * this only happens once to initialize the * first path up the left side of the tree * where the agbno's are already set up */ prop_ino_cursor(mp, agno, btree_curs, startino, level); } if (be16_to_cpu(bt_hdr->bb_numrecs) == lptr->num_recs_pb + (lptr->modulo > 0)) { /* * write out current prev block, grab us a new block, * and set the rightsib pointer of current block */ #ifdef XR_BLD_INO_TRACE fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno); #endif if (lptr->prev_agbno != NULLAGBLOCK) { ASSERT(lptr->prev_buf_p != NULL); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_agbno = lptr->agbno;; lptr->prev_buf_p = lptr->buf_p; agbno = get_next_blockaddr(agno, level, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); lptr->agbno = agbno; if (lptr->modulo) lptr->modulo--; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_inobt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, lptr->buf_p, XFS_IBT_CRC_MAGIC, level, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, lptr->buf_p, XFS_IBT_MAGIC, level, 0, agno, 0); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); /* * propagate extent record for first extent in new block up */ prop_ino_cursor(mp, agno, btree_curs, startino, level); } /* * add inode info to current block */ be16_add_cpu(&bt_hdr->bb_numrecs, 1); bt_key = XFS_INOBT_KEY_ADDR(mp, bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs)); bt_ptr = XFS_INOBT_PTR_ADDR(mp, bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs), mp->m_inobt_mxr[1]); bt_key->ir_startino = cpu_to_be32(startino); *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); } /* * XXX: yet more code that can be shared with mkfs, growfs. */ static void build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, bt_status_t *finobt_curs, struct agi_stat *agi_stat) { xfs_buf_t *agi_buf; xfs_agi_t *agi; int i; agi_buf = libxfs_getbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), mp->m_sb.sb_sectsize/BBSIZE); agi_buf->b_ops = &xfs_agi_buf_ops; agi = XFS_BUF_TO_AGI(agi_buf); memset(agi, 0, mp->m_sb.sb_sectsize); agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); agi->agi_seqno = cpu_to_be32(agno); if (agno < mp->m_sb.sb_agcount - 1) agi->agi_length = cpu_to_be32(mp->m_sb.sb_agblocks); else agi->agi_length = cpu_to_be32(mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno); agi->agi_count = cpu_to_be32(agi_stat->count); agi->agi_root = cpu_to_be32(btree_curs->root); agi->agi_level = cpu_to_be32(btree_curs->num_levels); agi->agi_freecount = cpu_to_be32(agi_stat->freecount); agi->agi_newino = cpu_to_be32(agi_stat->first_agino); agi->agi_dirino = cpu_to_be32(NULLAGINO); for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) agi->agi_unlinked[i] = cpu_to_be32(NULLAGINO); if (xfs_sb_version_hascrc(&mp->m_sb)) platform_uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid); if (xfs_sb_version_hasfinobt(&mp->m_sb)) { agi->agi_free_root = cpu_to_be32(finobt_curs->root); agi->agi_free_level = cpu_to_be32(finobt_curs->num_levels); } libxfs_writebuf(agi_buf, 0); } /* * rebuilds an inode tree given a cursor. We're lazy here and call * the routine that builds the agi */ static void build_ino_tree(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, __uint32_t magic, struct agi_stat *agi_stat, int finobt) { xfs_agnumber_t i; xfs_agblock_t j; xfs_agblock_t agbno; xfs_agino_t first_agino; struct xfs_btree_block *bt_hdr; xfs_inobt_rec_t *bt_rec; ino_tree_node_t *ino_rec; bt_stat_level_t *lptr; xfs_agino_t count = 0; xfs_agino_t freecount = 0; int inocnt; uint8_t finocnt; int k; int level = btree_curs->num_levels; int spmask; uint64_t sparse; uint16_t holemask; for (i = 0; i < level; i++) { lptr = &btree_curs->level[i]; agbno = get_next_blockaddr(agno, i, btree_curs); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); if (i == btree_curs->num_levels - 1) btree_curs->root = agbno; lptr->agbno = agbno; lptr->prev_agbno = NULLAGBLOCK; lptr->prev_buf_p = NULL; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_inobt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, lptr->buf_p, magic, i, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, lptr->buf_p, magic, i, 0, agno, 0); } /* * run along leaf, setting up records. as we have to switch * blocks, call the prop_ino_cursor routine to set up the new * pointers for the parent. that can recurse up to the root * if required. set the sibling pointers for leaf level here. */ if (finobt) ino_rec = findfirst_free_inode_rec(agno); else ino_rec = findfirst_inode_rec(agno); if (ino_rec != NULL) first_agino = ino_rec->ino_startnum; else first_agino = NULLAGINO; lptr = &btree_curs->level[0]; for (i = 0; i < lptr->num_blocks; i++) { /* * block initialization, lay in block header */ lptr->buf_p->b_ops = &xfs_inobt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) libxfs_btree_init_block(mp, lptr->buf_p, magic, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); else libxfs_btree_init_block(mp, lptr->buf_p, magic, 0, 0, agno, 0); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb + (lptr->modulo > 0)); if (lptr->modulo > 0) lptr->modulo--; if (lptr->num_recs_pb > 0) prop_ino_cursor(mp, agno, btree_curs, ino_rec->ino_startnum, 0); bt_rec = (xfs_inobt_rec_t *) ((char *)bt_hdr + XFS_INOBT_BLOCK_LEN(mp)); for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { ASSERT(ino_rec != NULL); bt_rec[j].ir_startino = cpu_to_be32(ino_rec->ino_startnum); bt_rec[j].ir_free = cpu_to_be64(ino_rec->ir_free); inocnt = finocnt = 0; for (k = 0; k < sizeof(xfs_inofree_t)*NBBY; k++) { ASSERT(is_inode_confirmed(ino_rec, k)); if (is_inode_sparse(ino_rec, k)) continue; if (is_inode_free(ino_rec, k)) finocnt++; inocnt++; } /* * Set the freecount and check whether we need to update * the sparse format fields. Otherwise, skip to the next * record. */ inorec_set_freecount(mp, &bt_rec[j], finocnt); if (!xfs_sb_version_hassparseinodes(&mp->m_sb)) goto nextrec; /* * Convert the 64-bit in-core sparse inode state to the * 16-bit on-disk holemask. */ holemask = 0; spmask = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1; sparse = ino_rec->ir_sparse; for (k = 0; k < XFS_INOBT_HOLEMASK_BITS; k++) { if (sparse & spmask) { ASSERT((sparse & spmask) == spmask); holemask |= (1 << k); } else ASSERT((sparse & spmask) == 0); sparse >>= XFS_INODES_PER_HOLEMASK_BIT; } bt_rec[j].ir_u.sp.ir_count = inocnt; bt_rec[j].ir_u.sp.ir_holemask = cpu_to_be16(holemask); nextrec: freecount += finocnt; count += inocnt; if (finobt) ino_rec = next_free_ino_rec(ino_rec); else ino_rec = next_ino_rec(ino_rec); } if (ino_rec != NULL) { /* * get next leaf level block */ if (lptr->prev_buf_p != NULL) { #ifdef XR_BLD_INO_TRACE fprintf(stderr, "writing inobt agbno %u\n", lptr->prev_agbno); #endif ASSERT(lptr->prev_agbno != NULLAGBLOCK); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_buf_p = lptr->buf_p; lptr->prev_agbno = lptr->agbno; lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), XFS_FSB_TO_BB(mp, 1)); } } if (agi_stat) { agi_stat->first_agino = first_agino; agi_stat->count = count; agi_stat->freecount = freecount; } } /* rebuild the rmap tree */ /* * we don't have to worry here about how chewing up free extents * may perturb things because rmap tree building happens before * freespace tree building. */ static void init_rmapbt_cursor( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *btree_curs) { size_t num_recs; int level; struct bt_stat_level *lptr; struct bt_stat_level *p_lptr; xfs_extlen_t blocks_allocated; int maxrecs; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) { memset(btree_curs, 0, sizeof(struct bt_status)); return; } lptr = &btree_curs->level[0]; btree_curs->init = 1; btree_curs->owner = XFS_RMAP_OWN_AG; /* * build up statistics */ num_recs = rmap_record_count(mp, agno); if (num_recs == 0) { /* * easy corner-case -- no rmap records */ lptr->num_blocks = 1; lptr->modulo = 0; lptr->num_recs_pb = 0; lptr->num_recs_tot = 0; btree_curs->num_levels = 1; btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; setup_cursor(mp, agno, btree_curs); return; } /* * Leave enough slack in the rmapbt that we can insert the * metadata AG entries without too many splits. */ maxrecs = mp->m_rmap_mxr[0]; if (num_recs > maxrecs) maxrecs -= 10; blocks_allocated = lptr->num_blocks = howmany(num_recs, maxrecs); lptr->modulo = num_recs % lptr->num_blocks; lptr->num_recs_pb = num_recs / lptr->num_blocks; lptr->num_recs_tot = num_recs; level = 1; if (lptr->num_blocks > 1) { for (; btree_curs->level[level-1].num_blocks > 1 && level < XFS_BTREE_MAXLEVELS; level++) { lptr = &btree_curs->level[level]; p_lptr = &btree_curs->level[level - 1]; lptr->num_blocks = howmany(p_lptr->num_blocks, mp->m_rmap_mxr[1]); lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; lptr->num_recs_pb = p_lptr->num_blocks / lptr->num_blocks; lptr->num_recs_tot = p_lptr->num_blocks; blocks_allocated += lptr->num_blocks; } } ASSERT(lptr->num_blocks == 1); btree_curs->num_levels = level; btree_curs->num_tot_blocks = btree_curs->num_free_blocks = blocks_allocated; setup_cursor(mp, agno, btree_curs); } static void prop_rmap_cursor( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *btree_curs, struct xfs_rmap_irec *rm_rec, int level) { struct xfs_btree_block *bt_hdr; struct xfs_rmap_key *bt_key; xfs_rmap_ptr_t *bt_ptr; xfs_agblock_t agbno; struct bt_stat_level *lptr; level++; if (level >= btree_curs->num_levels) return; lptr = &btree_curs->level[level]; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { /* * this only happens once to initialize the * first path up the left side of the tree * where the agbno's are already set up */ prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level); } if (be16_to_cpu(bt_hdr->bb_numrecs) == lptr->num_recs_pb + (lptr->modulo > 0)) { /* * write out current prev block, grab us a new block, * and set the rightsib pointer of current block */ #ifdef XR_BLD_INO_TRACE fprintf(stderr, " rmap prop agbno %d ", lptr->prev_agbno); #endif if (lptr->prev_agbno != NULLAGBLOCK) { ASSERT(lptr->prev_buf_p != NULL); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_agbno = lptr->agbno; lptr->prev_buf_p = lptr->buf_p; agbno = get_next_blockaddr(agno, level, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); lptr->agbno = agbno; if (lptr->modulo) lptr->modulo--; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_rmapbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); libxfs_btree_init_block(mp, lptr->buf_p, XFS_RMAP_CRC_MAGIC, level, 0, agno, XFS_BTREE_CRC_BLOCKS); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); /* * propagate extent record for first extent in new block up */ prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level); } /* * add rmap info to current block */ be16_add_cpu(&bt_hdr->bb_numrecs, 1); bt_key = XFS_RMAP_KEY_ADDR(bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs)); bt_ptr = XFS_RMAP_PTR_ADDR(bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs), mp->m_rmap_mxr[1]); bt_key->rm_startblock = cpu_to_be32(rm_rec->rm_startblock); bt_key->rm_owner = cpu_to_be64(rm_rec->rm_owner); bt_key->rm_offset = cpu_to_be64(rm_rec->rm_offset); *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); } static void prop_rmap_highkey( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *btree_curs, struct xfs_rmap_irec *rm_highkey) { struct xfs_btree_block *bt_hdr; struct xfs_rmap_key *bt_key; struct bt_stat_level *lptr; struct xfs_rmap_irec key = {0}; struct xfs_rmap_irec high_key; int level; int i; int numrecs; high_key = *rm_highkey; for (level = 1; level < btree_curs->num_levels; level++) { lptr = &btree_curs->level[level]; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); numrecs = be16_to_cpu(bt_hdr->bb_numrecs); bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, numrecs); bt_key->rm_startblock = cpu_to_be32(high_key.rm_startblock); bt_key->rm_owner = cpu_to_be64(high_key.rm_owner); bt_key->rm_offset = cpu_to_be64( libxfs_rmap_irec_offset_pack(&high_key)); for (i = 1; i < numrecs - 1; i++) { bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, i); key.rm_startblock = be32_to_cpu(bt_key->rm_startblock); key.rm_owner = be64_to_cpu(bt_key->rm_owner); key.rm_offset = be64_to_cpu(bt_key->rm_offset); if (rmap_diffkeys(&key, &high_key) > 0) high_key = key; } } } /* * rebuilds a rmap btree given a cursor. */ static void build_rmap_tree( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *btree_curs) { xfs_agnumber_t i; xfs_agblock_t j; xfs_agblock_t agbno; struct xfs_btree_block *bt_hdr; struct xfs_rmap_irec *rm_rec; struct xfs_slab_cursor *rmap_cur; struct xfs_rmap_rec *bt_rec; struct xfs_rmap_irec highest_key = {0}; struct xfs_rmap_irec hi_key = {0}; struct bt_stat_level *lptr; int numrecs; int level = btree_curs->num_levels; int error; highest_key.rm_flags = 0; for (i = 0; i < level; i++) { lptr = &btree_curs->level[i]; agbno = get_next_blockaddr(agno, i, btree_curs); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); if (i == btree_curs->num_levels - 1) btree_curs->root = agbno; lptr->agbno = agbno; lptr->prev_agbno = NULLAGBLOCK; lptr->prev_buf_p = NULL; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_rmapbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); libxfs_btree_init_block(mp, lptr->buf_p, XFS_RMAP_CRC_MAGIC, i, 0, agno, XFS_BTREE_CRC_BLOCKS); } /* * run along leaf, setting up records. as we have to switch * blocks, call the prop_rmap_cursor routine to set up the new * pointers for the parent. that can recurse up to the root * if required. set the sibling pointers for leaf level here. */ error = rmap_init_cursor(agno, &rmap_cur); if (error) do_error( _("Insufficient memory to construct reverse-map cursor.")); rm_rec = pop_slab_cursor(rmap_cur); lptr = &btree_curs->level[0]; for (i = 0; i < lptr->num_blocks; i++) { numrecs = lptr->num_recs_pb + (lptr->modulo > 0); ASSERT(rm_rec != NULL || numrecs == 0); /* * block initialization, lay in block header */ lptr->buf_p->b_ops = &xfs_rmapbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); libxfs_btree_init_block(mp, lptr->buf_p, XFS_RMAP_CRC_MAGIC, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); bt_hdr->bb_numrecs = cpu_to_be16(numrecs); if (lptr->modulo > 0) lptr->modulo--; if (lptr->num_recs_pb > 0) { ASSERT(rm_rec != NULL); prop_rmap_cursor(mp, agno, btree_curs, rm_rec, 0); } bt_rec = (struct xfs_rmap_rec *) ((char *)bt_hdr + XFS_RMAP_BLOCK_LEN); highest_key.rm_startblock = 0; highest_key.rm_owner = 0; highest_key.rm_offset = 0; for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { ASSERT(rm_rec != NULL); bt_rec[j].rm_startblock = cpu_to_be32(rm_rec->rm_startblock); bt_rec[j].rm_blockcount = cpu_to_be32(rm_rec->rm_blockcount); bt_rec[j].rm_owner = cpu_to_be64(rm_rec->rm_owner); bt_rec[j].rm_offset = cpu_to_be64( libxfs_rmap_irec_offset_pack(rm_rec)); rmap_high_key_from_rec(rm_rec, &hi_key); if (rmap_diffkeys(&hi_key, &highest_key) > 0) highest_key = hi_key; rm_rec = pop_slab_cursor(rmap_cur); } /* Now go set the parent key */ prop_rmap_highkey(mp, agno, btree_curs, &highest_key); if (rm_rec != NULL) { /* * get next leaf level block */ if (lptr->prev_buf_p != NULL) { #ifdef XR_BLD_RL_TRACE fprintf(stderr, "writing rmapbt agbno %u\n", lptr->prev_agbno); #endif ASSERT(lptr->prev_agbno != NULLAGBLOCK); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_buf_p = lptr->buf_p; lptr->prev_agbno = lptr->agbno; lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), XFS_FSB_TO_BB(mp, 1)); } } free_slab_cursor(&rmap_cur); } /* rebuild the refcount tree */ /* * we don't have to worry here about how chewing up free extents * may perturb things because reflink tree building happens before * freespace tree building. */ static void init_refc_cursor( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *btree_curs) { size_t num_recs; int level; struct bt_stat_level *lptr; struct bt_stat_level *p_lptr; xfs_extlen_t blocks_allocated; if (!xfs_sb_version_hasreflink(&mp->m_sb)) { memset(btree_curs, 0, sizeof(struct bt_status)); return; } lptr = &btree_curs->level[0]; btree_curs->init = 1; btree_curs->owner = XFS_RMAP_OWN_REFC; /* * build up statistics */ num_recs = refcount_record_count(mp, agno); if (num_recs == 0) { /* * easy corner-case -- no refcount records */ lptr->num_blocks = 1; lptr->modulo = 0; lptr->num_recs_pb = 0; lptr->num_recs_tot = 0; btree_curs->num_levels = 1; btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; setup_cursor(mp, agno, btree_curs); return; } blocks_allocated = lptr->num_blocks = howmany(num_recs, mp->m_refc_mxr[0]); lptr->modulo = num_recs % lptr->num_blocks; lptr->num_recs_pb = num_recs / lptr->num_blocks; lptr->num_recs_tot = num_recs; level = 1; if (lptr->num_blocks > 1) { for (; btree_curs->level[level-1].num_blocks > 1 && level < XFS_BTREE_MAXLEVELS; level++) { lptr = &btree_curs->level[level]; p_lptr = &btree_curs->level[level - 1]; lptr->num_blocks = howmany(p_lptr->num_blocks, mp->m_refc_mxr[1]); lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; lptr->num_recs_pb = p_lptr->num_blocks / lptr->num_blocks; lptr->num_recs_tot = p_lptr->num_blocks; blocks_allocated += lptr->num_blocks; } } ASSERT(lptr->num_blocks == 1); btree_curs->num_levels = level; btree_curs->num_tot_blocks = btree_curs->num_free_blocks = blocks_allocated; setup_cursor(mp, agno, btree_curs); } static void prop_refc_cursor( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *btree_curs, xfs_agblock_t startbno, int level) { struct xfs_btree_block *bt_hdr; struct xfs_refcount_key *bt_key; xfs_refcount_ptr_t *bt_ptr; xfs_agblock_t agbno; struct bt_stat_level *lptr; level++; if (level >= btree_curs->num_levels) return; lptr = &btree_curs->level[level]; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { /* * this only happens once to initialize the * first path up the left side of the tree * where the agbno's are already set up */ prop_refc_cursor(mp, agno, btree_curs, startbno, level); } if (be16_to_cpu(bt_hdr->bb_numrecs) == lptr->num_recs_pb + (lptr->modulo > 0)) { /* * write out current prev block, grab us a new block, * and set the rightsib pointer of current block */ #ifdef XR_BLD_INO_TRACE fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno); #endif if (lptr->prev_agbno != NULLAGBLOCK) { ASSERT(lptr->prev_buf_p != NULL); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_agbno = lptr->agbno; lptr->prev_buf_p = lptr->buf_p; agbno = get_next_blockaddr(agno, level, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); lptr->agbno = agbno; if (lptr->modulo) lptr->modulo--; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_refcountbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); libxfs_btree_init_block(mp, lptr->buf_p, XFS_REFC_CRC_MAGIC, level, 0, agno, XFS_BTREE_CRC_BLOCKS); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); /* * propagate extent record for first extent in new block up */ prop_refc_cursor(mp, agno, btree_curs, startbno, level); } /* * add inode info to current block */ be16_add_cpu(&bt_hdr->bb_numrecs, 1); bt_key = XFS_REFCOUNT_KEY_ADDR(bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs)); bt_ptr = XFS_REFCOUNT_PTR_ADDR(bt_hdr, be16_to_cpu(bt_hdr->bb_numrecs), mp->m_refc_mxr[1]); bt_key->rc_startblock = cpu_to_be32(startbno); *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); } /* * rebuilds a refcount btree given a cursor. */ static void build_refcount_tree( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *btree_curs) { xfs_agnumber_t i; xfs_agblock_t j; xfs_agblock_t agbno; struct xfs_btree_block *bt_hdr; struct xfs_refcount_irec *refc_rec; struct xfs_slab_cursor *refc_cur; struct xfs_refcount_rec *bt_rec; struct bt_stat_level *lptr; int numrecs; int level = btree_curs->num_levels; int error; for (i = 0; i < level; i++) { lptr = &btree_curs->level[i]; agbno = get_next_blockaddr(agno, i, btree_curs); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); if (i == btree_curs->num_levels - 1) btree_curs->root = agbno; lptr->agbno = agbno; lptr->prev_agbno = NULLAGBLOCK; lptr->prev_buf_p = NULL; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_refcountbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); libxfs_btree_init_block(mp, lptr->buf_p, XFS_REFC_CRC_MAGIC, i, 0, agno, XFS_BTREE_CRC_BLOCKS); } /* * run along leaf, setting up records. as we have to switch * blocks, call the prop_refc_cursor routine to set up the new * pointers for the parent. that can recurse up to the root * if required. set the sibling pointers for leaf level here. */ error = init_refcount_cursor(agno, &refc_cur); if (error) do_error( _("Insufficient memory to construct refcount cursor.")); refc_rec = pop_slab_cursor(refc_cur); lptr = &btree_curs->level[0]; for (i = 0; i < lptr->num_blocks; i++) { numrecs = lptr->num_recs_pb + (lptr->modulo > 0); ASSERT(refc_rec != NULL || numrecs == 0); /* * block initialization, lay in block header */ lptr->buf_p->b_ops = &xfs_refcountbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); libxfs_btree_init_block(mp, lptr->buf_p, XFS_REFC_CRC_MAGIC, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); bt_hdr->bb_numrecs = cpu_to_be16(numrecs); if (lptr->modulo > 0) lptr->modulo--; if (lptr->num_recs_pb > 0) prop_refc_cursor(mp, agno, btree_curs, refc_rec->rc_startblock, 0); bt_rec = (struct xfs_refcount_rec *) ((char *)bt_hdr + XFS_REFCOUNT_BLOCK_LEN); for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { ASSERT(refc_rec != NULL); bt_rec[j].rc_startblock = cpu_to_be32(refc_rec->rc_startblock); bt_rec[j].rc_blockcount = cpu_to_be32(refc_rec->rc_blockcount); bt_rec[j].rc_refcount = cpu_to_be32(refc_rec->rc_refcount); refc_rec = pop_slab_cursor(refc_cur); } if (refc_rec != NULL) { /* * get next leaf level block */ if (lptr->prev_buf_p != NULL) { #ifdef XR_BLD_RL_TRACE fprintf(stderr, "writing refcntbt agbno %u\n", lptr->prev_agbno); #endif ASSERT(lptr->prev_agbno != NULLAGBLOCK); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_buf_p = lptr->buf_p; lptr->prev_agbno = lptr->agbno; lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), XFS_FSB_TO_BB(mp, 1)); } } free_slab_cursor(&refc_cur); } /* * build both the agf and the agfl for an agno given both * btree cursors. * * XXX: yet more common code that can be shared with mkfs/growfs. */ static void build_agf_agfl( struct xfs_mount *mp, xfs_agnumber_t agno, struct bt_status *bno_bt, struct bt_status *bcnt_bt, xfs_extlen_t freeblks, /* # free blocks in tree */ int lostblocks, /* # blocks that will be lost */ struct bt_status *rmap_bt, struct bt_status *refcnt_bt, struct xfs_slab *lost_fsb) { struct extent_tree_node *ext_ptr; struct xfs_buf *agf_buf, *agfl_buf; int i; struct xfs_agfl *agfl; struct xfs_agf *agf; xfs_fsblock_t fsb; __be32 *freelist; int error; agf_buf = libxfs_getbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), mp->m_sb.sb_sectsize/BBSIZE); agf_buf->b_ops = &xfs_agf_buf_ops; agf = XFS_BUF_TO_AGF(agf_buf); memset(agf, 0, mp->m_sb.sb_sectsize); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "agf = 0x%p, agf_buf->b_addr = 0x%p\n", agf, agf_buf->b_addr); #endif /* * set up fixed part of agf */ agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); agf->agf_seqno = cpu_to_be32(agno); if (agno < mp->m_sb.sb_agcount - 1) agf->agf_length = cpu_to_be32(mp->m_sb.sb_agblocks); else agf->agf_length = cpu_to_be32(mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno); agf->agf_roots[XFS_BTNUM_BNO] = cpu_to_be32(bno_bt->root); agf->agf_levels[XFS_BTNUM_BNO] = cpu_to_be32(bno_bt->num_levels); agf->agf_roots[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->root); agf->agf_levels[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->num_levels); agf->agf_roots[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->root); agf->agf_levels[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->num_levels); agf->agf_freeblks = cpu_to_be32(freeblks); agf->agf_rmap_blocks = cpu_to_be32(rmap_bt->num_tot_blocks - rmap_bt->num_free_blocks); agf->agf_refcount_root = cpu_to_be32(refcnt_bt->root); agf->agf_refcount_level = cpu_to_be32(refcnt_bt->num_levels); agf->agf_refcount_blocks = cpu_to_be32(refcnt_bt->num_tot_blocks - refcnt_bt->num_free_blocks); /* * Count and record the number of btree blocks consumed if required. */ if (xfs_sb_version_haslazysbcount(&mp->m_sb)) { unsigned int blks; /* * Don't count the root blocks as they are already * accounted for. */ blks = (bno_bt->num_tot_blocks - bno_bt->num_free_blocks) + (bcnt_bt->num_tot_blocks - bcnt_bt->num_free_blocks) - 2; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) blks += rmap_bt->num_tot_blocks - rmap_bt->num_free_blocks - 1; agf->agf_btreeblks = cpu_to_be32(blks); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "agf->agf_btreeblks = %u\n", be32_to_cpu(agf->agf_btreeblks)); #endif } #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "bno root = %u, bcnt root = %u, indices = %u %u\n", be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]), be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]), XFS_BTNUM_BNO, XFS_BTNUM_CNT); #endif if (xfs_sb_version_hascrc(&mp->m_sb)) platform_uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid); /* initialise the AGFL, then fill it if there are blocks left over. */ agfl_buf = libxfs_getbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), mp->m_sb.sb_sectsize/BBSIZE); agfl_buf->b_ops = &xfs_agfl_buf_ops; agfl = XFS_BUF_TO_AGFL(agfl_buf); /* setting to 0xff results in initialisation to NULLAGBLOCK */ memset(agfl, 0xff, mp->m_sb.sb_sectsize); if (xfs_sb_version_hascrc(&mp->m_sb)) { agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC); agfl->agfl_seqno = cpu_to_be32(agno); platform_uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid); for (i = 0; i < XFS_AGFL_SIZE(mp); i++) agfl->agfl_bno[i] = cpu_to_be32(NULLAGBLOCK); } freelist = XFS_BUF_TO_AGFL_BNO(mp, agfl_buf); /* * do we have left-over blocks in the btree cursors that should * be used to fill the AGFL? */ if (bno_bt->num_free_blocks > 0 || bcnt_bt->num_free_blocks > 0) { /* * yes, now grab as many blocks as we can */ i = 0; while (bno_bt->num_free_blocks > 0 && i < XFS_AGFL_SIZE(mp)) { freelist[i] = cpu_to_be32( get_next_blockaddr(agno, 0, bno_bt)); i++; } while (bcnt_bt->num_free_blocks > 0 && i < XFS_AGFL_SIZE(mp)) { freelist[i] = cpu_to_be32( get_next_blockaddr(agno, 0, bcnt_bt)); i++; } /* * now throw the rest of the blocks away and complain */ while (bno_bt->num_free_blocks > 0) { fsb = XFS_AGB_TO_FSB(mp, agno, get_next_blockaddr(agno, 0, bno_bt)); error = slab_add(lost_fsb, &fsb); if (error) do_error( _("Insufficient memory saving lost blocks.\n")); } while (bcnt_bt->num_free_blocks > 0) { fsb = XFS_AGB_TO_FSB(mp, agno, get_next_blockaddr(agno, 0, bcnt_bt)); error = slab_add(lost_fsb, &fsb); if (error) do_error( _("Insufficient memory saving lost blocks.\n")); } agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(i - 1); agf->agf_flcount = cpu_to_be32(i); rmap_store_agflcount(mp, agno, i); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "writing agfl for ag %u\n", agno); #endif } else { agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); agf->agf_flcount = 0; } libxfs_writebuf(agfl_buf, 0); ext_ptr = findbiggest_bcnt_extent(agno); agf->agf_longest = cpu_to_be32((ext_ptr != NULL) ? ext_ptr->ex_blockcount : 0); ASSERT(be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]) != be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi])); ASSERT(be32_to_cpu(agf->agf_refcount_root) != be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi])); ASSERT(be32_to_cpu(agf->agf_refcount_root) != be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi])); libxfs_writebuf(agf_buf, 0); /* * now fix up the free list appropriately */ fix_freelist(mp, agno, true); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "wrote agf for ag %u\n", agno); #endif } /* * update the superblock counters, sync the sb version numbers and * feature bits to the filesystem, and sync up the on-disk superblock * to match the incore superblock. */ static void sync_sb(xfs_mount_t *mp) { xfs_buf_t *bp; bp = libxfs_getsb(mp, 0); if (!bp) do_error(_("couldn't get superblock\n")); mp->m_sb.sb_icount = sb_icount; mp->m_sb.sb_ifree = sb_ifree; mp->m_sb.sb_fdblocks = sb_fdblocks; mp->m_sb.sb_frextents = sb_frextents; update_sb_version(mp); libxfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); libxfs_writebuf(bp, 0); } /* * make sure the root and realtime inodes show up allocated * even if they've been freed. they get reinitialized in phase6. */ static void keep_fsinos(xfs_mount_t *mp) { ino_tree_node_t *irec; int i; irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)); for (i = 0; i < 3; i++) set_inode_used(irec, i); } static void phase5_func( xfs_mount_t *mp, xfs_agnumber_t agno, struct xfs_slab *lost_fsb) { __uint64_t num_inos; __uint64_t num_free_inos; __uint64_t finobt_num_inos; __uint64_t finobt_num_free_inos; bt_status_t bno_btree_curs; bt_status_t bcnt_btree_curs; bt_status_t ino_btree_curs; bt_status_t fino_btree_curs; bt_status_t rmap_btree_curs; bt_status_t refcnt_btree_curs; int extra_blocks = 0; uint num_freeblocks; xfs_extlen_t freeblks1; #ifdef DEBUG xfs_extlen_t freeblks2; #endif xfs_agblock_t num_extents; __uint32_t magic; struct agi_stat agi_stat = {0,}; int error; if (verbose) do_log(_(" - agno = %d\n"), agno); { /* * build up incore bno and bcnt extent btrees */ num_extents = mk_incore_fstree(mp, agno); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno)); #endif if (num_extents == 0) { /* * XXX - what we probably should do here is pick an * inode for a regular file in the allocation group * that has space allocated and shoot it by traversing * the bmap list and putting all its extents on the * incore freespace trees, clearing the inode, * and clearing the in-use bit in the incore inode * tree. Then try mk_incore_fstree() again. */ do_error(_("unable to rebuild AG %u. " "Not enough free space in on-disk AG.\n"), agno); } /* * ok, now set up the btree cursors for the * on-disk btrees (includs pre-allocating all * required blocks for the trees themselves) */ init_ino_cursor(mp, agno, &ino_btree_curs, &num_inos, &num_free_inos, 0); if (xfs_sb_version_hasfinobt(&mp->m_sb)) init_ino_cursor(mp, agno, &fino_btree_curs, &finobt_num_inos, &finobt_num_free_inos, 1); sb_icount_ag[agno] += num_inos; sb_ifree_ag[agno] += num_free_inos; /* * Set up the btree cursors for the on-disk rmap btrees, * which includes pre-allocating all required blocks. */ init_rmapbt_cursor(mp, agno, &rmap_btree_curs); /* * Set up the btree cursors for the on-disk refcount btrees, * which includes pre-allocating all required blocks. */ init_refc_cursor(mp, agno, &refcnt_btree_curs); num_extents = count_bno_extents_blocks(agno, &num_freeblocks); /* * lose two blocks per AG -- the space tree roots * are counted as allocated since the space trees * always have roots */ sb_fdblocks_ag[agno] += num_freeblocks - 2; if (num_extents == 0) { /* * XXX - what we probably should do here is pick an * inode for a regular file in the allocation group * that has space allocated and shoot it by traversing * the bmap list and putting all its extents on the * incore freespace trees, clearing the inode, * and clearing the in-use bit in the incore inode * tree. Then try mk_incore_fstree() again. */ do_error( _("unable to rebuild AG %u. No free space.\n"), agno); } #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "# of bno extents is %d\n", num_extents); #endif /* * track blocks that we might really lose */ extra_blocks = calculate_freespace_cursor(mp, agno, &num_extents, &bno_btree_curs); /* * freespace btrees live in the "free space" but * the filesystem treats AGFL blocks as allocated * since they aren't described by the freespace trees */ /* * see if we can fit all the extra blocks into the AGFL */ extra_blocks = (extra_blocks - XFS_AGFL_SIZE(mp) > 0) ? extra_blocks - XFS_AGFL_SIZE(mp) : 0; if (extra_blocks > 0) sb_fdblocks_ag[agno] -= extra_blocks; bcnt_btree_curs = bno_btree_curs; bno_btree_curs.owner = XFS_RMAP_OWN_AG; bcnt_btree_curs.owner = XFS_RMAP_OWN_AG; setup_cursor(mp, agno, &bno_btree_curs); setup_cursor(mp, agno, &bcnt_btree_curs); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno)); fprintf(stderr, "# of bcnt extents is %d\n", count_bcnt_extents(agno)); #endif /* * now rebuild the freespace trees */ freeblks1 = build_freespace_tree(mp, agno, &bno_btree_curs, XFS_ABTB_MAGIC); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "# of free blocks == %d\n", freeblks1); #endif write_cursor(&bno_btree_curs); #ifdef DEBUG freeblks2 = build_freespace_tree(mp, agno, &bcnt_btree_curs, XFS_ABTC_MAGIC); #else (void) build_freespace_tree(mp, agno, &bcnt_btree_curs, XFS_ABTC_MAGIC); #endif write_cursor(&bcnt_btree_curs); ASSERT(freeblks1 == freeblks2); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { build_rmap_tree(mp, agno, &rmap_btree_curs); write_cursor(&rmap_btree_curs); sb_fdblocks_ag[agno] += (rmap_btree_curs.num_tot_blocks - rmap_btree_curs.num_free_blocks) - 1; } if (xfs_sb_version_hasreflink(&mp->m_sb)) { build_refcount_tree(mp, agno, &refcnt_btree_curs); write_cursor(&refcnt_btree_curs); } /* * set up agf and agfl */ build_agf_agfl(mp, agno, &bno_btree_curs, &bcnt_btree_curs, freeblks1, extra_blocks, &rmap_btree_curs, &refcnt_btree_curs, lost_fsb); /* * build inode allocation tree. */ magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC : XFS_IBT_MAGIC; build_ino_tree(mp, agno, &ino_btree_curs, magic, &agi_stat, 0); write_cursor(&ino_btree_curs); /* * build free inode tree */ if (xfs_sb_version_hasfinobt(&mp->m_sb)) { magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC; build_ino_tree(mp, agno, &fino_btree_curs, magic, NULL, 1); write_cursor(&fino_btree_curs); } /* build the agi */ build_agi(mp, agno, &ino_btree_curs, &fino_btree_curs, &agi_stat); /* * tear down cursors */ finish_cursor(&bno_btree_curs); finish_cursor(&ino_btree_curs); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) finish_cursor(&rmap_btree_curs); if (xfs_sb_version_hasreflink(&mp->m_sb)) finish_cursor(&refcnt_btree_curs); if (xfs_sb_version_hasfinobt(&mp->m_sb)) finish_cursor(&fino_btree_curs); finish_cursor(&bcnt_btree_curs); /* * Put the per-AG btree rmap data into the rmapbt */ error = rmap_store_ag_btree_rec(mp, agno); if (error) do_error( _("unable to add AG %u reverse-mapping data to btree.\n"), agno); /* * release the incore per-AG bno/bcnt trees so * the extent nodes can be recycled */ release_agbno_extent_tree(agno); release_agbcnt_extent_tree(agno); } PROG_RPT_INC(prog_rpt_done[agno], 1); } /* Inject lost blocks back into the filesystem. */ static int inject_lost_blocks( struct xfs_mount *mp, struct xfs_slab *lost_fsbs) { struct xfs_trans *tp = NULL; struct xfs_slab_cursor *cur = NULL; xfs_fsblock_t *fsb; struct xfs_trans_res tres = {0}; struct xfs_owner_info oinfo; int error; libxfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG); error = init_slab_cursor(lost_fsbs, NULL, &cur); if (error) return error; while ((fsb = pop_slab_cursor(cur)) != NULL) { error = -libxfs_trans_alloc(mp, &tres, 16, 0, 0, &tp); if (error) goto out_cancel; error = -libxfs_free_extent(tp, *fsb, 1, &oinfo, XFS_AG_RESV_NONE); if (error) goto out_cancel; error = -libxfs_trans_commit(tp); if (error) goto out_cancel; tp = NULL; } out_cancel: if (tp) libxfs_trans_cancel(tp); free_slab_cursor(&cur); return error; } void phase5(xfs_mount_t *mp) { struct xfs_slab *lost_fsb; xfs_agnumber_t agno; int error; do_log(_("Phase 5 - rebuild AG headers and trees...\n")); set_progress_msg(PROG_FMT_REBUILD_AG, (__uint64_t )glob_agcount); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "inobt level 1, maxrec = %d, minrec = %d\n", libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0), libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2); fprintf(stderr, "inobt level 0 (leaf), maxrec = %d, minrec = %d\n", libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1), libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2); fprintf(stderr, "xr inobt level 0 (leaf), maxrec = %d\n", XR_INOBT_BLOCK_MAXRECS(mp, 0)); fprintf(stderr, "xr inobt level 1 (int), maxrec = %d\n", XR_INOBT_BLOCK_MAXRECS(mp, 1)); fprintf(stderr, "bnobt level 1, maxrec = %d, minrec = %d\n", libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0), libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2); fprintf(stderr, "bnobt level 0 (leaf), maxrec = %d, minrec = %d\n", libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1), libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2); #endif /* * make sure the root and realtime inodes show up allocated */ keep_fsinos(mp); /* allocate per ag counters */ sb_icount_ag = calloc(mp->m_sb.sb_agcount, sizeof(__uint64_t)); if (sb_icount_ag == NULL) do_error(_("cannot alloc sb_icount_ag buffers\n")); sb_ifree_ag = calloc(mp->m_sb.sb_agcount, sizeof(__uint64_t)); if (sb_ifree_ag == NULL) do_error(_("cannot alloc sb_ifree_ag buffers\n")); sb_fdblocks_ag = calloc(mp->m_sb.sb_agcount, sizeof(__uint64_t)); if (sb_fdblocks_ag == NULL) do_error(_("cannot alloc sb_fdblocks_ag buffers\n")); error = init_slab(&lost_fsb, sizeof(xfs_fsblock_t)); if (error) do_error(_("cannot alloc lost block slab\n")); for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) phase5_func(mp, agno, lost_fsb); print_final_rpt(); /* aggregate per ag counters */ for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { sb_icount += sb_icount_ag[agno]; sb_ifree += sb_ifree_ag[agno]; sb_fdblocks += sb_fdblocks_ag[agno]; } free(sb_icount_ag); free(sb_ifree_ag); free(sb_fdblocks_ag); if (mp->m_sb.sb_rblocks) { do_log( _(" - generate realtime summary info and bitmap...\n")); rtinit(mp); generate_rtinfo(mp, btmcompute, sumcompute); } do_log(_(" - reset superblock...\n")); /* * sync superblock counter and set version bits correctly */ sync_sb(mp); error = inject_lost_blocks(mp, lost_fsb); if (error) do_error(_("Unable to reinsert lost blocks into filesystem.\n")); free_slab(&lost_fsb); bad_ino_btree = 0; } xfsprogs-4.9.0+nmu1ubuntu2/repair/phase6.c0000644000000000000000000024366613063067173015331 0ustar /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "threads.h" #include "prefetch.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "dir2.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "progress.h" #include "versions.h" static struct cred zerocr; static struct fsxattr zerofsx; static xfs_ino_t orphanage_ino; static struct xfs_name xfs_name_dot = {(unsigned char *)".", 1, XFS_DIR3_FT_DIR}; /* * Data structures used to keep track of directories where the ".." * entries are updated. These must be rebuilt after the initial pass */ typedef struct dotdot_update { struct list_head list; ino_tree_node_t *irec; xfs_agnumber_t agno; int ino_offset; } dotdot_update_t; static LIST_HEAD(dotdot_update_list); static int dotdot_update; static void add_dotdot_update( xfs_agnumber_t agno, ino_tree_node_t *irec, int ino_offset) { dotdot_update_t *dir = malloc(sizeof(dotdot_update_t)); if (!dir) do_error(_("malloc failed add_dotdot_update (%zu bytes)\n"), sizeof(dotdot_update_t)); INIT_LIST_HEAD(&dir->list); dir->irec = irec; dir->agno = agno; dir->ino_offset = ino_offset; list_add(&dir->list, &dotdot_update_list); } /* * Data structures and routines to keep track of directory entries * and whether their leaf entry has been seen. Also used for name * duplicate checking and rebuilding step if required. */ typedef struct dir_hash_ent { struct dir_hash_ent *nextbyaddr; /* next in addr bucket */ struct dir_hash_ent *nextbyhash; /* next in name bucket */ struct dir_hash_ent *nextbyorder; /* next in order added */ xfs_dahash_t hashval; /* hash value of name */ __uint32_t address; /* offset of data entry */ xfs_ino_t inum; /* inode num of entry */ short junkit; /* name starts with / */ short seen; /* have seen leaf entry */ struct xfs_name name; } dir_hash_ent_t; typedef struct dir_hash_tab { int size; /* size of hash tables */ int names_duped; /* 1 = ent names malloced */ dir_hash_ent_t *first; /* ptr to first added entry */ dir_hash_ent_t *last; /* ptr to last added entry */ dir_hash_ent_t **byhash; /* ptr to name hash buckets */ dir_hash_ent_t **byaddr; /* ptr to addr hash buckets */ } dir_hash_tab_t; #define DIR_HASH_TAB_SIZE(n) \ (sizeof(dir_hash_tab_t) + (sizeof(dir_hash_ent_t *) * (n) * 2)) #define DIR_HASH_FUNC(t,a) ((a) % (t)->size) /* * Track the contents of the freespace table in a directory. */ typedef struct freetab { int naents; /* expected number of data blocks */ int nents; /* number of data blocks processed */ struct freetab_ent { xfs_dir2_data_off_t v; short s; } ents[1]; } freetab_t; #define FREETAB_SIZE(n) \ (offsetof(freetab_t, ents) + (sizeof(struct freetab_ent) * (n))) #define DIR_HASH_CK_OK 0 #define DIR_HASH_CK_DUPLEAF 1 #define DIR_HASH_CK_BADHASH 2 #define DIR_HASH_CK_NODATA 3 #define DIR_HASH_CK_NOLEAF 4 #define DIR_HASH_CK_BADSTALE 5 #define DIR_HASH_CK_TOTAL 6 /* * Need to handle CRC and validation errors specially here. If there is a * validator error, re-read without the verifier so that we get a buffer we can * check and repair. Re-attach the ops to the buffer after the read so that when * it is rewritten the CRC is recalculated. * * If the buffer was not read, we return an error. If the buffer was read but * had a CRC or corruption error, we reread it without the verifier and if it is * read successfully we increment *crc_error and return 0. Otherwise we * return the read error. */ static int dir_read_buf( struct xfs_inode *ip, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp, const struct xfs_buf_ops *ops, int *crc_error) { int error; int error2; error = -libxfs_da_read_buf(NULL, ip, bno, mappedbno, bpp, XFS_DATA_FORK, ops); if (error != EFSBADCRC && error != EFSCORRUPTED) return error; error2 = -libxfs_da_read_buf(NULL, ip, bno, mappedbno, bpp, XFS_DATA_FORK, NULL); if (error2) return error2; (*crc_error)++; (*bpp)->b_ops = ops; return 0; } /* * Returns 0 if the name already exists (ie. a duplicate) */ static int dir_hash_add( xfs_mount_t *mp, dir_hash_tab_t *hashtab, __uint32_t addr, xfs_ino_t inum, int namelen, unsigned char *name, __uint8_t ftype) { xfs_dahash_t hash = 0; int byaddr; int byhash = 0; dir_hash_ent_t *p; int dup; short junk; struct xfs_name xname; ASSERT(!hashtab->names_duped); xname.name = name; xname.len = namelen; xname.type = ftype; junk = name[0] == '/'; byaddr = DIR_HASH_FUNC(hashtab, addr); dup = 0; if (!junk) { hash = mp->m_dirnameops->hashname(&xname); byhash = DIR_HASH_FUNC(hashtab, hash); /* * search hash bucket for existing name. */ for (p = hashtab->byhash[byhash]; p; p = p->nextbyhash) { if (p->hashval == hash && p->name.len == namelen) { if (memcmp(p->name.name, name, namelen) == 0) { dup = 1; junk = 1; break; } } } } if ((p = malloc(sizeof(*p))) == NULL) do_error(_("malloc failed in dir_hash_add (%zu bytes)\n"), sizeof(*p)); p->nextbyaddr = hashtab->byaddr[byaddr]; hashtab->byaddr[byaddr] = p; if (hashtab->last) hashtab->last->nextbyorder = p; else hashtab->first = p; p->nextbyorder = NULL; hashtab->last = p; if (!(p->junkit = junk)) { p->hashval = hash; p->nextbyhash = hashtab->byhash[byhash]; hashtab->byhash[byhash] = p; } p->address = addr; p->inum = inum; p->seen = 0; p->name = xname; return !dup; } /* * checks to see if any data entries are not in the leaf blocks */ static int dir_hash_unseen( dir_hash_tab_t *hashtab) { int i; dir_hash_ent_t *p; for (i = 0; i < hashtab->size; i++) { for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) { if (p->seen == 0) return 1; } } return 0; } static int dir_hash_check( dir_hash_tab_t *hashtab, xfs_inode_t *ip, int seeval) { static char *seevalstr[DIR_HASH_CK_TOTAL]; static int done; if (!done) { seevalstr[DIR_HASH_CK_OK] = _("ok"); seevalstr[DIR_HASH_CK_DUPLEAF] = _("duplicate leaf"); seevalstr[DIR_HASH_CK_BADHASH] = _("hash value mismatch"); seevalstr[DIR_HASH_CK_NODATA] = _("no data entry"); seevalstr[DIR_HASH_CK_NOLEAF] = _("no leaf entry"); seevalstr[DIR_HASH_CK_BADSTALE] = _("bad stale count"); done = 1; } if (seeval == DIR_HASH_CK_OK && dir_hash_unseen(hashtab)) seeval = DIR_HASH_CK_NOLEAF; if (seeval == DIR_HASH_CK_OK) return 0; do_warn(_("bad hash table for directory inode %" PRIu64 " (%s): "), ip->i_ino, seevalstr[seeval]); if (!no_modify) do_warn(_("rebuilding\n")); else do_warn(_("would rebuild\n")); return 1; } static void dir_hash_done( dir_hash_tab_t *hashtab) { int i; dir_hash_ent_t *n; dir_hash_ent_t *p; for (i = 0; i < hashtab->size; i++) { for (p = hashtab->byaddr[i]; p; p = n) { n = p->nextbyaddr; if (hashtab->names_duped) free((void *)p->name.name); free(p); } } free(hashtab); } static dir_hash_tab_t * dir_hash_init( xfs_fsize_t size) { dir_hash_tab_t *hashtab; int hsize; hsize = size / (16 * 4); if (hsize > 65536) hsize = 63336; else if (hsize < 16) hsize = 16; if ((hashtab = calloc(DIR_HASH_TAB_SIZE(hsize), 1)) == NULL) do_error(_("calloc failed in dir_hash_init\n")); hashtab->size = hsize; hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab + sizeof(dir_hash_tab_t)); hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab + sizeof(dir_hash_tab_t) + sizeof(dir_hash_ent_t*) * hsize); return hashtab; } static int dir_hash_see( dir_hash_tab_t *hashtab, xfs_dahash_t hash, xfs_dir2_dataptr_t addr) { int i; dir_hash_ent_t *p; i = DIR_HASH_FUNC(hashtab, addr); for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) { if (p->address != addr) continue; if (p->seen) return DIR_HASH_CK_DUPLEAF; if (p->junkit == 0 && p->hashval != hash) return DIR_HASH_CK_BADHASH; p->seen = 1; return DIR_HASH_CK_OK; } return DIR_HASH_CK_NODATA; } static void dir_hash_update_ftype( dir_hash_tab_t *hashtab, xfs_dir2_dataptr_t addr, __uint8_t ftype) { int i; dir_hash_ent_t *p; i = DIR_HASH_FUNC(hashtab, addr); for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) { if (p->address != addr) continue; p->name.type = ftype; } } /* * checks to make sure leafs match a data entry, and that the stale * count is valid. */ static int dir_hash_see_all( dir_hash_tab_t *hashtab, xfs_dir2_leaf_entry_t *ents, int count, int stale) { int i; int j; int rval; for (i = j = 0; i < count; i++) { if (be32_to_cpu(ents[i].address) == XFS_DIR2_NULL_DATAPTR) { j++; continue; } rval = dir_hash_see(hashtab, be32_to_cpu(ents[i].hashval), be32_to_cpu(ents[i].address)); if (rval != DIR_HASH_CK_OK) return rval; } return j == stale ? DIR_HASH_CK_OK : DIR_HASH_CK_BADSTALE; } /* * Convert name pointers into locally allocated memory. * This must only be done after all the entries have been added. */ static void dir_hash_dup_names(dir_hash_tab_t *hashtab) { unsigned char *name; dir_hash_ent_t *p; if (hashtab->names_duped) return; for (p = hashtab->first; p; p = p->nextbyorder) { name = malloc(p->name.len); memcpy(name, p->name.name, p->name.len); p->name.name = name; } hashtab->names_duped = 1; } /* * Given a block number in a fork, return the next valid block number * (not a hole). * If this is the last block number then NULLFILEOFF is returned. * * This was originally in the kernel, but only used in xfs_repair. */ static int bmap_next_offset( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode */ xfs_fileoff_t *bnop, /* current block */ int whichfork) /* data or attr fork */ { xfs_fileoff_t bno; /* current block */ int eof; /* hit end of file */ int error; /* error return value */ xfs_bmbt_irec_t got; /* current extent value */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_extnum_t lastx; /* last extent used */ xfs_bmbt_irec_t prev; /* previous extent value */ if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL) return EIO; if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { *bnop = NULLFILEOFF; return 0; } ifp = XFS_IFORK_PTR(ip, whichfork); if (!(ifp->if_flags & XFS_IFEXTENTS) && (error = -libxfs_iread_extents(tp, ip, whichfork))) return error; bno = *bnop + 1; libxfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); if (eof) *bnop = NULLFILEOFF; else *bnop = got.br_startoff < bno ? bno : got.br_startoff; return 0; } static void res_failed( int err) { if (err == ENOSPC) { do_error(_("ran out of disk space!\n")); } else do_error(_("xfs_trans_reserve returned %d\n"), err); } void mk_rbmino(xfs_mount_t *mp) { xfs_trans_t *tp; xfs_inode_t *ip; xfs_bmbt_irec_t *ep; xfs_fsblock_t first; int i; int nmap; int error; struct xfs_defer_ops dfops; xfs_fileoff_t bno; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; int vers; int times; struct xfs_trans_res tres = {0}; /* * first set up inode */ i = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp); if (i) res_failed(i); error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip); if (error) { do_error( _("couldn't iget realtime bitmap inode -- error - %d\n"), error); } vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 2; memset(&ip->i_d, 0, sizeof(ip->i_d)); VFS_I(ip)->i_mode = S_IFREG; ip->i_d.di_version = vers; ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; set_nlink(VFS_I(ip), 1); /* account for sb ptr */ times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD; if (ip->i_d.di_version == 3) { VFS_I(ip)->i_version = 1; ip->i_d.di_flags2 = 0; times |= XFS_ICHGTIME_CREATE; } libxfs_trans_ichgtime(tp, ip, times); /* * now the ifork */ ip->i_df.if_flags = XFS_IFEXTENTS; ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0; ip->i_df.if_u1.if_extents = NULL; ip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize; /* * commit changes */ libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); libxfs_trans_commit(tp); /* * then allocate blocks for file and fill with zeroes (stolen * from mkfs) */ error = -libxfs_trans_alloc(mp, &tres, mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); bno = 0; libxfs_defer_init(&dfops, &first); while (bno < mp->m_sb.sb_rbmblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, ip, bno, (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno), 0, &first, mp->m_sb.sb_rbmblocks, map, &nmap, &dfops); if (error) { do_error( _("couldn't allocate realtime bitmap, error = %d\n"), error); } for (i = 0, ep = map; i < nmap; i++, ep++) { libxfs_device_zero(mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, ep->br_startblock), XFS_FSB_TO_BB(mp, ep->br_blockcount)); bno += ep->br_blockcount; } } error = -libxfs_defer_finish(&tp, &dfops, ip); if (error) { do_error( _("allocation of the realtime bitmap failed, error = %d\n"), error); } libxfs_trans_commit(tp); IRELE(ip); } static int fill_rbmino(xfs_mount_t *mp) { xfs_buf_t *bp; xfs_trans_t *tp; xfs_inode_t *ip; xfs_rtword_t *bmp; xfs_fsblock_t first; int nmap; int error; xfs_fileoff_t bno; xfs_bmbt_irec_t map; struct xfs_trans_res tres = {0}; bmp = btmcompute; bno = 0; error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp); if (error) res_failed(error); error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip); if (error) { do_error( _("couldn't iget realtime bitmap inode -- error - %d\n"), error); } first = NULLFSBLOCK; while (bno < mp->m_sb.sb_rbmblocks) { /* * fill the file one block at a time */ nmap = 1; error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, &first, 1, &map, &nmap, NULL); if (error || nmap != 1) { do_error( _("couldn't map realtime bitmap block %" PRIu64 ", error = %d\n"), bno, error); } ASSERT(map.br_startblock != HOLESTARTBLOCK); error = -libxfs_trans_read_buf( mp, tp, mp->m_dev, XFS_FSB_TO_DADDR(mp, map.br_startblock), XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL); if (error) { do_warn( _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %" PRIu64 "\n"), bno, map.br_startblock, mp->m_sb.sb_rbmino); return(1); } memmove(XFS_BUF_PTR(bp), bmp, mp->m_sb.sb_blocksize); libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); bmp = (xfs_rtword_t *)((intptr_t) bmp + mp->m_sb.sb_blocksize); bno++; } libxfs_trans_commit(tp); IRELE(ip); return(0); } static int fill_rsumino(xfs_mount_t *mp) { xfs_buf_t *bp; xfs_trans_t *tp; xfs_inode_t *ip; xfs_suminfo_t *smp; xfs_fsblock_t first; int nmap; int error; xfs_fileoff_t bno; xfs_fileoff_t end_bno; xfs_bmbt_irec_t map; struct xfs_trans_res tres = {0}; smp = sumcompute; bno = 0; end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog; error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp); if (error) res_failed(error); error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip); if (error) { do_error( _("couldn't iget realtime summary inode -- error - %d\n"), error); } first = NULLFSBLOCK; while (bno < end_bno) { /* * fill the file one block at a time */ nmap = 1; error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, &first, 1, &map, &nmap, NULL); if (error || nmap != 1) { do_error( _("couldn't map realtime summary inode block %" PRIu64 ", error = %d\n"), bno, error); } ASSERT(map.br_startblock != HOLESTARTBLOCK); error = -libxfs_trans_read_buf( mp, tp, mp->m_dev, XFS_FSB_TO_DADDR(mp, map.br_startblock), XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL); if (error) { do_warn( _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime summary inode %" PRIu64 "\n"), bno, map.br_startblock, mp->m_sb.sb_rsumino); IRELE(ip); return(1); } memmove(XFS_BUF_PTR(bp), smp, mp->m_sb.sb_blocksize); libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); smp = (xfs_suminfo_t *)((intptr_t)smp + mp->m_sb.sb_blocksize); bno++; } libxfs_trans_commit(tp); IRELE(ip); return(0); } static void mk_rsumino(xfs_mount_t *mp) { xfs_trans_t *tp; xfs_inode_t *ip; xfs_bmbt_irec_t *ep; xfs_fsblock_t first; int i; int nmap; int error; int nsumblocks; struct xfs_defer_ops dfops; xfs_fileoff_t bno; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; int vers; int times; struct xfs_trans_res tres = {0}; /* * first set up inode */ i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 10, 0, 0, &tp); if (i) res_failed(i); error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip); if (error) { do_error( _("couldn't iget realtime summary inode -- error - %d\n"), error); } vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 2; memset(&ip->i_d, 0, sizeof(ip->i_d)); VFS_I(ip)->i_mode = S_IFREG; ip->i_d.di_version = vers; ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; set_nlink(VFS_I(ip), 1); /* account for sb ptr */ times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD; if (ip->i_d.di_version == 3) { VFS_I(ip)->i_version = 1; ip->i_d.di_flags2 = 0; times |= XFS_ICHGTIME_CREATE; } libxfs_trans_ichgtime(tp, ip, times); /* * now the ifork */ ip->i_df.if_flags = XFS_IFEXTENTS; ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0; ip->i_df.if_u1.if_extents = NULL; ip->i_d.di_size = mp->m_rsumsize; /* * commit changes */ libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); libxfs_trans_commit(tp); /* * then allocate blocks for file and fill with zeroes (stolen * from mkfs) */ libxfs_defer_init(&dfops, &first); nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; tres.tr_logres = BBTOB(128); tres.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT; tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; error = -libxfs_trans_alloc(mp, &tres, mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); bno = 0; libxfs_defer_init(&dfops, &first); while (bno < nsumblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, ip, bno, (xfs_extlen_t)(nsumblocks - bno), 0, &first, nsumblocks, map, &nmap, &dfops); if (error) { do_error( _("couldn't allocate realtime summary inode, error = %d\n"), error); } for (i = 0, ep = map; i < nmap; i++, ep++) { libxfs_device_zero(mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, ep->br_startblock), XFS_FSB_TO_BB(mp, ep->br_blockcount)); bno += ep->br_blockcount; } } error = -libxfs_defer_finish(&tp, &dfops, ip); if (error) { do_error( _("allocation of the realtime summary ino failed, error = %d\n"), error); } libxfs_trans_commit(tp); IRELE(ip); } /* * makes a new root directory. */ static void mk_root_dir(xfs_mount_t *mp) { xfs_trans_t *tp; xfs_inode_t *ip; int i; int error; const mode_t mode = 0755; ino_tree_node_t *irec; int vers; int times; ip = NULL; i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 10, 0, 0, &tp); if (i) res_failed(i); error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rootino, 0, 0, &ip); if (error) { do_error(_("could not iget root inode -- error - %d\n"), error); } /* * take care of the core -- initialization from xfs_ialloc() */ vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 2; memset(&ip->i_d, 0, sizeof(ip->i_d)); VFS_I(ip)->i_mode = mode|S_IFDIR; ip->i_d.di_version = vers; ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; set_nlink(VFS_I(ip), 1); /* account for . */ times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD; if (ip->i_d.di_version == 3) { VFS_I(ip)->i_version = 1; ip->i_d.di_flags2 = 0; times |= XFS_ICHGTIME_CREATE; } libxfs_trans_ichgtime(tp, ip, times); libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); /* * now the ifork */ ip->i_df.if_flags = XFS_IFEXTENTS; ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0; ip->i_df.if_u1.if_extents = NULL; /* * initialize the directory */ ip->d_ops = mp->m_dir_inode_ops; libxfs_dir_init(tp, ip, ip); libxfs_trans_commit(tp); IRELE(ip); irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)); set_inode_isadir(irec, XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino) - irec->ino_startnum); } /* * orphanage name == lost+found */ static xfs_ino_t mk_orphanage(xfs_mount_t *mp) { xfs_ino_t ino; xfs_trans_t *tp; xfs_inode_t *ip; xfs_inode_t *pip; xfs_fsblock_t first; ino_tree_node_t *irec; int ino_offset = 0; int i; int error; struct xfs_defer_ops dfops; const int mode = 0755; int nres; struct xfs_name xname; /* * check for an existing lost+found first, if it exists, return * its inode. Otherwise, we can create it. Bad lost+found inodes * would have been cleared in phase3 and phase4. */ if ((i = -libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip))) do_error(_("%d - couldn't iget root inode to obtain %s\n"), i, ORPHANAGE); xname.name = (unsigned char *)ORPHANAGE; xname.len = strlen(ORPHANAGE); xname.type = XFS_DIR3_FT_DIR; if (libxfs_dir_lookup(NULL, pip, &xname, &ino, NULL) == 0) return ino; /* * could not be found, create it */ libxfs_defer_init(&dfops, &first); nres = XFS_MKDIR_SPACE_RES(mp, xname.len); i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); if (i) res_failed(i); /* * use iget/ijoin instead of trans_iget because the ialloc * wrapper can commit the transaction and start a new one */ /* if ((i = -libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip))) do_error(_("%d - couldn't iget root inode to make %s\n"), i, ORPHANAGE);*/ error = -libxfs_inode_alloc(&tp, pip, mode|S_IFDIR, 1, 0, &zerocr, &zerofsx, &ip); if (error) { do_error(_("%s inode allocation failed %d\n"), ORPHANAGE, error); } inc_nlink(VFS_I(ip)); /* account for . */ ino = ip->i_ino; irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, ino), XFS_INO_TO_AGINO(mp, ino)); if (irec == NULL) { /* * This inode is allocated from a newly created inode * chunk and therefore did not exist when inode chunks * were processed in phase3. Add this group of inodes to * the entry avl tree as if they were discovered in phase3. */ irec = set_inode_free_alloc(mp, XFS_INO_TO_AGNO(mp, ino), XFS_INO_TO_AGINO(mp, ino)); alloc_ex_data(irec); for (i = 0; i < XFS_INODES_PER_CHUNK; i++) set_inode_free(irec, i); } ino_offset = get_inode_offset(mp, ino, irec); /* * Mark the inode allocated to lost+found as used in the AVL tree * so it is not skipped in phase 7 */ set_inode_used(irec, ino_offset); add_inode_ref(irec, ino_offset); /* * now that we know the transaction will stay around, * add the root inode to it */ libxfs_trans_ijoin(tp, pip, 0); /* * create the actual entry */ error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first, &dfops, nres); if (error) do_error( _("can't make %s, createname error %d\n"), ORPHANAGE, error); /* * bump up the link count in the root directory to account * for .. in the new directory */ inc_nlink(VFS_I(pip)); add_inode_ref(find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)), 0); libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); libxfs_dir_init(tp, ip, pip); libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); error = -libxfs_defer_finish(&tp, &dfops, ip); if (error) { do_error(_("%s directory creation failed -- bmapf error %d\n"), ORPHANAGE, error); } libxfs_trans_commit(tp); IRELE(ip); IRELE(pip); add_inode_reached(irec,ino_offset); return(ino); } /* * move a file to the orphange. */ static void mv_orphanage( xfs_mount_t *mp, xfs_ino_t ino, /* inode # to be moved */ int isa_dir) /* 1 if inode is a directory */ { xfs_inode_t *orphanage_ip; xfs_ino_t entry_ino_num; xfs_inode_t *ino_p; xfs_trans_t *tp; xfs_fsblock_t first; struct xfs_defer_ops dfops; int err; unsigned char fname[MAXPATHLEN + 1]; int nres; int incr; ino_tree_node_t *irec; int ino_offset = 0; struct xfs_name xname; xname.name = fname; xname.len = snprintf((char *)fname, sizeof(fname), "%llu", (unsigned long long)ino); err = -libxfs_iget(mp, NULL, orphanage_ino, 0, &orphanage_ip); if (err) do_error(_("%d - couldn't iget orphanage inode\n"), err); /* * Make sure the filename is unique in the lost+found */ incr = 0; while (libxfs_dir_lookup(NULL, orphanage_ip, &xname, &entry_ino_num, NULL) == 0) xname.len = snprintf((char *)fname, sizeof(fname), "%llu.%d", (unsigned long long)ino, ++incr); if ((err = -libxfs_iget(mp, NULL, ino, 0, &ino_p))) do_error(_("%d - couldn't iget disconnected inode\n"), err); xname.type = xfs_mode_to_ftype[(VFS_I(ino_p)->i_mode & S_IFMT)>>S_SHIFT]; if (isa_dir) { irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, orphanage_ino), XFS_INO_TO_AGINO(mp, orphanage_ino)); if (irec) ino_offset = XFS_INO_TO_AGINO(mp, orphanage_ino) - irec->ino_startnum; nres = XFS_DIRENTER_SPACE_RES(mp, fnamelen) + XFS_DIRENTER_SPACE_RES(mp, 2); err = -libxfs_dir_lookup(NULL, ino_p, &xfs_name_dotdot, &entry_ino_num, NULL); if (err) { ASSERT(err == ENOENT); err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename, nres, 0, 0, &tp); if (err) do_error( _("space reservation failed (%d), filesystem may be out of space\n"), err); libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); libxfs_defer_init(&dfops, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino, &first, &dfops, nres); if (err) do_error( _("name create failed in %s (%d), filesystem may be out of space\n"), ORPHANAGE, err); if (irec) add_inode_ref(irec, ino_offset); else inc_nlink(VFS_I(orphanage_ip)); libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE); err = -libxfs_dir_createname(tp, ino_p, &xfs_name_dotdot, orphanage_ino, &first, &dfops, nres); if (err) do_error( _("creation of .. entry failed (%d), filesystem may be out of space\n"), err); inc_nlink(VFS_I(ino_p)); libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE); err = -libxfs_defer_finish(&tp, &dfops, ino_p); if (err) do_error( _("bmap finish failed (err - %d), filesystem may be out of space\n"), err); libxfs_trans_commit(tp); } else { err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename, nres, 0, 0, &tp); if (err) do_error( _("space reservation failed (%d), filesystem may be out of space\n"), err); libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); libxfs_defer_init(&dfops, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino, &first, &dfops, nres); if (err) do_error( _("name create failed in %s (%d), filesystem may be out of space\n"), ORPHANAGE, err); if (irec) add_inode_ref(irec, ino_offset); else inc_nlink(VFS_I(orphanage_ip)); libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE); /* * don't replace .. value if it already points * to us. that'll pop a libxfs/kernel ASSERT. */ if (entry_ino_num != orphanage_ino) { err = -libxfs_dir_replace(tp, ino_p, &xfs_name_dotdot, orphanage_ino, &first, &dfops, nres); if (err) do_error( _("name replace op failed (%d), filesystem may be out of space\n"), err); } err = -libxfs_defer_finish(&tp, &dfops, ino_p); if (err) do_error( _("bmap finish failed (%d), filesystem may be out of space\n"), err); libxfs_trans_commit(tp); } } else { /* * use the remove log reservation as that's * more accurate. we're only creating the * links, we're not doing the inode allocation * also accounted for in the create */ nres = XFS_DIRENTER_SPACE_RES(mp, xname.len); err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (err) do_error( _("space reservation failed (%d), filesystem may be out of space\n"), err); libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); libxfs_defer_init(&dfops, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino, &first, &dfops, nres); if (err) do_error( _("name create failed in %s (%d), filesystem may be out of space\n"), ORPHANAGE, err); ASSERT(err == 0); set_nlink(VFS_I(ino_p), 1); libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE); err = -libxfs_defer_finish(&tp, &dfops, ino_p); if (err) do_error( _("bmap finish failed (%d), filesystem may be out of space\n"), err); libxfs_trans_commit(tp); } IRELE(ino_p); IRELE(orphanage_ip); } static int entry_junked( const char *msg, const char *iname, xfs_ino_t ino1, xfs_ino_t ino2) { do_warn(msg, iname, ino1, ino2); if (!no_modify) { if (verbose) do_warn(_(", marking entry to be junked\n")); else do_warn("\n"); } else do_warn(_(", would junk entry\n")); return !no_modify; } /* * Unexpected failure during the rebuild will leave the entries in * lost+found on the next run */ static void longform_dir2_rebuild( xfs_mount_t *mp, xfs_ino_t ino, xfs_inode_t *ip, ino_tree_node_t *irec, int ino_offset, dir_hash_tab_t *hashtab) { int error; int nres; xfs_trans_t *tp; xfs_fileoff_t lastblock; xfs_fsblock_t firstblock; struct xfs_defer_ops dfops; xfs_inode_t pip; dir_hash_ent_t *p; int done; /* * trash directory completely and rebuild from scratch using the * name/inode pairs in the hash table */ do_warn(_("rebuilding directory inode %" PRIu64 "\n"), ino); /* * first attempt to locate the parent inode, if it can't be * found, set it to the root inode and it'll be moved to the * orphanage later (the inode number here needs to be valid * for the libxfs_dir_init() call). */ pip.i_ino = get_inode_parent(irec, ino_offset); if (pip.i_ino == NULLFSINO || libxfs_dir_ino_validate(mp, pip.i_ino)) pip.i_ino = mp->m_sb.sb_rootino; libxfs_defer_init(&dfops, &firstblock); nres = XFS_REMOVE_SPACE_RES(mp); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); if ((error = -libxfs_bmap_last_offset(ip, &lastblock, XFS_DATA_FORK))) do_error(_("xfs_bmap_last_offset failed -- error - %d\n"), error); /* free all data, leaf, node and freespace blocks */ error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA, 0, &firstblock, &dfops, &done); if (error) { do_warn(_("xfs_bunmapi failed -- error - %d\n"), error); goto out_bmap_cancel; } ASSERT(done); error = -libxfs_dir_init(tp, ip, &pip); if (error) { do_warn(_("xfs_dir_init failed -- error - %d\n"), error); goto out_bmap_cancel; } error = -libxfs_defer_finish(&tp, &dfops, ip); libxfs_trans_commit(tp); if (ino == mp->m_sb.sb_rootino) need_root_dotdot = 0; /* go through the hash list and re-add the inodes */ for (p = hashtab->first; p; p = p->nextbyorder) { if (p->name.name[0] == '/' || (p->name.name[0] == '.' && (p->name.len == 1 || (p->name.len == 2 && p->name.name[1] == '.')))) continue; nres = XFS_CREATE_SPACE_RES(mp, p->name.len); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_create, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); libxfs_defer_init(&dfops, &firstblock); error = -libxfs_dir_createname(tp, ip, &p->name, p->inum, &firstblock, &dfops, nres); if (error) { do_warn( _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"), ino, error); goto out_bmap_cancel; } error = -libxfs_defer_finish(&tp, &dfops, ip); if (error) { do_warn( _("bmap finish failed (%d), filesystem may be out of space\n"), error); goto out_bmap_cancel; } libxfs_trans_commit(tp); } return; out_bmap_cancel: libxfs_defer_cancel(&dfops); libxfs_trans_cancel(tp); return; } /* * Kill a block in a version 2 inode. * Makes its own transaction. */ static void dir2_kill_block( xfs_mount_t *mp, xfs_inode_t *ip, xfs_dablk_t da_bno, struct xfs_buf *bp) { xfs_da_args_t args; int error; xfs_fsblock_t firstblock; struct xfs_defer_ops dfops; int nres; xfs_trans_t *tp; nres = XFS_REMOVE_SPACE_RES(mp); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); libxfs_trans_bjoin(tp, bp); memset(&args, 0, sizeof(args)); libxfs_defer_init(&dfops, &firstblock); args.dp = ip; args.trans = tp; args.firstblock = &firstblock; args.dfops = &dfops; args.whichfork = XFS_DATA_FORK; args.geo = mp->m_dir_geo; if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk) error = -libxfs_da_shrink_inode(&args, da_bno, bp); else error = -libxfs_dir2_shrink_inode(&args, xfs_dir2_da_to_db(mp->m_dir_geo, da_bno), bp); if (error) do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"), ip->i_ino, da_bno); libxfs_defer_finish(&tp, &dfops, ip); libxfs_trans_commit(tp); } /* * process a data block, also checks for .. entry * and corrects it to match what we think .. should be */ static void longform_dir2_entry_check_data( xfs_mount_t *mp, xfs_inode_t *ip, int *num_illegal, int *need_dot, ino_tree_node_t *current_irec, int current_ino_offset, struct xfs_buf **bpp, dir_hash_tab_t *hashtab, freetab_t **freetabp, xfs_dablk_t da_bno, int isblock) { xfs_dir2_dataptr_t addr; xfs_dir2_leaf_entry_t *blp; struct xfs_buf *bp; xfs_dir2_block_tail_t *btp; struct xfs_dir2_data_hdr *d; xfs_dir2_db_t db; xfs_dir2_data_entry_t *dep; xfs_dir2_data_unused_t *dup; struct xfs_dir2_data_free *bf; char *endptr; int error; xfs_fsblock_t firstblock; struct xfs_defer_ops dfops; char fname[MAXNAMELEN + 1]; freetab_t *freetab; int i; int ino_offset; xfs_ino_t inum; ino_tree_node_t *irec; int junkit; int lastfree; int len; int nbad; int needlog; int needscan; xfs_ino_t parent; char *ptr; xfs_trans_t *tp; int wantmagic; struct xfs_da_args da = { .dp = ip, .geo = mp->m_dir_geo, }; bp = *bpp; d = bp->b_addr; ptr = (char *)M_DIROPS(mp)->data_entry_p(d); nbad = 0; needscan = needlog = 0; junkit = 0; freetab = *freetabp; if (isblock) { btp = xfs_dir2_block_tail_p(mp->m_dir_geo, d); blp = xfs_dir2_block_leaf_p(btp); endptr = (char *)blp; if (endptr > (char *)btp) endptr = (char *)btp; if (xfs_sb_version_hascrc(&mp->m_sb)) wantmagic = XFS_DIR3_BLOCK_MAGIC; else wantmagic = XFS_DIR2_BLOCK_MAGIC; } else { endptr = (char *)d + mp->m_dir_geo->blksize; if (xfs_sb_version_hascrc(&mp->m_sb)) wantmagic = XFS_DIR3_DATA_MAGIC; else wantmagic = XFS_DIR2_DATA_MAGIC; } db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno); /* check for data block beyond expected end */ if (freetab->naents <= db) { struct freetab_ent e; *freetabp = freetab = realloc(freetab, FREETAB_SIZE(db + 1)); if (!freetab) { do_error(_("realloc failed in %s (%zu bytes)\n"), __func__, FREETAB_SIZE(db + 1)); } e.v = NULLDATAOFF; e.s = 0; for (i = freetab->naents; i < db; i++) freetab->ents[i] = e; freetab->naents = db + 1; } /* check the data block */ while (ptr < endptr) { /* check for freespace */ dup = (xfs_dir2_data_unused_t *)ptr; if (XFS_DIR2_DATA_FREE_TAG == be16_to_cpu(dup->freetag)) { /* check for invalid freespace length */ if (ptr + be16_to_cpu(dup->length) > endptr || be16_to_cpu(dup->length) == 0 || (be16_to_cpu(dup->length) & (XFS_DIR2_DATA_ALIGN - 1))) break; /* check for invalid tag */ if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) != (char *)dup - (char *)d) break; /* check for block with no data entries */ if ((ptr == (char *)M_DIROPS(mp)->data_entry_p(d)) && (ptr + be16_to_cpu(dup->length) >= endptr)) { junkit = 1; *num_illegal += 1; break; } /* continue at the end of the freespace */ ptr += be16_to_cpu(dup->length); if (ptr >= endptr) break; } /* validate data entry size */ dep = (xfs_dir2_data_entry_t *)ptr; if (ptr + M_DIROPS(mp)->data_entsize(dep->namelen) > endptr) break; if (be16_to_cpu(*M_DIROPS(mp)->data_entry_tag_p(dep)) != (char *)dep - (char *)d) break; ptr += M_DIROPS(mp)->data_entsize(dep->namelen); } /* did we find an empty or corrupt block? */ if (ptr != endptr) { if (junkit) { do_warn( _("empty data block %u in directory inode %" PRIu64 ": "), da_bno, ip->i_ino); } else { do_warn(_ ("corrupt block %u in directory inode %" PRIu64 ": "), da_bno, ip->i_ino); } if (!no_modify) { do_warn(_("junking block\n")); dir2_kill_block(mp, ip, da_bno, bp); } else { do_warn(_("would junk block\n")); libxfs_putbuf(bp); } freetab->ents[db].v = NULLDATAOFF; *bpp = NULL; return; } /* update number of data blocks processed */ if (freetab->nents < db + 1) freetab->nents = db + 1; error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, 0, 0, 0, &tp); if (error) res_failed(error); da.trans = tp; libxfs_trans_ijoin(tp, ip, 0); libxfs_trans_bjoin(tp, bp); libxfs_trans_bhold(tp, bp); libxfs_defer_init(&dfops, &firstblock); if (be32_to_cpu(d->magic) != wantmagic) { do_warn( _("bad directory block magic # %#x for directory inode %" PRIu64 " block %d: "), be32_to_cpu(d->magic), ip->i_ino, da_bno); if (!no_modify) { do_warn(_("fixing magic # to %#x\n"), wantmagic); d->magic = cpu_to_be32(wantmagic); needlog = 1; } else do_warn(_("would fix magic # to %#x\n"), wantmagic); } lastfree = 0; ptr = (char *)M_DIROPS(mp)->data_entry_p(d); /* * look at each entry. reference inode pointed to by each * entry in the incore inode tree. * if not a directory, set reached flag, increment link count * if a directory and reached, mark entry as to be deleted. * if a directory, check to see if recorded parent * matches current inode #, * if so, then set reached flag, increment link count * of current and child dir inodes, push the child * directory inode onto the directory stack. * if current inode != parent, then mark entry to be deleted. */ while (ptr < endptr) { dup = (xfs_dir2_data_unused_t *)ptr; if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { if (lastfree) { do_warn( _("directory inode %" PRIu64 " block %u has consecutive free entries: "), ip->i_ino, da_bno); if (!no_modify) { do_warn(_("joining together\n")); len = be16_to_cpu(dup->length); libxfs_dir2_data_use_free(&da, bp, dup, ptr - (char *)d, len, &needlog, &needscan); libxfs_dir2_data_make_free(&da, bp, ptr - (char *)d, len, &needlog, &needscan); } else do_warn(_("would join together\n")); } ptr += be16_to_cpu(dup->length); lastfree = 1; continue; } addr = xfs_dir2_db_off_to_dataptr(mp->m_dir_geo, db, ptr - (char *)d); dep = (xfs_dir2_data_entry_t *)ptr; ptr += M_DIROPS(mp)->data_entsize(dep->namelen); inum = be64_to_cpu(dep->inumber); lastfree = 0; /* * skip bogus entries (leading '/'). they'll be deleted * later. must still log it, else we leak references to * buffers. */ if (dep->name[0] == '/') { nbad++; if (!no_modify) libxfs_dir2_data_log_entry(&da, bp, dep); continue; } memmove(fname, dep->name, dep->namelen); fname[dep->namelen] = '\0'; ASSERT(inum != NULLFSINO); irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, inum), XFS_INO_TO_AGINO(mp, inum)); if (irec == NULL) { nbad++; if (entry_junked( _("entry \"%s\" in directory inode %" PRIu64 " points to non-existent inode %" PRIu64 ""), fname, ip->i_ino, inum)) { dep->name[0] = '/'; libxfs_dir2_data_log_entry(&da, bp, dep); } continue; } ino_offset = XFS_INO_TO_AGINO(mp, inum) - irec->ino_startnum; /* * if it's a free inode, blow out the entry. * by now, any inode that we think is free * really is free. */ if (is_inode_free(irec, ino_offset)) { nbad++; if (entry_junked( _("entry \"%s\" in directory inode %" PRIu64 " points to free inode %" PRIu64), fname, ip->i_ino, inum)) { dep->name[0] = '/'; libxfs_dir2_data_log_entry(&da, bp, dep); } continue; } /* * check if this inode is lost+found dir in the root */ if (inum == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) { /* * if it's not a directory, trash it */ if (!inode_isadir(irec, ino_offset)) { nbad++; if (entry_junked( _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"), ORPHANAGE, inum, ip->i_ino)) { dep->name[0] = '/'; libxfs_dir2_data_log_entry(&da, bp, dep); } continue; } /* * if this is a dup, it will be picked up below, * otherwise, mark it as the orphanage for later. */ if (!orphanage_ino) orphanage_ino = inum; } /* * check for duplicate names in directory. */ if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen, dep->name, M_DIROPS(mp)->data_get_ftype(dep))) { nbad++; if (entry_junked( _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"), fname, inum, ip->i_ino)) { dep->name[0] = '/'; libxfs_dir2_data_log_entry(&da, bp, dep); } if (inum == orphanage_ino) orphanage_ino = 0; continue; } /* * if just scanning to rebuild a directory due to a ".." * update, just continue */ if (dotdot_update) continue; /* * skip the '..' entry since it's checked when the * directory is reached by something else. if it never * gets reached, it'll be moved to the orphanage and we'll * take care of it then. If it doesn't exist at all, the * directory needs to be rebuilt first before being added * to the orphanage. */ if (dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.') { if (da_bno != 0) { /* ".." should be in the first block */ nbad++; if (entry_junked( _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is not in the the first block"), fname, inum, ip->i_ino)) { dep->name[0] = '/'; libxfs_dir2_data_log_entry(&da, bp, dep); } } continue; } ASSERT(no_modify || !verify_inum(mp, inum)); /* * special case the . entry. we know there's only one * '.' and only '.' points to itself because bogus entries * got trashed in phase 3 if there were > 1. * bump up link count for '.' but don't set reached * until we're actually reached by another directory * '..' is already accounted for or will be taken care * of when directory is moved to orphanage. */ if (ip->i_ino == inum) { ASSERT(dep->name[0] == '.' && dep->namelen == 1); add_inode_ref(current_irec, current_ino_offset); if (da_bno != 0 || dep != M_DIROPS(mp)->data_entry_p(d)) { /* "." should be the first entry */ nbad++; if (entry_junked( _("entry \"%s\" in dir %" PRIu64 " is not the first entry"), fname, inum, ip->i_ino)) { dep->name[0] = '/'; libxfs_dir2_data_log_entry(&da, bp, dep); } } *need_dot = 0; continue; } /* * skip entries with bogus inumbers if we're in no modify mode */ if (no_modify && verify_inum(mp, inum)) continue; /* validate ftype field if supported */ if (xfs_sb_version_hasftype(&mp->m_sb)) { __uint8_t dir_ftype; __uint8_t ino_ftype; dir_ftype = M_DIROPS(mp)->data_get_ftype(dep); ino_ftype = get_inode_ftype(irec, ino_offset); if (dir_ftype != ino_ftype) { if (no_modify) { do_warn( _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"), dir_ftype, ino_ftype, ip->i_ino, inum); } else { do_warn( _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"), dir_ftype, ino_ftype, ip->i_ino, inum); M_DIROPS(mp)->data_put_ftype(dep, ino_ftype); libxfs_dir2_data_log_entry(&da, bp, dep); dir_hash_update_ftype(hashtab, addr, ino_ftype); } } } /* * check easy case first, regular inode, just bump * the link count and continue */ if (!inode_isadir(irec, ino_offset)) { add_inode_reached(irec, ino_offset); continue; } parent = get_inode_parent(irec, ino_offset); ASSERT(parent != 0); junkit = 0; /* * bump up the link counts in parent and child * directory but if the link doesn't agree with * the .. in the child, blow out the entry. * if the directory has already been reached, * blow away the entry also. */ if (is_inode_reached(irec, ino_offset)) { junkit = 1; do_warn( _("entry \"%s\" in dir %" PRIu64" points to an already connected directory inode %" PRIu64 "\n"), fname, ip->i_ino, inum); } else if (parent == ip->i_ino) { add_inode_reached(irec, ino_offset); add_inode_ref(current_irec, current_ino_offset); } else if (parent == NULLFSINO) { /* ".." was missing, but this entry refers to it, so, set it as the parent and mark for rebuild */ do_warn( _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"), fname, ip->i_ino, inum); set_inode_parent(irec, ino_offset, ip->i_ino); add_inode_reached(irec, ino_offset); add_inode_ref(current_irec, current_ino_offset); add_dotdot_update(XFS_INO_TO_AGNO(mp, inum), irec, ino_offset); } else { junkit = 1; do_warn( _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 ") in ino %" PRIu64 "\n"), fname, ip->i_ino, parent, inum); } if (junkit) { if (inum == orphanage_ino) orphanage_ino = 0; nbad++; if (!no_modify) { dep->name[0] = '/'; libxfs_dir2_data_log_entry(&da, bp, dep); if (verbose) do_warn( _("\twill clear entry \"%s\"\n"), fname); } else { do_warn(_("\twould clear entry \"%s\"\n"), fname); } } } *num_illegal += nbad; if (needscan) libxfs_dir2_data_freescan(mp->m_dir_geo, M_DIROPS(mp), d, &i); if (needlog) libxfs_dir2_data_log_header(&da, bp); libxfs_defer_finish(&tp, &dfops, ip); libxfs_trans_commit(tp); /* record the largest free space in the freetab for later checking */ bf = M_DIROPS(mp)->data_bestfree_p(d); freetab->ents[db].v = be16_to_cpu(bf[0].length); freetab->ents[db].s = 0; } /* check v5 metadata */ static int __check_dir3_header( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino, __be64 owner, __be64 blkno, uuid_t *uuid) { /* verify owner */ if (be64_to_cpu(owner) != ino) { do_warn( _("expected owner inode %" PRIu64 ", got %llu, directory block %" PRIu64 "\n"), ino, be64_to_cpu(owner), bp->b_bn); return 1; } /* verify block number */ if (be64_to_cpu(blkno) != bp->b_bn) { do_warn( _("expected block %" PRIu64 ", got %llu, directory inode %" PRIu64 "\n"), bp->b_bn, be64_to_cpu(blkno), ino); return 1; } /* verify uuid */ if (platform_uuid_compare(uuid, &mp->m_sb.sb_meta_uuid) != 0) { do_warn( _("wrong FS UUID, directory inode %" PRIu64 " block %" PRIu64 "\n"), ino, bp->b_bn); return 1; } return 0; } static int check_da3_header( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino) { struct xfs_da3_blkinfo *info = bp->b_addr; return __check_dir3_header(mp, bp, ino, info->owner, info->blkno, &info->uuid); } static int check_dir3_header( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino) { struct xfs_dir3_blk_hdr *info = bp->b_addr; return __check_dir3_header(mp, bp, ino, info->owner, info->blkno, &info->uuid); } /* * Check contents of leaf-form block. */ static int longform_dir2_check_leaf( xfs_mount_t *mp, xfs_inode_t *ip, dir_hash_tab_t *hashtab, freetab_t *freetab) { int badtail; __be16 *bestsp; struct xfs_buf *bp; xfs_dablk_t da_bno; int i; xfs_dir2_leaf_t *leaf; xfs_dir2_leaf_tail_t *ltp; int seeval; struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; int error; int fixit = 0; da_bno = mp->m_dir_geo->leafblk; error = dir_read_buf(ip, da_bno, -1, &bp, &xfs_dir3_leaf1_buf_ops, &fixit); if (error == EFSBADCRC || error == EFSCORRUPTED || fixit) { do_warn( _("leaf block %u for directory inode %" PRIu64 " bad CRC\n"), da_bno, ip->i_ino); return 1; } else if (error) { do_error( _("can't read block %u for directory inode %" PRIu64 ", error %d\n"), da_bno, ip->i_ino, error); /* NOTREACHED */ } leaf = bp->b_addr; M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf); ents = M_DIROPS(mp)->leaf_ents_p(leaf); ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); if (!(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) || leafhdr.forw || leafhdr.back || leafhdr.count < leafhdr.stale || leafhdr.count > M_DIROPS(mp)->leaf_max_ents(mp->m_dir_geo) || (char *)&ents[leafhdr.count] > (char *)bestsp) { do_warn( _("leaf block %u for directory inode %" PRIu64 " bad header\n"), da_bno, ip->i_ino); libxfs_putbuf(bp); return 1; } if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) { error = check_da3_header(mp, bp, ip->i_ino); if (error) { libxfs_putbuf(bp); return error; } } seeval = dir_hash_see_all(hashtab, ents, leafhdr.count, leafhdr.stale); if (dir_hash_check(hashtab, ip, seeval)) { libxfs_putbuf(bp); return 1; } badtail = freetab->nents != be32_to_cpu(ltp->bestcount); for (i = 0; !badtail && i < be32_to_cpu(ltp->bestcount); i++) { freetab->ents[i].s = 1; badtail = freetab->ents[i].v != be16_to_cpu(bestsp[i]); } if (badtail) { do_warn( _("leaf block %u for directory inode %" PRIu64 " bad tail\n"), da_bno, ip->i_ino); libxfs_putbuf(bp); return 1; } libxfs_putbuf(bp); return fixit; } /* * Check contents of the node blocks (leaves) * Looks for matching hash values for the data entries. */ static int longform_dir2_check_node( xfs_mount_t *mp, xfs_inode_t *ip, dir_hash_tab_t *hashtab, freetab_t *freetab) { struct xfs_buf *bp; xfs_dablk_t da_bno; xfs_dir2_db_t fdb; xfs_dir2_free_t *free; int i; xfs_dir2_leaf_t *leaf; xfs_fileoff_t next_da_bno; int seeval = 0; int used; struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir3_icfree_hdr freehdr; __be16 *bests; int error; int fixit = 0; for (da_bno = mp->m_dir_geo->leafblk, next_da_bno = 0; next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->freeblk; da_bno = (xfs_dablk_t)next_da_bno) { next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1; if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) break; /* * we need to use the da3 node verifier here as it handles the * fact that reading the leaf hash tree blocks can return either * leaf or node blocks and calls the correct verifier. If we get * a node block, then we'll skip it below based on a magic * number check. */ error = dir_read_buf(ip, da_bno, -1, &bp, &xfs_da3_node_buf_ops, &fixit); if (error) { do_warn( _("can't read leaf block %u for directory inode %" PRIu64 ", error %d\n"), da_bno, ip->i_ino, error); return 1; } leaf = bp->b_addr; M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf); ents = M_DIROPS(mp)->leaf_ents_p(leaf); if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC || leafhdr.magic == XFS_DA_NODE_MAGIC || leafhdr.magic == XFS_DA3_NODE_MAGIC)) { do_warn( _("unknown magic number %#x for block %u in directory inode %" PRIu64 "\n"), leafhdr.magic, da_bno, ip->i_ino); libxfs_putbuf(bp); return 1; } /* check v5 metadata */ if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC || leafhdr.magic == XFS_DA3_NODE_MAGIC) { error = check_da3_header(mp, bp, ip->i_ino); if (error) { libxfs_putbuf(bp); return error; } } /* ignore nodes */ if (leafhdr.magic == XFS_DA_NODE_MAGIC || leafhdr.magic == XFS_DA3_NODE_MAGIC) { libxfs_putbuf(bp); continue; } /* * If there's a validator error, we need to ensure that we got * the right ops on the buffer for when we write it back out. */ bp->b_ops = &xfs_dir3_leafn_buf_ops; if (leafhdr.count > M_DIROPS(mp)->leaf_max_ents(mp->m_dir_geo) || leafhdr.count < leafhdr.stale) { do_warn( _("leaf block %u for directory inode %" PRIu64 " bad header\n"), da_bno, ip->i_ino); libxfs_putbuf(bp); return 1; } seeval = dir_hash_see_all(hashtab, ents, leafhdr.count, leafhdr.stale); libxfs_putbuf(bp); if (seeval != DIR_HASH_CK_OK) return 1; } if (dir_hash_check(hashtab, ip, seeval)) return 1; for (da_bno = mp->m_dir_geo->freeblk, next_da_bno = 0; next_da_bno != NULLFILEOFF; da_bno = (xfs_dablk_t)next_da_bno) { next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1; if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) break; error = dir_read_buf(ip, da_bno, -1, &bp, &xfs_dir3_free_buf_ops, &fixit); if (error) { do_warn( _("can't read freespace block %u for directory inode %" PRIu64 ", error %d\n"), da_bno, ip->i_ino, error); return 1; } free = bp->b_addr; M_DIROPS(mp)->free_hdr_from_disk(&freehdr, free); bests = M_DIROPS(mp)->free_bests_p(free); fdb = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno); if (!(freehdr.magic == XFS_DIR2_FREE_MAGIC || freehdr.magic == XFS_DIR3_FREE_MAGIC) || freehdr.firstdb != (fdb - xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) * M_DIROPS(mp)->free_max_bests(mp->m_dir_geo) || freehdr.nvalid < freehdr.nused) { do_warn( _("free block %u for directory inode %" PRIu64 " bad header\n"), da_bno, ip->i_ino); libxfs_putbuf(bp); return 1; } if (freehdr.magic == XFS_DIR3_FREE_MAGIC) { error = check_dir3_header(mp, bp, ip->i_ino); if (error) { libxfs_putbuf(bp); return error; } } for (i = used = 0; i < freehdr.nvalid; i++) { if (i + freehdr.firstdb >= freetab->nents || freetab->ents[i + freehdr.firstdb].v != be16_to_cpu(bests[i])) { do_warn( _("free block %u entry %i for directory ino %" PRIu64 " bad\n"), da_bno, i, ip->i_ino); libxfs_putbuf(bp); return 1; } used += be16_to_cpu(bests[i]) != NULLDATAOFF; freetab->ents[i + freehdr.firstdb].s = 1; } if (used != freehdr.nused) { do_warn( _("free block %u for directory inode %" PRIu64 " bad nused\n"), da_bno, ip->i_ino); libxfs_putbuf(bp); return 1; } libxfs_putbuf(bp); } for (i = 0; i < freetab->nents; i++) { if ((freetab->ents[i].s == 0) && (freetab->ents[i].v != NULLDATAOFF)) { do_warn( _("missing freetab entry %u for directory inode %" PRIu64 "\n"), i, ip->i_ino); return 1; } } return fixit; } /* * If a directory is corrupt, we need to read in as many entries as possible, * destroy the entry and create a new one with recovered name/inode pairs. * (ie. get libxfs to do all the grunt work) */ static void longform_dir2_entry_check(xfs_mount_t *mp, xfs_ino_t ino, xfs_inode_t *ip, int *num_illegal, int *need_dot, ino_tree_node_t *irec, int ino_offset, dir_hash_tab_t *hashtab) { struct xfs_buf **bplist; xfs_dablk_t da_bno; freetab_t *freetab; int num_bps; int i; int isblock; int isleaf; xfs_fileoff_t next_da_bno; int seeval; int fixit = 0; xfs_dir2_db_t db; struct xfs_da_args args; *need_dot = 1; freetab = malloc(FREETAB_SIZE(ip->i_d.di_size / mp->m_dir_geo->blksize)); if (!freetab) { do_error(_("malloc failed in %s (%" PRId64 " bytes)\n"), __func__, FREETAB_SIZE(ip->i_d.di_size / mp->m_dir_geo->blksize)); exit(1); } freetab->naents = ip->i_d.di_size / mp->m_dir_geo->blksize; freetab->nents = 0; for (i = 0; i < freetab->naents; i++) { freetab->ents[i].v = NULLDATAOFF; freetab->ents[i].s = 0; } num_bps = freetab->naents; bplist = calloc(num_bps, sizeof(struct xfs_buf*)); if (!bplist) do_error(_("calloc failed in %s (%zu bytes)\n"), __func__, num_bps * sizeof(struct xfs_buf*)); /* is this a block, leaf, or node directory? */ args.dp = ip; args.geo = mp->m_dir_geo; libxfs_dir2_isblock(&args, &isblock); libxfs_dir2_isleaf(&args, &isleaf); /* check directory "data" blocks (ie. name/inode pairs) */ for (da_bno = 0, next_da_bno = 0; next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->leafblk; da_bno = (xfs_dablk_t)next_da_bno) { const struct xfs_buf_ops *ops; int error; struct xfs_dir2_data_hdr *d; next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1; if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) { /* * if this is the first block, there isn't anything we * can recover so we just trash it. */ if (da_bno == 0) { fixit++; goto out_fix; } break; } db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno); if (db >= num_bps) { /* more data blocks than expected */ num_bps = db + 1; bplist = realloc(bplist, num_bps * sizeof(struct xfs_buf*)); if (!bplist) do_error(_("realloc failed in %s (%zu bytes)\n"), __func__, num_bps * sizeof(struct xfs_buf*)); } if (isblock) ops = &xfs_dir3_block_buf_ops; else ops = &xfs_dir3_data_buf_ops; error = dir_read_buf(ip, da_bno, -1, &bplist[db], ops, &fixit); if (error) { do_warn( _("can't read data block %u for directory inode %" PRIu64 " error %d\n"), da_bno, ino, error); *num_illegal += 1; /* * we try to read all "data" blocks, but if we are in * block form and we fail, there isn't anything else to * read, and nothing we can do but trash it. */ if (isblock) { fixit++; goto out_fix; } continue; } /* check v5 metadata */ d = bplist[db]->b_addr; if (be32_to_cpu(d->magic) == XFS_DIR3_BLOCK_MAGIC || be32_to_cpu(d->magic) == XFS_DIR3_DATA_MAGIC) { struct xfs_buf *bp = bplist[db]; error = check_dir3_header(mp, bp, ino); if (error) { fixit++; continue; } } longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot, irec, ino_offset, &bplist[db], hashtab, &freetab, da_bno, isblock); } fixit |= (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot; if (!dotdot_update) { /* check btree and freespace */ if (isblock) { struct xfs_dir2_data_hdr *block; xfs_dir2_block_tail_t *btp; xfs_dir2_leaf_entry_t *blp; block = bplist[0]->b_addr; btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); blp = xfs_dir2_block_leaf_p(btp); seeval = dir_hash_see_all(hashtab, blp, be32_to_cpu(btp->count), be32_to_cpu(btp->stale)); if (dir_hash_check(hashtab, ip, seeval)) fixit |= 1; } else if (isleaf) { fixit |= longform_dir2_check_leaf(mp, ip, hashtab, freetab); } else { fixit |= longform_dir2_check_node(mp, ip, hashtab, freetab); } } out_fix: if (!no_modify && (fixit || dotdot_update)) { dir_hash_dup_names(hashtab); for (i = 0; i < num_bps; i++) if (bplist[i]) libxfs_putbuf(bplist[i]); longform_dir2_rebuild(mp, ino, ip, irec, ino_offset, hashtab); *num_illegal = 0; *need_dot = 0; } else { for (i = 0; i < num_bps; i++) if (bplist[i]) libxfs_putbuf(bplist[i]); } free(bplist); free(freetab); } /* * shortform directory v2 processing routines -- entry verification and * bad entry deletion (pruning). */ static struct xfs_dir2_sf_entry * shortform_dir2_junk( struct xfs_mount *mp, struct xfs_dir2_sf_hdr *sfp, struct xfs_dir2_sf_entry *sfep, xfs_ino_t lino, int *max_size, int *index, int *bytes_deleted, int *ino_dirty) { struct xfs_dir2_sf_entry *next_sfep; int next_len; int next_elen; if (lino == orphanage_ino) orphanage_ino = 0; next_elen = M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen); next_sfep = M_DIROPS(mp)->sf_nextentry(sfp, sfep); /* * if we are just checking, simply return the pointer to the next entry * here so that the checking loop can continue. */ if (no_modify) { do_warn(_("would junk entry\n")); return next_sfep; } /* * now move all the remaining entries down over the junked entry and * clear the newly unused bytes at the tail of the directory region. */ next_len = *max_size - ((intptr_t)next_sfep - (intptr_t)sfp); *max_size -= next_elen; *bytes_deleted += next_elen; memmove(sfep, next_sfep, next_len); memset((void *)((intptr_t)sfep + next_len), 0, next_elen); sfp->count -= 1; *ino_dirty = 1; /* * WARNING: drop the index i by one so it matches the decremented count * for accurate comparisons in the loop test */ (*index)--; if (verbose) do_warn(_("junking entry\n")); else do_warn("\n"); return sfep; } static void shortform_dir2_entry_check(xfs_mount_t *mp, xfs_ino_t ino, xfs_inode_t *ip, int *ino_dirty, ino_tree_node_t *current_irec, int current_ino_offset, dir_hash_tab_t *hashtab) { xfs_ino_t lino; xfs_ino_t parent; struct xfs_dir2_sf_hdr *sfp; struct xfs_dir2_sf_entry *sfep; struct xfs_dir2_sf_entry *next_sfep; struct xfs_ifork *ifp; struct ino_tree_node *irec; int max_size; int ino_offset; int i; int bad_sfnamelen; int namelen; int bytes_deleted; char fname[MAXNAMELEN + 1]; int i8; ifp = &ip->i_df; sfp = (struct xfs_dir2_sf_hdr *) ifp->if_u1.if_data; *ino_dirty = 0; bytes_deleted = 0; max_size = ifp->if_bytes; ASSERT(ip->i_d.di_size <= ifp->if_bytes); /* * if just rebuild a directory due to a "..", update and return */ if (dotdot_update) { parent = get_inode_parent(current_irec, current_ino_offset); if (no_modify) { do_warn( _("would set .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"), ino, parent); } else { do_warn( _("setting .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"), ino, parent); M_DIROPS(mp)->sf_put_parent_ino(sfp, parent); *ino_dirty = 1; } return; } /* * no '.' entry in shortform dirs, just bump up ref count by 1 * '..' was already (or will be) accounted for and checked when * the directory is reached or will be taken care of when the * directory is moved to orphanage. */ add_inode_ref(current_irec, current_ino_offset); /* * Initialise i8 counter -- the parent inode number counts as well. */ i8 = M_DIROPS(mp)->sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM; /* * now run through entries, stop at first bad entry, don't need * to skip over '..' since that's encoded in its own field and * no need to worry about '.' since it doesn't exist. */ sfep = next_sfep = xfs_dir2_sf_firstentry(sfp); for (i = 0; i < sfp->count && max_size > (intptr_t)next_sfep - (intptr_t)sfp; sfep = next_sfep, i++) { bad_sfnamelen = 0; lino = M_DIROPS(mp)->sf_get_ino(sfp, sfep); namelen = sfep->namelen; ASSERT(no_modify || namelen > 0); if (no_modify && namelen == 0) { /* * if we're really lucky, this is * the last entry in which case we * can use the dir size to set the * namelen value. otherwise, forget * it because we're not going to be * able to find the next entry. */ bad_sfnamelen = 1; if (i == sfp->count - 1) { namelen = ip->i_d.di_size - ((intptr_t) &sfep->name[0] - (intptr_t) sfp); } else { /* * don't process the rest of the directory, * break out of processing loop */ break; } } else if (no_modify && (intptr_t) sfep - (intptr_t) sfp + + M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen) > ip->i_d.di_size) { bad_sfnamelen = 1; if (i == sfp->count - 1) { namelen = ip->i_d.di_size - ((intptr_t) &sfep->name[0] - (intptr_t) sfp); } else { /* * don't process the rest of the directory, * break out of processing loop */ break; } } memmove(fname, sfep->name, sfep->namelen); fname[sfep->namelen] = '\0'; ASSERT(no_modify || (lino != NULLFSINO && lino != 0)); ASSERT(no_modify || !verify_inum(mp, lino)); /* * Also skip entries with bogus inode numbers if we're * in no modify mode. */ if (no_modify && verify_inum(mp, lino)) { next_sfep = M_DIROPS(mp)->sf_nextentry(sfp, sfep); continue; } irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino), XFS_INO_TO_AGINO(mp, lino)); if (irec == NULL) { do_warn( _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 "\n"), fname, ino, lino); next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino, &max_size, &i, &bytes_deleted, ino_dirty); continue; } ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum; /* * if it's a free inode, blow out the entry. * by now, any inode that we think is free * really is free. */ if (is_inode_free(irec, ino_offset)) { do_warn( _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 "\n"), fname, ino, lino); next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino, &max_size, &i, &bytes_deleted, ino_dirty); continue; } /* * check if this inode is lost+found dir in the root */ if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) { /* * if it's not a directory, trash it */ if (!inode_isadir(irec, ino_offset)) { do_warn( _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"), ORPHANAGE, lino, ino); next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino, &max_size, &i, &bytes_deleted, ino_dirty); continue; } /* * if this is a dup, it will be picked up below, * otherwise, mark it as the orphanage for later. */ if (!orphanage_ino) orphanage_ino = lino; } /* * check for duplicate names in directory. */ if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t) (sfep - xfs_dir2_sf_firstentry(sfp)), lino, sfep->namelen, sfep->name, M_DIROPS(mp)->sf_get_ftype(sfep))) { do_warn( _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"), fname, lino, ino); next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino, &max_size, &i, &bytes_deleted, ino_dirty); continue; } if (!inode_isadir(irec, ino_offset)) { /* * check easy case first, regular inode, just bump * the link count */ add_inode_reached(irec, ino_offset); } else { parent = get_inode_parent(irec, ino_offset); /* * bump up the link counts in parent and child. * directory but if the link doesn't agree with * the .. in the child, blow out the entry */ if (is_inode_reached(irec, ino_offset)) { do_warn( _("entry \"%s\" in directory inode %" PRIu64 " references already connected inode %" PRIu64 ".\n"), fname, ino, lino); next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino, &max_size, &i, &bytes_deleted, ino_dirty); continue; } else if (parent == ino) { add_inode_reached(irec, ino_offset); add_inode_ref(current_irec, current_ino_offset); } else if (parent == NULLFSINO) { /* ".." was missing, but this entry refers to it, so, set it as the parent and mark for rebuild */ do_warn( _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"), fname, ino, lino); set_inode_parent(irec, ino_offset, ino); add_inode_reached(irec, ino_offset); add_inode_ref(current_irec, current_ino_offset); add_dotdot_update(XFS_INO_TO_AGNO(mp, lino), irec, ino_offset); } else { do_warn( _("entry \"%s\" in directory inode %" PRIu64 " not consistent with .. value (%" PRIu64 ") in inode %" PRIu64 ",\n"), fname, ino, parent, lino); next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino, &max_size, &i, &bytes_deleted, ino_dirty); continue; } } /* validate ftype field if supported */ if (xfs_sb_version_hasftype(&mp->m_sb)) { __uint8_t dir_ftype; __uint8_t ino_ftype; dir_ftype = M_DIROPS(mp)->sf_get_ftype(sfep); ino_ftype = get_inode_ftype(irec, ino_offset); if (dir_ftype != ino_ftype) { if (no_modify) { do_warn( _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"), dir_ftype, ino_ftype, ino, lino); } else { do_warn( _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"), dir_ftype, ino_ftype, ino, lino); M_DIROPS(mp)->sf_put_ftype(sfep, ino_ftype); dir_hash_update_ftype(hashtab, (xfs_dir2_dataptr_t)(sfep - xfs_dir2_sf_firstentry(sfp)), ino_ftype); *ino_dirty = 1; } } } if (lino > XFS_DIR2_MAX_SHORT_INUM) i8++; /* * go onto next entry - we have to take entries with bad namelen * into account in no modify mode since we calculate size based * on next_sfep. */ ASSERT(no_modify || bad_sfnamelen == 0); next_sfep = (struct xfs_dir2_sf_entry *)((intptr_t)sfep + (bad_sfnamelen ? M_DIROPS(mp)->sf_entsize(sfp, namelen) : M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen))); } if (sfp->i8count != i8) { if (no_modify) { do_warn(_("would fix i8count in inode %" PRIu64 "\n"), ino); } else { if (i8 == 0) { struct xfs_dir2_sf_entry *tmp_sfep; tmp_sfep = next_sfep; process_sf_dir2_fixi8(mp, sfp, &tmp_sfep); bytes_deleted += (intptr_t)next_sfep - (intptr_t)tmp_sfep; next_sfep = tmp_sfep; } else sfp->i8count = i8; *ino_dirty = 1; do_warn(_("fixing i8count in inode %" PRIu64 "\n"), ino); } } /* * sync up sizes if required */ if (*ino_dirty && bytes_deleted > 0) { ASSERT(!no_modify); libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK); ip->i_d.di_size -= bytes_deleted; } if (ip->i_d.di_size != ip->i_df.if_bytes) { ASSERT(ip->i_df.if_bytes == (xfs_fsize_t) ((intptr_t) next_sfep - (intptr_t) sfp)); ip->i_d.di_size = (xfs_fsize_t) ((intptr_t) next_sfep - (intptr_t) sfp); do_warn( _("setting size to %" PRId64 " bytes to reflect junked entries\n"), ip->i_d.di_size); *ino_dirty = 1; } } /* * processes all reachable inodes in directories */ static void process_dir_inode( xfs_mount_t *mp, xfs_agnumber_t agno, ino_tree_node_t *irec, int ino_offset) { xfs_ino_t ino; struct xfs_defer_ops dfops; xfs_fsblock_t first; xfs_inode_t *ip; xfs_trans_t *tp; dir_hash_tab_t *hashtab; int need_dot; int dirty, num_illegal, error, nres; ino = XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum + ino_offset); /* * open up directory inode, check all entries, * then call prune_dir_entries to remove all * remaining illegal directory entries. */ ASSERT(!is_inode_refchecked(irec, ino_offset) || dotdot_update); error = -libxfs_iget(mp, NULL, ino, 0, &ip); if (error) { if (!no_modify) do_error( _("couldn't map inode %" PRIu64 ", err = %d\n"), ino, error); else { do_warn( _("couldn't map inode %" PRIu64 ", err = %d\n"), ino, error); /* * see below for what we're doing if this * is root. Why do we need to do this here? * to ensure that the root doesn't show up * as being disconnected in the no_modify case. */ if (mp->m_sb.sb_rootino == ino) { add_inode_reached(irec, 0); add_inode_ref(irec, 0); } } add_inode_refchecked(irec, 0); return; } need_dot = dirty = num_illegal = 0; if (mp->m_sb.sb_rootino == ino) { /* * mark root inode reached and bump up * link count for root inode to account * for '..' entry since the root inode is * never reached by a parent. we know * that root's '..' is always good -- * guaranteed by phase 3 and/or below. */ add_inode_reached(irec, ino_offset); } add_inode_refchecked(irec, ino_offset); hashtab = dir_hash_init(ip->i_d.di_size); /* * look for bogus entries */ switch (ip->i_d.di_format) { case XFS_DINODE_FMT_EXTENTS: case XFS_DINODE_FMT_BTREE: /* * also check for missing '.' in longform dirs. * missing .. entries are added if required when * the directory is connected to lost+found. but * we need to create '.' entries here. */ longform_dir2_entry_check(mp, ino, ip, &num_illegal, &need_dot, irec, ino_offset, hashtab); break; case XFS_DINODE_FMT_LOCAL: /* * using the remove reservation is overkill * since at most we'll only need to log the * inode but it's easier than wedging a * new define in ourselves. */ nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); shortform_dir2_entry_check(mp, ino, ip, &dirty, irec, ino_offset, hashtab); ASSERT(dirty == 0 || (dirty && !no_modify)); if (dirty) { libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE | XFS_ILOG_DDATA); libxfs_trans_commit(tp); } else { libxfs_trans_cancel(tp); } break; default: break; } dir_hash_done(hashtab); /* * if we have to create a .. for /, do it now *before* * we delete the bogus entries, otherwise the directory * could transform into a shortform dir which would * probably cause the simulation to choke. Even * if the illegal entries get shifted around, it's ok * because the entries are structurally intact and in * in hash-value order so the simulation won't get confused * if it has to move them around. */ if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) { ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_LOCAL); do_warn(_("recreating root directory .. entry\n")); nres = XFS_MKDIR_SPACE_RES(mp, 2); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); libxfs_defer_init(&dfops, &first); error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot, ip->i_ino, &first, &dfops, nres); if (error) do_error( _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error); libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); error = -libxfs_defer_finish(&tp, &dfops, ip); ASSERT(error == 0); libxfs_trans_commit(tp); need_root_dotdot = 0; } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) { do_warn(_("would recreate root directory .. entry\n")); } /* * if we need to create the '.' entry, do so only if * the directory is a longform dir. if it's been * turned into a shortform dir, then the inode is ok * since shortform dirs have no '.' entry and the inode * has already been committed by prune_lf_dir_entry(). */ if (need_dot) { /* * bump up our link count but don't * bump up the inode link count. chances * are good that even though we lost '.' * the inode link counts reflect '.' so * leave the inode link count alone and if * it turns out to be wrong, we'll catch * that in phase 7. */ add_inode_ref(irec, ino_offset); if (no_modify) { do_warn( _("would create missing \".\" entry in dir ino %" PRIu64 "\n"), ino); } else if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) { /* * need to create . entry in longform dir. */ do_warn( _("creating missing \".\" entry in dir ino %" PRIu64 "\n"), ino); nres = XFS_MKDIR_SPACE_RES(mp, 1); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); libxfs_defer_init(&dfops, &first); error = -libxfs_dir_createname(tp, ip, &xfs_name_dot, ip->i_ino, &first, &dfops, nres); if (error) do_error( _("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"), ino, error); libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); error = -libxfs_defer_finish(&tp, &dfops, ip); ASSERT(error == 0); libxfs_trans_commit(tp); } } IRELE(ip); } /* * mark realtime bitmap and summary inodes as reached. * quota inode will be marked here as well */ static void mark_standalone_inodes(xfs_mount_t *mp) { ino_tree_node_t *irec; int offset; irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rbmino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino)); ASSERT(irec != NULL); offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino) - irec->ino_startnum; add_inode_reached(irec, offset); irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rsumino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino)); offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino) - irec->ino_startnum; ASSERT(irec != NULL); add_inode_reached(irec, offset); if (fs_quotas) { if (mp->m_sb.sb_uquotino && mp->m_sb.sb_uquotino != NULLFSINO) { irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_uquotino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)); offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino) - irec->ino_startnum; add_inode_reached(irec, offset); } if (mp->m_sb.sb_gquotino && mp->m_sb.sb_gquotino != NULLFSINO) { irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_gquotino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)); offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino) - irec->ino_startnum; add_inode_reached(irec, offset); } if (mp->m_sb.sb_pquotino && mp->m_sb.sb_pquotino != NULLFSINO) { irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_pquotino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino)); offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino) - irec->ino_startnum; add_inode_reached(irec, offset); } } } static void check_for_orphaned_inodes( xfs_mount_t *mp, xfs_agnumber_t agno, ino_tree_node_t *irec) { int i; xfs_ino_t ino; for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { ASSERT(is_inode_confirmed(irec, i)); if (is_inode_free(irec, i)) continue; if (is_inode_reached(irec, i)) continue; ASSERT(inode_isadir(irec, i) || num_inode_references(irec, i) == 0); ino = XFS_AGINO_TO_INO(mp, agno, i + irec->ino_startnum); if (inode_isadir(irec, i)) do_warn(_("disconnected dir inode %" PRIu64 ", "), ino); else do_warn(_("disconnected inode %" PRIu64 ", "), ino); if (!no_modify) { if (!orphanage_ino) orphanage_ino = mk_orphanage(mp); do_warn(_("moving to %s\n"), ORPHANAGE); mv_orphanage(mp, ino, inode_isadir(irec, i)); } else { do_warn(_("would move to %s\n"), ORPHANAGE); } /* * for read-only case, even though the inode isn't * really reachable, set the flag (and bump our link * count) anyway to fool phase 7 */ add_inode_reached(irec, i); } } static void traverse_function( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { ino_tree_node_t *irec; int i; prefetch_args_t *pf_args = arg; wait_for_inode_prefetch(pf_args); if (verbose) do_log(_(" - agno = %d\n"), agno); for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) { if (irec->ino_isa_dir == 0) continue; if (pf_args) { sem_post(&pf_args->ra_count); #ifdef XR_PF_TRACE sem_getvalue(&pf_args->ra_count, &i); pftrace( "processing inode chunk %p in AG %d (sem count = %d)", irec, agno, i); #endif } for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { if (inode_isadir(irec, i)) process_dir_inode(wq->mp, agno, irec, i); } } cleanup_inode_prefetch(pf_args); } static void update_missing_dotdot_entries( xfs_mount_t *mp) { dotdot_update_t *dir; /* * these entries parents were updated, rebuild them again * set dotdot_update flag so processing routines do not count links */ dotdot_update = 1; while (!list_empty(&dotdot_update_list)) { dir = list_entry(dotdot_update_list.prev, struct dotdot_update, list); list_del(&dir->list); process_dir_inode(mp, dir->agno, dir->irec, dir->ino_offset); free(dir); } } static void traverse_ags( struct xfs_mount *mp) { do_inode_prefetch(mp, 0, traverse_function, false, true); } void phase6(xfs_mount_t *mp) { ino_tree_node_t *irec; int i; memset(&zerocr, 0, sizeof(struct cred)); memset(&zerofsx, 0, sizeof(struct fsxattr)); orphanage_ino = 0; do_log(_("Phase 6 - check inode connectivity...\n")); incore_ext_teardown(mp); add_ino_ex_data(mp); /* * verify existence of root directory - if we have to * make one, it's ok for the incore data structs not to * know about it since everything about it (and the other * inodes in its chunk if a new chunk was created) are ok */ if (need_root_inode) { if (!no_modify) { do_warn(_("reinitializing root directory\n")); mk_root_dir(mp); need_root_inode = 0; need_root_dotdot = 0; } else { do_warn(_("would reinitialize root directory\n")); } } if (need_rbmino) { if (!no_modify) { do_warn(_("reinitializing realtime bitmap inode\n")); mk_rbmino(mp); need_rbmino = 0; } else { do_warn(_("would reinitialize realtime bitmap inode\n")); } } if (need_rsumino) { if (!no_modify) { do_warn(_("reinitializing realtime summary inode\n")); mk_rsumino(mp); need_rsumino = 0; } else { do_warn(_("would reinitialize realtime summary inode\n")); } } if (!no_modify) { do_log( _(" - resetting contents of realtime bitmap and summary inodes\n")); if (fill_rbmino(mp)) { do_warn( _("Warning: realtime bitmap may be inconsistent\n")); } if (fill_rsumino(mp)) { do_warn( _("Warning: realtime bitmap may be inconsistent\n")); } } mark_standalone_inodes(mp); do_log(_(" - traversing filesystem ...\n")); irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)); /* * we always have a root inode, even if it's free... * if the root is free, forget it, lost+found is already gone */ if (is_inode_free(irec, 0) || !inode_isadir(irec, 0)) { need_root_inode = 1; } /* * then process all inodes by walking incore inode tree */ traverse_ags(mp); /* * any directories that had updated ".." entries, rebuild them now */ update_missing_dotdot_entries(mp); do_log(_(" - traversal finished ...\n")); do_log(_(" - moving disconnected inodes to %s ...\n"), ORPHANAGE); /* * move all disconnected inodes to the orphanage */ for (i = 0; i < glob_agcount; i++) { irec = findfirst_inode_rec(i); while (irec != NULL) { check_for_orphaned_inodes(mp, i, irec); irec = next_ino_rec(irec); } } } xfsprogs-4.9.0+nmu1ubuntu2/repair/phase7.c0000644000000000000000000000701013063067173015307 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "versions.h" #include "progress.h" #include "threads.h" static void update_inode_nlinks( xfs_mount_t *mp, xfs_ino_t ino, __uint32_t nlinks) { xfs_trans_t *tp; xfs_inode_t *ip; int error; int dirty; int nres; nres = no_modify ? 0 : 10; error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); ASSERT(error == 0); error = -libxfs_trans_iget(mp, tp, ino, 0, 0, &ip); if (error) { if (!no_modify) do_error( _("couldn't map inode %" PRIu64 ", err = %d\n"), ino, error); else { do_warn( _("couldn't map inode %" PRIu64 ", err = %d, can't compare link counts\n"), ino, error); return; } } dirty = 0; /* compare and set links if they differ. */ if (VFS_I(ip)->i_nlink != nlinks) { if (!no_modify) { do_warn( _("resetting inode %" PRIu64 " nlinks from %u to %u\n"), ino, VFS_I(ip)->i_nlink, nlinks); set_nlink(VFS_I(ip), nlinks); dirty = 1; } else { do_warn( _("would have reset inode %" PRIu64 " nlinks from %u to %u\n"), ino, VFS_I(ip)->i_nlink, nlinks); } } if (!dirty) { libxfs_trans_cancel(tp); } else { libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); /* * no need to do a bmap finish since * we're not allocating anything */ ASSERT(error == 0); error = -libxfs_trans_commit(tp); ASSERT(error == 0); } IRELE(ip); } /* * for each ag, look at each inode 1 at a time. If the number of * links is bad, reset it, log the inode core, commit the transaction */ static void do_link_updates( struct work_queue *wq, xfs_agnumber_t agno, void *arg) { ino_tree_node_t *irec; int j; __uint32_t nrefs; for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) { for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { ASSERT(is_inode_confirmed(irec, j)); if (is_inode_free(irec, j)) continue; ASSERT(no_modify || is_inode_reached(irec, j)); nrefs = num_inode_references(irec, j); ASSERT(no_modify || nrefs > 0); if (get_inode_disk_nlinks(irec, j) != nrefs) update_inode_nlinks(wq->mp, XFS_AGINO_TO_INO(wq->mp, agno, irec->ino_startnum + j), nrefs); } } PROG_RPT_INC(prog_rpt_done[agno], 1); } void phase7( struct xfs_mount *mp, int scan_threads) { struct work_queue wq; int agno; if (!no_modify) do_log(_("Phase 7 - verify and correct link counts...\n")); else do_log(_("Phase 7 - verify link counts...\n")); set_progress_msg(PROGRESS_FMT_CORR_LINK, (__uint64_t) glob_agcount); create_work_queue(&wq, mp, scan_threads); for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) queue_work(&wq, do_link_updates, agno, NULL); destroy_work_queue(&wq); print_final_rpt(); } xfsprogs-4.9.0+nmu1ubuntu2/repair/prefetch.c0000644000000000000000000006624613063067172015737 0ustar #include "libxfs.h" #include #include "avl.h" #include "btree.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "dir2.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "bmap.h" #include "versions.h" #include "threads.h" #include "prefetch.h" #include "progress.h" int do_prefetch = 1; /* * Performs prefetching by priming the libxfs cache by using a dedicate thread * scanning inodes and reading blocks in ahead of time they are required. * * Any I/O errors can be safely ignored. */ static xfs_mount_t *mp; static int mp_fd; static int pf_max_bytes; static int pf_max_bbs; static int pf_max_fsbs; static int pf_batch_bytes; static int pf_batch_fsbs; static void pf_read_inode_dirs(prefetch_args_t *, xfs_buf_t *); /* * Buffer priorities for the libxfs cache * * Directory metadata is ranked higher than other metadata as it's used * in phases 3, 4 and 6, while other metadata is only used in 3 & 4. */ /* intermediate directory btree nodes - can't be queued */ #define B_DIR_BMAP CACHE_PREFETCH_PRIORITY + 7 /* directory metadata in secondary queue */ #define B_DIR_META_2 CACHE_PREFETCH_PRIORITY + 6 /* dir metadata that had to fetched from the primary queue to avoid stalling */ #define B_DIR_META_H CACHE_PREFETCH_PRIORITY + 5 /* single block of directory metadata (can't batch read) */ #define B_DIR_META_S CACHE_PREFETCH_PRIORITY + 4 /* dir metadata with more than one block fetched in a single I/O */ #define B_DIR_META CACHE_PREFETCH_PRIORITY + 3 /* inode clusters with directory inodes */ #define B_DIR_INODE CACHE_PREFETCH_PRIORITY + 2 /* intermediate extent btree nodes */ #define B_BMAP CACHE_PREFETCH_PRIORITY + 1 /* inode clusters without any directory entries */ #define B_INODE CACHE_PREFETCH_PRIORITY /* * Test if bit 0 or 2 is set in the "priority tag" of the buffer to see if * the buffer is for an inode or other metadata. */ #define B_IS_INODE(f) (((f) & 5) == 0) #define DEF_BATCH_BYTES 0x10000 #define MAX_BUFS 128 #define IO_THRESHOLD (MAX_BUFS * 2) typedef enum pf_which { PF_PRIMARY, PF_SECONDARY, PF_META_ONLY } pf_which_t; static inline void pf_start_processing( prefetch_args_t *args) { if (!args->can_start_processing) { pftrace("signalling processing for AG %d", args->agno); args->can_start_processing = 1; pthread_cond_signal(&args->start_processing); } } static inline void pf_start_io_workers( prefetch_args_t *args) { if (!args->can_start_reading) { pftrace("signalling reading for AG %d", args->agno); args->can_start_reading = 1; pthread_cond_broadcast(&args->start_reading); } } static void pf_queue_io( prefetch_args_t *args, struct xfs_buf_map *map, int nmaps, int flag) { struct xfs_buf *bp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, map[0].bm_bn); /* * Never block on a buffer lock here, given that the actual repair * code might lock buffers in a different order from us. Given that * the lock holder is either reading it from disk himself or * completely overwriting it this behaviour is perfectly fine. */ bp = libxfs_getbuf_map(mp->m_dev, map, nmaps, LIBXFS_GETBUF_TRYLOCK); if (!bp) return; if (bp->b_flags & LIBXFS_B_UPTODATE) { if (B_IS_INODE(flag)) pf_read_inode_dirs(args, bp); XFS_BUF_SET_PRIORITY(bp, XFS_BUF_PRIORITY(bp) + CACHE_PREFETCH_PRIORITY); libxfs_putbuf(bp); return; } XFS_BUF_SET_PRIORITY(bp, flag); pthread_mutex_lock(&args->lock); btree_insert(args->io_queue, fsbno, bp); if (fsbno > args->last_bno_read) { if (B_IS_INODE(flag)) { args->inode_bufs_queued++; if (args->inode_bufs_queued == IO_THRESHOLD) pf_start_io_workers(args); } } else { ASSERT(!B_IS_INODE(flag)); XFS_BUF_SET_PRIORITY(bp, B_DIR_META_2); } pftrace("getbuf %c %p (%llu) in AG %d (fsbno = %lu) added to queue" "(inode_bufs_queued = %d, last_bno = %lu)", B_IS_INODE(flag) ? 'I' : 'M', bp, (long long)XFS_BUF_ADDR(bp), args->agno, fsbno, args->inode_bufs_queued, args->last_bno_read); pf_start_processing(args); pthread_mutex_unlock(&args->lock); } static int pf_read_bmbt_reclist( prefetch_args_t *args, xfs_bmbt_rec_t *rp, int numrecs) { int i; xfs_bmbt_irec_t irec; xfs_filblks_t cp = 0; /* prev count */ xfs_fileoff_t op = 0; /* prev offset */ #define MAP_ARRAY_SZ 4 struct xfs_buf_map map_array[MAP_ARRAY_SZ]; struct xfs_buf_map *map = map_array; int max_extents = MAP_ARRAY_SZ; int nmaps = 0; unsigned int len = 0; int ret = 0; for (i = 0; i < numrecs; i++) { libxfs_bmbt_disk_get_all(rp + i, &irec); if (((i > 0) && (op + cp > irec.br_startoff)) || (irec.br_blockcount == 0) || (irec.br_startoff >= fs_max_file_offset)) goto out_free; if (!verify_dfsbno(mp, irec.br_startblock) || !verify_dfsbno(mp, irec.br_startblock + irec.br_blockcount - 1)) goto out_free; if (!args->dirs_only && ((irec.br_startoff + irec.br_blockcount) >= mp->m_dir_geo->freeblk)) break; /* only Phase 6 reads the free blocks */ op = irec.br_startoff; cp = irec.br_blockcount; while (irec.br_blockcount) { unsigned int bm_len; pftrace("queuing dir extent in AG %d", args->agno); if (len + irec.br_blockcount >= mp->m_dir_geo->fsbcount) bm_len = mp->m_dir_geo->fsbcount - len; else bm_len = irec.br_blockcount; len += bm_len; map[nmaps].bm_bn = XFS_FSB_TO_DADDR(mp, irec.br_startblock); map[nmaps].bm_len = XFS_FSB_TO_BB(mp, bm_len); nmaps++; if (len == mp->m_dir_geo->fsbcount) { pf_queue_io(args, map, nmaps, B_DIR_META); len = 0; nmaps = 0; } irec.br_blockcount -= bm_len; irec.br_startblock += bm_len; /* * Handle very fragmented dir2 blocks with dynamically * allocated buffer maps. */ if (nmaps >= max_extents) { struct xfs_buf_map *old_map = NULL; if (map == map_array) { old_map = map; map = NULL; } max_extents *= 2; map = realloc(map, max_extents * sizeof(*map)); if (map == NULL) { do_error( _("couldn't malloc dir2 buffer list\n")); exit(1); } if (old_map) memcpy(map, old_map, sizeof(map_array)); } } } ret = 1; out_free: if (map != map_array) free(map); return ret; } /* * simplified version of the main scan_lbtree. Returns 0 to stop. */ static int pf_scan_lbtree( xfs_fsblock_t dbno, int level, int isadir, prefetch_args_t *args, int (*func)(struct xfs_btree_block *block, int level, int isadir, prefetch_args_t *args)) { xfs_buf_t *bp; int rc; bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, dbno), XFS_FSB_TO_BB(mp, 1), 0, &xfs_bmbt_buf_ops); if (!bp) return 0; XFS_BUF_SET_PRIORITY(bp, isadir ? B_DIR_BMAP : B_BMAP); /* * If the verifier flagged a problem with the buffer, we can't trust * its contents for the purposes of reading ahead. Stop prefetching * the tree and mark the buffer unchecked so that the next read of the * buffer will retain the error status and be acted upon appropriately. */ if (bp->b_error) { bp->b_flags |= LIBXFS_B_UNCHECKED; libxfs_putbuf(bp); return 0; } rc = (*func)(XFS_BUF_TO_BLOCK(bp), level - 1, isadir, args); libxfs_putbuf(bp); return rc; } static int pf_scanfunc_bmap( struct xfs_btree_block *block, int level, int isadir, prefetch_args_t *args) { xfs_bmbt_ptr_t *pp; int numrecs; int i; xfs_fsblock_t dbno; /* * do some validation on the block contents */ if ((block->bb_magic != cpu_to_be32(XFS_BMAP_MAGIC) && block->bb_magic != cpu_to_be32(XFS_BMAP_CRC_MAGIC)) || (be16_to_cpu(block->bb_level) != level)) return 0; numrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (numrecs > mp->m_bmap_dmxr[0] || !isadir) return 0; return pf_read_bmbt_reclist(args, XFS_BMBT_REC_ADDR(mp, block, 1), numrecs); } if (numrecs > mp->m_bmap_dmxr[1]) return 0; pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); for (i = 0; i < numrecs; i++) { dbno = get_unaligned_be64(&pp[i]); if (!verify_dfsbno(mp, dbno)) return 0; if (!pf_scan_lbtree(dbno, level, isadir, args, pf_scanfunc_bmap)) return 0; } return 1; } static void pf_read_btinode( prefetch_args_t *args, xfs_dinode_t *dino, int isadir) { xfs_bmdr_block_t *dib; xfs_bmbt_ptr_t *pp; int i; int level; int numrecs; int dsize; xfs_fsblock_t dbno; dib = (xfs_bmdr_block_t *)XFS_DFORK_DPTR(dino); level = be16_to_cpu(dib->bb_level); numrecs = be16_to_cpu(dib->bb_numrecs); if ((numrecs == 0) || (level == 0) || (level > XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))) return; /* * use bmdr/dfork_dsize since the root block is in the data fork */ if (XFS_BMDR_SPACE_CALC(numrecs) > XFS_DFORK_DSIZE(dino, mp)) return; dsize = XFS_DFORK_DSIZE(dino, mp); pp = XFS_BMDR_PTR_ADDR(dib, 1, libxfs_bmdr_maxrecs(dsize, 0)); for (i = 0; i < numrecs; i++) { dbno = get_unaligned_be64(&pp[i]); if (!verify_dfsbno(mp, dbno)) break; if (!pf_scan_lbtree(dbno, level, isadir, args, pf_scanfunc_bmap)) break; } } static void pf_read_exinode( prefetch_args_t *args, xfs_dinode_t *dino) { pf_read_bmbt_reclist(args, (xfs_bmbt_rec_t *)XFS_DFORK_DPTR(dino), be32_to_cpu(dino->di_nextents)); } static void pf_read_inode_dirs( prefetch_args_t *args, xfs_buf_t *bp) { xfs_dinode_t *dino; int icnt = 0; int hasdir = 0; int isadir; libxfs_readbuf_verify(bp, &xfs_inode_buf_ops); if (bp->b_error) return; for (icnt = 0; icnt < (XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog); icnt++) { dino = xfs_make_iptr(mp, bp, icnt); /* * We are only prefetching directory contents in extents * and btree nodes for other inodes */ isadir = (be16_to_cpu(dino->di_mode) & S_IFMT) == S_IFDIR; hasdir |= isadir; if (dino->di_format <= XFS_DINODE_FMT_LOCAL) continue; if (!isadir && (dino->di_format == XFS_DINODE_FMT_EXTENTS || args->dirs_only)) continue; /* * do some checks on the inode to see if we can prefetch * its directory data. It's a cut down version of * process_dinode_int() in dinode.c. */ if (dino->di_format > XFS_DINODE_FMT_BTREE) continue; if (be16_to_cpu(dino->di_magic) != XFS_DINODE_MAGIC) continue; if (!libxfs_dinode_good_version(mp, dino->di_version)) continue; if (be64_to_cpu(dino->di_size) <= XFS_DFORK_DSIZE(dino, mp)) continue; if ((dino->di_forkoff != 0) && (dino->di_forkoff >= XFS_LITINO(mp, dino->di_version) >> 3)) continue; switch (dino->di_format) { case XFS_DINODE_FMT_EXTENTS: pf_read_exinode(args, dino); break; case XFS_DINODE_FMT_BTREE: pf_read_btinode(args, dino, isadir); break; } } if (hasdir) XFS_BUF_SET_PRIORITY(bp, B_DIR_INODE); } /* * pf_batch_read must be called with the lock locked. */ static void pf_batch_read( prefetch_args_t *args, pf_which_t which, void *buf) { xfs_buf_t *bplist[MAX_BUFS]; unsigned int num; off64_t first_off, last_off, next_off; int len, size; int i; int inode_bufs; unsigned long fsbno = 0; unsigned long max_fsbno; char *pbuf; for (;;) { num = 0; if (which == PF_SECONDARY) { bplist[0] = btree_find(args->io_queue, 0, &fsbno); max_fsbno = MIN(fsbno + pf_max_fsbs, args->last_bno_read); } else { bplist[0] = btree_find(args->io_queue, args->last_bno_read, &fsbno); max_fsbno = fsbno + pf_max_fsbs; } while (bplist[num] && num < MAX_BUFS && fsbno < max_fsbno) { /* * Discontiguous buffers need special handling, so stop * gathering new buffers and process the list and this * discontigous buffer immediately. This avoids the * complexity of keeping a separate discontigous buffer * list and seeking back over ranges we've already done * optimised reads for. */ if ((bplist[num]->b_flags & LIBXFS_B_DISCONTIG)) { num++; break; } if (which != PF_META_ONLY || !B_IS_INODE(XFS_BUF_PRIORITY(bplist[num]))) num++; if (num == MAX_BUFS) break; bplist[num] = btree_lookup_next(args->io_queue, &fsbno); } if (!num) return; /* * do a big read if 25% of the potential buffer is useful, * otherwise, find as many close together blocks and * read them in one read */ first_off = LIBXFS_BBTOOFF64(XFS_BUF_ADDR(bplist[0])); last_off = LIBXFS_BBTOOFF64(XFS_BUF_ADDR(bplist[num-1])) + XFS_BUF_SIZE(bplist[num-1]); while (num > 1 && last_off - first_off > pf_max_bytes) { num--; last_off = LIBXFS_BBTOOFF64(XFS_BUF_ADDR(bplist[num-1])) + XFS_BUF_SIZE(bplist[num-1]); } if (num < ((last_off - first_off) >> (mp->m_sb.sb_blocklog + 3))) { /* * not enough blocks for one big read, so determine * the number of blocks that are close enough. */ last_off = first_off + XFS_BUF_SIZE(bplist[0]); for (i = 1; i < num; i++) { next_off = LIBXFS_BBTOOFF64(XFS_BUF_ADDR(bplist[i])) + XFS_BUF_SIZE(bplist[i]); if (next_off - last_off > pf_batch_bytes) break; last_off = next_off; } num = i; } for (i = 0; i < num; i++) { if (btree_delete(args->io_queue, XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bplist[i]))) == NULL) do_error(_("prefetch corruption\n")); } if (which == PF_PRIMARY) { for (inode_bufs = 0, i = 0; i < num; i++) { if (B_IS_INODE(XFS_BUF_PRIORITY(bplist[i]))) inode_bufs++; } args->inode_bufs_queued -= inode_bufs; if (inode_bufs && (first_off >> mp->m_sb.sb_blocklog) > pf_batch_fsbs) args->last_bno_read = (first_off >> mp->m_sb.sb_blocklog); } #ifdef XR_PF_TRACE pftrace("reading bbs %llu to %llu (%d bufs) from %s queue in AG %d (last_bno = %lu, inode_bufs = %d)", (long long)XFS_BUF_ADDR(bplist[0]), (long long)XFS_BUF_ADDR(bplist[num-1]), num, (which != PF_SECONDARY) ? "pri" : "sec", args->agno, args->last_bno_read, args->inode_bufs_queued); #endif pthread_mutex_unlock(&args->lock); /* * now read the data and put into the xfs_but_t's */ len = pread(mp_fd, buf, (int)(last_off - first_off), first_off); /* * Check the last buffer on the list to see if we need to * process a discontiguous buffer. The gather above loop * guarantees that only the last buffer in the list will be a * discontiguous buffer. */ if ((bplist[num - 1]->b_flags & LIBXFS_B_DISCONTIG)) { libxfs_readbufr_map(mp->m_ddev_targp, bplist[num - 1], 0); bplist[num - 1]->b_flags |= LIBXFS_B_UNCHECKED; libxfs_putbuf(bplist[num - 1]); num--; } if (len > 0) { /* * go through the xfs_buf_t list copying from the * read buffer into the xfs_buf_t's and release them. */ for (i = 0; i < num; i++) { pbuf = ((char *)buf) + (LIBXFS_BBTOOFF64(XFS_BUF_ADDR(bplist[i])) - first_off); size = XFS_BUF_SIZE(bplist[i]); if (len < size) break; memcpy(XFS_BUF_PTR(bplist[i]), pbuf, size); bplist[i]->b_flags |= (LIBXFS_B_UPTODATE | LIBXFS_B_UNCHECKED); len -= size; if (B_IS_INODE(XFS_BUF_PRIORITY(bplist[i]))) pf_read_inode_dirs(args, bplist[i]); else if (which == PF_META_ONLY) XFS_BUF_SET_PRIORITY(bplist[i], B_DIR_META_H); else if (which == PF_PRIMARY && num == 1) XFS_BUF_SET_PRIORITY(bplist[i], B_DIR_META_S); } } for (i = 0; i < num; i++) { pftrace("putbuf %c %p (%llu) in AG %d", B_IS_INODE(XFS_BUF_PRIORITY(bplist[i])) ? 'I' : 'M', bplist[i], (long long)XFS_BUF_ADDR(bplist[i]), args->agno); libxfs_putbuf(bplist[i]); } pthread_mutex_lock(&args->lock); if (which != PF_SECONDARY) { pftrace("inode_bufs_queued for AG %d = %d", args->agno, args->inode_bufs_queued); /* * if primary inode queue running low, process metadata * in boths queues to avoid I/O starvation as the * processing thread would be waiting for a metadata * buffer */ if (which == PF_PRIMARY && !args->queuing_done && args->inode_bufs_queued < IO_THRESHOLD) { pftrace("reading metadata bufs from primary queue for AG %d", args->agno); pf_batch_read(args, PF_META_ONLY, buf); pftrace("reading bufs from secondary queue for AG %d", args->agno); pf_batch_read(args, PF_SECONDARY, buf); } } } } static void * pf_io_worker( void *param) { prefetch_args_t *args = param; void *buf = memalign(libxfs_device_alignment(), pf_max_bytes); if (buf == NULL) return NULL; pthread_mutex_lock(&args->lock); while (!args->queuing_done || !btree_is_empty(args->io_queue)) { pftrace("waiting to start prefetch I/O for AG %d", args->agno); while (!args->can_start_reading && !args->queuing_done) pthread_cond_wait(&args->start_reading, &args->lock); pftrace("starting prefetch I/O for AG %d", args->agno); pf_batch_read(args, PF_PRIMARY, buf); pf_batch_read(args, PF_SECONDARY, buf); pftrace("ran out of bufs to prefetch for AG %d", args->agno); if (!args->queuing_done) args->can_start_reading = 0; } pthread_mutex_unlock(&args->lock); free(buf); pftrace("finished prefetch I/O for AG %d", args->agno); return NULL; } static int pf_create_prefetch_thread( prefetch_args_t *args); static void * pf_queuing_worker( void *param) { prefetch_args_t *args = param; int num_inos; ino_tree_node_t *irec; ino_tree_node_t *cur_irec; int blks_per_cluster; xfs_agblock_t bno; int i; int err; uint64_t sparse; blks_per_cluster = mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog; if (blks_per_cluster == 0) blks_per_cluster = 1; for (i = 0; i < PF_THREAD_COUNT; i++) { err = pthread_create(&args->io_threads[i], NULL, pf_io_worker, args); if (err != 0) { do_warn(_("failed to create prefetch thread: %s\n"), strerror(err)); if (i == 0) { pf_start_processing(args); return NULL; } /* * since we have at least one I/O thread, use them for * prefetch */ break; } } pftrace("starting prefetch for AG %d", args->agno); for (irec = findfirst_inode_rec(args->agno); irec != NULL; irec = next_ino_rec(irec)) { cur_irec = irec; num_inos = XFS_INODES_PER_CHUNK; while (num_inos < mp->m_ialloc_inos && irec != NULL) { irec = next_ino_rec(irec); num_inos += XFS_INODES_PER_CHUNK; } if (args->dirs_only && cur_irec->ino_isa_dir == 0) continue; #ifdef XR_PF_TRACE sem_getvalue(&args->ra_count, &i); pftrace("queuing irec %p in AG %d, sem count = %d", irec, args->agno, i); #endif err = sem_trywait(&args->ra_count); if (err < 0 && errno == EAGAIN) { /* * Kick the queue once we have reached the limit; * without this the threads processing the inodes * might get stuck on a buffer that has been locked * and added to the I/O queue but is waiting for * the thread to be woken. */ pf_start_io_workers(args); sem_wait(&args->ra_count); } num_inos = 0; bno = XFS_AGINO_TO_AGBNO(mp, cur_irec->ino_startnum); sparse = cur_irec->ir_sparse; do { struct xfs_buf_map map; map.bm_bn = XFS_AGB_TO_DADDR(mp, args->agno, bno); map.bm_len = XFS_FSB_TO_BB(mp, blks_per_cluster); /* * Queue I/O for each non-sparse cluster. We can check * sparse state in cluster sized chunks as cluster size * is the min. granularity of sparse irec regions. */ if ((sparse & ((1ULL << inodes_per_cluster) - 1)) == 0) pf_queue_io(args, &map, 1, (cur_irec->ino_isa_dir != 0) ? B_DIR_INODE : B_INODE); bno += blks_per_cluster; num_inos += inodes_per_cluster; sparse >>= inodes_per_cluster; } while (num_inos < mp->m_ialloc_inos); } pthread_mutex_lock(&args->lock); pftrace("finished queuing inodes for AG %d (inode_bufs_queued = %d)", args->agno, args->inode_bufs_queued); args->queuing_done = 1; pf_start_io_workers(args); pf_start_processing(args); pthread_mutex_unlock(&args->lock); /* now wait for the readers to finish */ for (i = 0; i < PF_THREAD_COUNT; i++) if (args->io_threads[i]) pthread_join(args->io_threads[i], NULL); pftrace("prefetch for AG %d finished", args->agno); pthread_mutex_lock(&args->lock); ASSERT(btree_is_empty(args->io_queue)); args->prefetch_done = 1; if (args->next_args) pf_create_prefetch_thread(args->next_args); pthread_mutex_unlock(&args->lock); return NULL; } static int pf_create_prefetch_thread( prefetch_args_t *args) { int err; pftrace("creating queue thread for AG %d", args->agno); err = pthread_create(&args->queuing_thread, NULL, pf_queuing_worker, args); if (err != 0) { do_warn(_("failed to create prefetch thread: %s\n"), strerror(err)); cleanup_inode_prefetch(args); } return err == 0; } void init_prefetch( xfs_mount_t *pmp) { mp = pmp; mp_fd = libxfs_device_to_fd(mp->m_ddev_targp->dev); pf_max_bytes = sysconf(_SC_PAGE_SIZE) << 7; pf_max_bbs = pf_max_bytes >> BBSHIFT; pf_max_fsbs = pf_max_bytes >> mp->m_sb.sb_blocklog; pf_batch_bytes = DEF_BATCH_BYTES; pf_batch_fsbs = DEF_BATCH_BYTES >> (mp->m_sb.sb_blocklog + 1); } prefetch_args_t * start_inode_prefetch( xfs_agnumber_t agno, int dirs_only, prefetch_args_t *prev_args) { prefetch_args_t *args; long max_queue; if (!do_prefetch || agno >= mp->m_sb.sb_agcount) return NULL; args = calloc(1, sizeof(prefetch_args_t)); btree_init(&args->io_queue); if (pthread_mutex_init(&args->lock, NULL) != 0) do_error(_("failed to initialize prefetch mutex\n")); if (pthread_cond_init(&args->start_reading, NULL) != 0) do_error(_("failed to initialize prefetch cond var\n")); if (pthread_cond_init(&args->start_processing, NULL) != 0) do_error(_("failed to initialize prefetch cond var\n")); args->agno = agno; args->dirs_only = dirs_only; /* * use only 1/8 of the libxfs cache as we are only counting inodes * and not any other associated metadata like directories */ max_queue = libxfs_bcache->c_maxcount / thread_count / 8; if (mp->m_inode_cluster_size > mp->m_sb.sb_blocksize) max_queue = max_queue * (mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog) / mp->m_ialloc_blks; sem_init(&args->ra_count, 0, max_queue); if (!prev_args) { if (!pf_create_prefetch_thread(args)) return NULL; } else { pthread_mutex_lock(&prev_args->lock); if (prev_args->prefetch_done) { if (!pf_create_prefetch_thread(args)) args = NULL; } else prev_args->next_args = args; pthread_mutex_unlock(&prev_args->lock); } return args; } /* * prefetch_ag_range runs a prefetch-and-process loop across a range of AGs. It * begins with @start+ag, and finishes with @end_ag - 1 (i.e. does not prefetch * or process @end_ag). The function starts prefetch on the first AG, then loops * starting prefetch on the next AG and then blocks processing the current AG as * the prefetch queue brings inodes into the processing queue. * * There is only one prefetch taking place at a time, so the prefetch on the * next AG only starts once the current AG has been completely prefetched. Hence * the prefetch of the next AG will start some time before the processing of the * current AG finishes, ensuring that when we iterate an start processing the * next AG there is already a significant queue of inodes to process. * * Prefetch is done this way to prevent it from running too far ahead of the * processing. Allowing it to do so can cause cache thrashing, where new * prefetch causes previously prefetched buffers to be reclaimed before the * processing thread uses them. This results in reading all the inodes and * metadata twice per phase and it greatly slows down the processing. Hence we * have to carefully control how far ahead we prefetch... */ static void prefetch_ag_range( struct work_queue *work, xfs_agnumber_t start_ag, xfs_agnumber_t end_ag, bool dirs_only, void (*func)(struct work_queue *, xfs_agnumber_t, void *)) { int i; struct prefetch_args *pf_args[2]; pf_args[start_ag & 1] = start_inode_prefetch(start_ag, dirs_only, NULL); for (i = start_ag; i < end_ag; i++) { /* Don't prefetch end_ag */ if (i + 1 < end_ag) pf_args[(~i) & 1] = start_inode_prefetch(i + 1, dirs_only, pf_args[i & 1]); func(work, i, pf_args[i & 1]); } } struct pf_work_args { xfs_agnumber_t start_ag; xfs_agnumber_t end_ag; bool dirs_only; void (*func)(struct work_queue *, xfs_agnumber_t, void *); }; static void prefetch_ag_range_work( struct work_queue *work, xfs_agnumber_t unused, void *args) { struct pf_work_args *wargs = args; prefetch_ag_range(work, wargs->start_ag, wargs->end_ag, wargs->dirs_only, wargs->func); free(args); } /* * Do inode prefetch in the most optimal way for the context under which repair * has been run. */ void do_inode_prefetch( struct xfs_mount *mp, int stride, void (*func)(struct work_queue *, xfs_agnumber_t, void *), bool check_cache, bool dirs_only) { int i; struct work_queue queue; struct work_queue *queues; int queues_started = 0; /* * If the previous phases of repair have not overflowed the buffer * cache, then we don't need to re-read any of the metadata in the * filesystem - it's all in the cache. In that case, run a thread per * CPU to maximise parallelism of the queue to be processed. */ if (check_cache && !libxfs_bcache_overflowed()) { queue.mp = mp; create_work_queue(&queue, mp, libxfs_nproc()); for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&queue, func, i, NULL); destroy_work_queue(&queue); return; } /* * single threaded behaviour - single prefetch thread, processed * directly after each AG is queued. */ if (!stride) { queue.mp = mp; prefetch_ag_range(&queue, 0, mp->m_sb.sb_agcount, dirs_only, func); return; } /* * create one worker thread for each segment of the volume */ queues = malloc(thread_count * sizeof(work_queue_t)); for (i = 0; i < thread_count; i++) { struct pf_work_args *wargs; wargs = malloc(sizeof(struct pf_work_args)); wargs->start_ag = i * stride; wargs->end_ag = min((i + 1) * stride, mp->m_sb.sb_agcount); wargs->dirs_only = dirs_only; wargs->func = func; create_work_queue(&queues[i], mp, 1); queue_work(&queues[i], prefetch_ag_range_work, 0, wargs); queues_started++; if (wargs->end_ag >= mp->m_sb.sb_agcount) break; } /* * wait for workers to complete */ for (i = 0; i < queues_started; i++) destroy_work_queue(&queues[i]); free(queues); } void wait_for_inode_prefetch( prefetch_args_t *args) { if (args == NULL) return; pthread_mutex_lock(&args->lock); while (!args->can_start_processing) { pftrace("waiting to start processing AG %d", args->agno); pthread_cond_wait(&args->start_processing, &args->lock); } pftrace("can start processing AG %d", args->agno); pthread_mutex_unlock(&args->lock); } void cleanup_inode_prefetch( prefetch_args_t *args) { if (args == NULL) return; pftrace("waiting AG %d prefetch to finish", args->agno); if (args->queuing_thread) pthread_join(args->queuing_thread, NULL); pftrace("AG %d prefetch done", args->agno); pthread_mutex_destroy(&args->lock); pthread_cond_destroy(&args->start_reading); pthread_cond_destroy(&args->start_processing); sem_destroy(&args->ra_count); btree_destroy(args->io_queue); free(args); } #ifdef XR_PF_TRACE static FILE *pf_trace_file; void pftrace_init(void) { pf_trace_file = fopen("/tmp/xfs_repair_prefetch.trace", "w"); setvbuf(pf_trace_file, NULL, _IOLBF, 1024); } void pftrace_done(void) { fclose(pf_trace_file); } void _pftrace(const char *func, const char *msg, ...) { char buf[200]; struct timeval tv; va_list args; gettimeofday(&tv, NULL); va_start(args, msg); vsnprintf(buf, sizeof(buf), msg, args); buf[sizeof(buf)-1] = '\0'; va_end(args); fprintf(pf_trace_file, "%lu.%06lu %s: %s\n", tv.tv_sec, tv.tv_usec, func, buf); } #endif xfsprogs-4.9.0+nmu1ubuntu2/repair/prefetch.h0000644000000000000000000000275113063067173015734 0ustar #ifndef _XFS_REPAIR_PREFETCH_H #define _XFS_REPAIR_PREFETCH_H #include #include "incore.h" struct work_queue; extern int do_prefetch; #define PF_THREAD_COUNT 4 typedef struct prefetch_args { pthread_mutex_t lock; pthread_t queuing_thread; pthread_t io_threads[PF_THREAD_COUNT]; struct btree_root *io_queue; pthread_cond_t start_reading; pthread_cond_t start_processing; int agno; int dirs_only; volatile int can_start_reading; volatile int can_start_processing; volatile int prefetch_done; volatile int queuing_done; volatile int inode_bufs_queued; volatile xfs_fsblock_t last_bno_read; sem_t ra_count; struct prefetch_args *next_args; } prefetch_args_t; void init_prefetch( xfs_mount_t *pmp); prefetch_args_t * start_inode_prefetch( xfs_agnumber_t agno, int dirs_only, prefetch_args_t *prev_args); void do_inode_prefetch( struct xfs_mount *mp, int stride, void (*func)(struct work_queue *, xfs_agnumber_t, void *), bool check_cache, bool dirs_only); void wait_for_inode_prefetch( prefetch_args_t *args); void cleanup_inode_prefetch( prefetch_args_t *args); #ifdef XR_PF_TRACE void pftrace_init(void); void pftrace_done(void); #define pftrace(msg...) _pftrace(__FUNCTION__, ## msg) void _pftrace(const char *, const char *, ...); #else static inline void pftrace_init(void) { }; static inline void pftrace_done(void) { }; static inline void pftrace(const char *msg, ...) { }; #endif #endif /* _XFS_REPAIR_PREFETCH_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/progress.c0000644000000000000000000003046313063067173015774 0ustar #include "libxfs.h" #include "globals.h" #include "progress.h" #include "err_protos.h" #include #define ONEMINUTE 60 #define ONEHOUR (60*ONEMINUTE) #define ONEDAY (24*ONEHOUR) #define ONEWEEK (7*ONEDAY) static char *rpt_types[] = { #define TYPE_INODE 0 N_("inodes"), #define TYPE_BLOCK 1 N_("blocks"), #define TYPE_DIR 2 N_("directories"), #define TYPE_AG 3 N_("allocation groups"), #define TYPE_AGI_BUCKET 4 N_("AGI unlinked buckets"), #define TYPE_EXTENTS 5 N_("extents"), #define TYPE_RTEXTENTS 6 N_("realtime extents"), #define TYPE_UNLINKED_LIST 7 N_("unlinked lists") }; static char *rpt_fmts[] = { #define FMT1 0 N_(" - %02d:%02d:%02d: %s - %llu of %llu %s done\n"), #define FMT2 1 N_(" - %02d:%02d:%02d: %s - %llu %s done\n"), }; typedef struct progress_rpt_s { short format; char *msg; char **fmt; char **type; } progress_rpt_t; static progress_rpt_t progress_rpt_reports[] = { {FMT1, N_("scanning filesystem freespace"), /* 0 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT1, N_("scanning agi unlinked lists"), /* 1 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT2, N_("check uncertain AG inodes"), /* 2 */ &rpt_fmts[FMT2], &rpt_types[TYPE_AGI_BUCKET]}, {FMT1, N_("process known inodes and inode discovery"), /* 3 */ &rpt_fmts[FMT1], &rpt_types[TYPE_INODE]}, {FMT1, N_("process newly discovered inodes"), /* 4 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT1, N_("setting up duplicate extent list"), /* 5 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT1, N_("initialize realtime bitmap"), /* 6 */ &rpt_fmts[FMT1], &rpt_types[TYPE_BLOCK]}, {FMT1, N_("reset realtime bitmaps"), /* 7 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT1, N_("check for inodes claiming duplicate blocks"), /* 8 */ &rpt_fmts[FMT1], &rpt_types[TYPE_INODE]}, {FMT1, N_("rebuild AG headers and trees"), /* 9 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT1, N_("traversing filesystem"), /* 10 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT2, N_("traversing all unattached subtrees"), /* 11 */ &rpt_fmts[FMT2], &rpt_types[TYPE_DIR]}, {FMT2, N_("moving disconnected inodes to lost+found"), /* 12 */ &rpt_fmts[FMT2], &rpt_types[TYPE_INODE]}, {FMT1, N_("verify and correct link counts"), /* 13 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]}, {FMT1, N_("verify link counts"), /* 14 */ &rpt_fmts[FMT1], &rpt_types[TYPE_AG]} }; pthread_t report_thread; typedef struct msg_block_s { pthread_mutex_t mutex; progress_rpt_t *format; __uint64_t *done; __uint64_t *total; int count; int interval; } msg_block_t; static msg_block_t global_msgs; typedef struct phase_times_s { time_t start; time_t end; time_t duration; __uint64_t item_counts[4]; } phase_times_t; static phase_times_t phase_times[8]; static void *progress_rpt_thread(void *); static int current_phase; static int running; static __uint64_t prog_rpt_total; void init_progress_rpt (void) { /* * allocate the done vector */ if ((prog_rpt_done = (__uint64_t *) malloc(sizeof(__uint64_t)*glob_agcount)) == NULL ) { do_error(_("cannot malloc pointer to done vector\n")); } bzero(prog_rpt_done, sizeof(__uint64_t)*glob_agcount); /* * Setup comm block, start the thread */ pthread_mutex_init(&global_msgs.mutex, NULL); global_msgs.format = NULL; global_msgs.count = glob_agcount; global_msgs.interval = report_interval; global_msgs.done = prog_rpt_done; global_msgs.total = &prog_rpt_total; if (pthread_create (&report_thread, NULL, progress_rpt_thread, (void *)&global_msgs)) do_error(_("unable to create progress report thread\n")); return; } void stop_progress_rpt(void) { /* * Tell msg thread to shutdown, * wait for all threads to finished */ running = 0; pthread_kill (report_thread, SIGHUP); pthread_join (report_thread, NULL); free(prog_rpt_done); return; } static void * progress_rpt_thread (void *p) { int i; int caught; sigset_t sigs_to_catch; struct tm *tmp; time_t now, elapsed; timer_t timerid; struct itimerspec timespec; char *msgbuf; __uint64_t *donep; __uint64_t sum; msg_block_t *msgp = (msg_block_t *)p; __uint64_t percent; /* It's possible to get here very early w/ no progress msg set */ if (!msgp->format) return NULL; if ((msgbuf = (char *)malloc(DURATION_BUF_SIZE)) == NULL) do_error (_("progress_rpt: cannot malloc progress msg buffer\n")); running = 1; /* * Specify a repeating timer that fires each MSG_INTERVAL seconds. */ memset(×pec, 0, sizeof(timespec)); timespec.it_value.tv_sec = msgp->interval; timespec.it_interval.tv_sec = msgp->interval; if (timer_create (CLOCK_REALTIME, NULL, &timerid)) do_error(_("progress_rpt: cannot create timer\n")); if (timer_settime (timerid, 0, ×pec, NULL)) do_error(_("progress_rpt: cannot set timer\n")); /* * Main loop - output messages based on periodic signal arrival * set this thread's signal mask to block out all other signals */ sigemptyset (&sigs_to_catch); sigaddset (&sigs_to_catch, SIGALRM); sigaddset (&sigs_to_catch, SIGHUP); sigwait (&sigs_to_catch, &caught); while (caught != SIGHUP) { /* * Allow the mainline to hold off messages by holding * the lock. We don't want to just skip a period in case the * reporting interval is very long... people get nervous. But, * if the interval is very short, we can't let the timer go * off again without sigwait'ing for it. So disarm the timer * while we try to get the lock and giveup the cpu... the * mainline shouldn't take that long. */ if (pthread_mutex_lock(&msgp->mutex)) { do_error(_("progress_rpt: cannot lock progress mutex\n")); } if (!running) break; now = time (NULL); tmp = localtime ((const time_t *) &now); /* * Sum the work */ sum = 0; donep = msgp->done; for (i = 0; i < msgp->count; i++) { sum += *donep++; } percent = 0; switch(msgp->format->format) { case FMT1: if (*msgp->total) percent = (sum * 100) / ( *msgp->total ); sprintf (msgbuf, *msgp->format->fmt, tmp->tm_hour, tmp->tm_min, tmp->tm_sec, msgp->format->msg, sum, *msgp->total, *msgp->format->type); break; case FMT2: sprintf (msgbuf, *msgp->format->fmt, tmp->tm_hour, tmp->tm_min, tmp->tm_sec, msgp->format->msg, sum, *msgp->format->type); break; } do_log(_("%s"), msgbuf); elapsed = now - phase_times[current_phase].start; if ((msgp->format->format == FMT1) && sum && elapsed && ((current_phase == 3) || (current_phase == 4) || (current_phase == 7))) { /* for inode phase report % complete */ do_log( _("\t- %02d:%02d:%02d: Phase %d: elapsed time %s - processed %d %s per minute\n"), tmp->tm_hour, tmp->tm_min, tmp->tm_sec, current_phase, duration(elapsed, msgbuf), (int) (60*sum/(elapsed)), *msgp->format->type); do_log( _("\t- %02d:%02d:%02d: Phase %d: %" PRIu64 "%% done - estimated remaining time %s\n"), tmp->tm_hour, tmp->tm_min, tmp->tm_sec, current_phase, percent, duration((int) ((*msgp->total - sum) * (elapsed)/sum), msgbuf)); } if (pthread_mutex_unlock(&msgp->mutex) != 0) { do_error( _("progress_rpt: error unlock msg mutex\n")); } sigwait (&sigs_to_catch, &caught); } if (timer_delete (timerid)) do_warn(_("cannot delete timer\n")); free (msgbuf); return (NULL); } int set_progress_msg (int report, __uint64_t total) { if (!ag_stride) return (0); if (pthread_mutex_lock(&global_msgs.mutex)) do_error(_("set_progress_msg: cannot lock progress mutex\n")); prog_rpt_total = total; global_msgs.format = &progress_rpt_reports[report]; /* reset all the accumulative totals */ if (prog_rpt_done) bzero(prog_rpt_done, sizeof(__uint64_t)*glob_agcount); if (pthread_mutex_unlock(&global_msgs.mutex)) do_error(_("set_progress_msg: cannot unlock progress mutex\n")); return (0); } __uint64_t print_final_rpt(void) { int i; struct tm *tmp; time_t now; __uint64_t *donep; __uint64_t sum; msg_block_t *msgp = &global_msgs; char msgbuf[DURATION_BUF_SIZE]; if (!ag_stride) return 0; if (pthread_mutex_lock(&global_msgs.mutex)) do_error(_("print_final_rpt: cannot lock progress mutex\n")); bzero(&msgbuf, sizeof(msgbuf)); now = time (NULL); tmp = localtime ((const time_t *) &now); /* * Sum the work */ sum = 0; donep = msgp->done; for (i = 0; i < msgp->count; i++) { sum += *donep++; } if (report_interval) { switch(msgp->format->format) { case FMT1: sprintf (msgbuf, _(*msgp->format->fmt), tmp->tm_hour, tmp->tm_min, tmp->tm_sec, _(msgp->format->msg), sum, *msgp->total, _(*msgp->format->type)); break; case FMT2: sprintf (msgbuf, _(*msgp->format->fmt), tmp->tm_hour, tmp->tm_min, tmp->tm_sec, _(msgp->format->msg), sum, _(*msgp->format->type)); break; } do_log(_("%s"), msgbuf); } if (pthread_mutex_unlock(&global_msgs.mutex)) do_error(_("print_final_rpt: cannot unlock progress mutex\n")); return(sum); } static void timediff(int phase) { phase_times[phase].duration = phase_times[phase].end - phase_times[phase].start; } /* ** Get the time and save in the phase time ** array. */ char * timestamp(int end, int phase, char *buf) { time_t now; struct tm *tmp; if (verbose > 1) cache_report(stderr, "libxfs_bcache", libxfs_bcache); now = time(NULL); if (end) { phase_times[phase].end = now; timediff(phase); /* total time in slot zero */ phase_times[0].end = now; timediff(0); if (phase < 7) { phase_times[phase+1].start = now; current_phase = phase + 1; } } else { phase_times[phase].start = now; current_phase = phase; } if (buf) { tmp = localtime((const time_t *)&now); sprintf(buf, _("%02d:%02d:%02d"), tmp->tm_hour, tmp->tm_min, tmp->tm_sec); } return(buf); } char * duration(int length, char *buf) { int sum; int weeks; int days; int hours; int minutes; int seconds; char temp[128]; *buf = '\0'; weeks = days = hours = minutes = seconds = sum = 0; if (length >= ONEWEEK) { weeks = length / ONEWEEK; sum = (weeks * ONEWEEK); if (weeks) { sprintf(buf, _("%d week"), weeks); if (weeks > 1) strcat(buf, _("s")); if ((length-sum) == 0) return(buf); } } if (length >= ONEDAY) { days = (length - sum) / ONEDAY; sum += (days * ONEDAY); if (days) { sprintf(temp, _("%d day"), days); if (days > 1) strcat(temp, _("s")); if (((length-sum) == 0) && (!weeks)) { strcpy(buf, temp); return(buf); } else if (weeks) { strcat(buf, _(", ")); } strcat(buf, temp); } } if (length >= ONEHOUR) { hours = (length - sum) / ONEHOUR; sum += (hours * ONEHOUR); if (hours) { sprintf(temp, _("%d hour"), hours); if (hours > 1) strcat(temp, _("s")); if (((length-sum) == 0) && (!weeks) && (!days)) { strcpy(buf, temp); return(buf); } else if ((weeks) || (days)) { strcat(buf, _(", ")); } strcat(buf, temp); } } if (length >= ONEMINUTE) { minutes = (length - sum) / ONEMINUTE; sum += (minutes * ONEMINUTE); if (minutes) { sprintf(temp, _("%d minute"), minutes); if (minutes > 1) strcat(temp, _("s")); if (((length-sum) == 0) && (!weeks) && (!days) && (!hours)) { strcpy(buf, temp); return(buf); } else if ((weeks)||(days)||(hours)) { strcat(buf, _(", ")); } strcat(buf, temp); } } seconds = length - sum; if (seconds) { sprintf(temp, _("%d second"), seconds); if (seconds > 1) strcat(temp, _("s")); if ((weeks)||(days)||(hours)||(minutes)) strcat(buf, _(", ")); strcat(buf, temp); } return(buf); } void summary_report(void) { int i; time_t now; struct tm end; struct tm start; char msgbuf[DURATION_BUF_SIZE]; now = time(NULL); do_log(_("\n XFS_REPAIR Summary %s\n"), ctime((const time_t *)&now)); do_log(_("Phase\t\tStart\t\tEnd\t\tDuration\n")); for (i = 1; i < 8; i++) { localtime_r((const time_t *)&phase_times[i].start, &start); localtime_r((const time_t *)&phase_times[i].end, &end); if ((no_modify) && (i == 5)) { do_log(_("Phase %d:\tSkipped\n"), i); } else if ((bad_ino_btree) && ((i == 6) || (i == 7))) { do_log(_("Phase %d:\tSkipped\n"), i); } else { do_log( _("Phase %d:\t%02d/%02d %02d:%02d:%02d\t%02d/%02d %02d:%02d:%02d\t%s\n"), i, start.tm_mon+1, start.tm_mday, start.tm_hour, start.tm_min, start.tm_sec, end.tm_mon+1, end.tm_mday, end.tm_hour, end.tm_min, end.tm_sec, duration(phase_times[i].duration, msgbuf)); } } do_log(_("\nTotal run time: %s\n"), duration(phase_times[0].duration, msgbuf)); } xfsprogs-4.9.0+nmu1ubuntu2/repair/progress.h0000644000000000000000000000231113063067172015767 0ustar #ifndef _XFS_REPAIR_PROGRESS_RPT_H_ #define _XFS_REPAIR_PROGRESS_RPT_H_ #define PROG_RPT_DEFAULT (15*60) /* default 15 minute report interval */ #define PHASE_START 0 #define PHASE_END 1 #define PROG_FMT_SCAN_AG 0 /* Phase 2 */ #define PROG_FMT_AGI_UNLINKED 1 /* Phase 3 */ #define PROG_FMT_UNCERTAIN 2 #define PROG_FMT_PROCESS_INO 3 #define PROG_FMT_NEW_INODES 4 #define PROG_FMT_DUP_EXTENT 5 /* Phase 4 */ #define PROG_FMT_INIT_RTEXT 6 #define PROG_FMT_RESET_RTBM 7 #define PROG_FMT_DUP_BLOCKS 8 #define PROG_FMT_REBUILD_AG 9 /* Phase 5 */ #define PROG_FMT_TRAVERSAL 10 /* Phase 6 */ #define PROG_FMT_TRAVERSSUB 11 #define PROG_FMT_DISCONINODE 12 #define PROGRESS_FMT_CORR_LINK 13 /* Phase 7 */ #define PROGRESS_FMT_VRFY_LINK 14 #define DURATION_BUF_SIZE 512 extern void init_progress_rpt(void); extern void stop_progress_rpt(void); extern void summary_report(void); extern int set_progress_msg(int report, __uint64_t total); extern __uint64_t print_final_rpt(void); extern char *timestamp(int end, int phase, char *buf); extern char *duration(int val, char *buf); extern int do_parallel; #define PROG_RPT_INC(a,b) if (ag_stride && prog_rpt_done) (a) += (b) #endif /* _XFS_REPAIR_PROGRESS_RPT_H_ */ xfsprogs-4.9.0+nmu1ubuntu2/repair/protos.h0000644000000000000000000000324213063067172015455 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ void xfs_init(libxfs_init_t *args); int verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb); int verify_set_primary_sb(xfs_sb_t *root_sb, int sb_index, int *sb_modified); int get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno); void write_primary_sb(xfs_sb_t *sbp, int size); int find_secondary_sb(xfs_sb_t *sb); struct fs_geometry; void get_sb_geometry(struct fs_geometry *geo, xfs_sb_t *sbp); char *alloc_ag_buf(int size); void print_inode_list(xfs_agnumber_t i); char *err_string(int err_code); void thread_init(void); void phase1(struct xfs_mount *); void phase2(struct xfs_mount *, int); void phase3(struct xfs_mount *, int); void phase4(struct xfs_mount *); void phase5(struct xfs_mount *); void phase6(struct xfs_mount *); void phase7(struct xfs_mount *, int); int verify_set_agheader(struct xfs_mount *, struct xfs_buf *, struct xfs_sb *, struct xfs_agf *, struct xfs_agi *, xfs_agnumber_t); xfsprogs-4.9.0+nmu1ubuntu2/repair/rmap.c0000644000000000000000000011351013033541503015051 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "btree.h" #include "err_protos.h" #include "libxlog.h" #include "incore.h" #include "globals.h" #include "dinode.h" #include "slab.h" #include "rmap.h" #undef RMAP_DEBUG #ifdef RMAP_DEBUG # define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0) #else # define dbg_printf(f, a...) #endif /* per-AG rmap object anchor */ struct xfs_ag_rmap { struct xfs_slab *ar_rmaps; /* rmap observations, p4 */ struct xfs_slab *ar_raw_rmaps; /* unmerged rmaps */ int ar_flcount; /* agfl entries from leftover */ /* agbt allocations */ struct xfs_rmap_irec ar_last_rmap; /* last rmap seen */ struct xfs_slab *ar_refcount_items; /* refcount items, p4-5 */ }; static struct xfs_ag_rmap *ag_rmaps; static bool rmapbt_suspect; static bool refcbt_suspect; /* * Compare rmap observations for array sorting. */ static int rmap_compare( const void *a, const void *b) { const struct xfs_rmap_irec *pa; const struct xfs_rmap_irec *pb; __u64 oa; __u64 ob; pa = a; pb = b; oa = libxfs_rmap_irec_offset_pack(pa); ob = libxfs_rmap_irec_offset_pack(pb); if (pa->rm_startblock < pb->rm_startblock) return -1; else if (pa->rm_startblock > pb->rm_startblock) return 1; else if (pa->rm_owner < pb->rm_owner) return -1; else if (pa->rm_owner > pb->rm_owner) return 1; else if (oa < ob) return -1; else if (oa > ob) return 1; else return 0; } /* * Returns true if we must reconstruct either the reference count or reverse * mapping trees. */ bool rmap_needs_work( struct xfs_mount *mp) { return xfs_sb_version_hasreflink(&mp->m_sb) || xfs_sb_version_hasrmapbt(&mp->m_sb); } /* * Initialize per-AG reverse map data. */ void rmaps_init( struct xfs_mount *mp) { xfs_agnumber_t i; int error; if (!rmap_needs_work(mp)) return; ag_rmaps = calloc(mp->m_sb.sb_agcount, sizeof(struct xfs_ag_rmap)); if (!ag_rmaps) do_error(_("couldn't allocate per-AG reverse map roots\n")); for (i = 0; i < mp->m_sb.sb_agcount; i++) { error = init_slab(&ag_rmaps[i].ar_rmaps, sizeof(struct xfs_rmap_irec)); if (error) do_error( _("Insufficient memory while allocating reverse mapping slabs.")); error = init_slab(&ag_rmaps[i].ar_raw_rmaps, sizeof(struct xfs_rmap_irec)); if (error) do_error( _("Insufficient memory while allocating raw metadata reverse mapping slabs.")); ag_rmaps[i].ar_last_rmap.rm_owner = XFS_RMAP_OWN_UNKNOWN; error = init_slab(&ag_rmaps[i].ar_refcount_items, sizeof(struct xfs_refcount_irec)); if (error) do_error( _("Insufficient memory while allocating refcount item slabs.")); } } /* * Free the per-AG reverse-mapping data. */ void rmaps_free( struct xfs_mount *mp) { xfs_agnumber_t i; if (!rmap_needs_work(mp)) return; for (i = 0; i < mp->m_sb.sb_agcount; i++) { free_slab(&ag_rmaps[i].ar_rmaps); free_slab(&ag_rmaps[i].ar_raw_rmaps); free_slab(&ag_rmaps[i].ar_refcount_items); } free(ag_rmaps); ag_rmaps = NULL; } /* * Decide if two reverse-mapping records can be merged. */ bool rmaps_are_mergeable( struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2) { if (r1->rm_owner != r2->rm_owner) return false; if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock) return false; if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount > XFS_RMAP_LEN_MAX) return false; if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner)) return true; /* must be an inode owner below here */ if (r1->rm_flags != r2->rm_flags) return false; if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK) return true; return r1->rm_offset + r1->rm_blockcount == r2->rm_offset; } /* * Add an observation about a block mapping in an inode's data or attribute * fork for later btree reconstruction. */ int rmap_add_rec( struct xfs_mount *mp, xfs_ino_t ino, int whichfork, struct xfs_bmbt_irec *irec) { struct xfs_rmap_irec rmap; xfs_agnumber_t agno; xfs_agblock_t agbno; struct xfs_rmap_irec *last_rmap; int error = 0; if (!rmap_needs_work(mp)) return 0; agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); ASSERT(agno != NULLAGNUMBER); ASSERT(agno < mp->m_sb.sb_agcount); ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks); ASSERT(ino != NULLFSINO); ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK); rmap.rm_owner = ino; rmap.rm_offset = irec->br_startoff; rmap.rm_flags = 0; if (whichfork == XFS_ATTR_FORK) rmap.rm_flags |= XFS_RMAP_ATTR_FORK; rmap.rm_startblock = agbno; rmap.rm_blockcount = irec->br_blockcount; if (irec->br_state == XFS_EXT_UNWRITTEN) rmap.rm_flags |= XFS_RMAP_UNWRITTEN; last_rmap = &ag_rmaps[agno].ar_last_rmap; if (last_rmap->rm_owner == XFS_RMAP_OWN_UNKNOWN) *last_rmap = rmap; else if (rmaps_are_mergeable(last_rmap, &rmap)) last_rmap->rm_blockcount += rmap.rm_blockcount; else { error = slab_add(ag_rmaps[agno].ar_rmaps, last_rmap); if (error) return error; *last_rmap = rmap; } return error; } /* Finish collecting inode data/attr fork rmaps. */ int rmap_finish_collecting_fork_recs( struct xfs_mount *mp, xfs_agnumber_t agno) { if (!rmap_needs_work(mp) || ag_rmaps[agno].ar_last_rmap.rm_owner == XFS_RMAP_OWN_UNKNOWN) return 0; return slab_add(ag_rmaps[agno].ar_rmaps, &ag_rmaps[agno].ar_last_rmap); } /* add a raw rmap; these will be merged later */ static int __rmap_add_raw_rec( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner, bool is_attr, bool is_bmbt) { struct xfs_rmap_irec rmap; ASSERT(len != 0); rmap.rm_owner = owner; rmap.rm_offset = 0; rmap.rm_flags = 0; if (is_attr) rmap.rm_flags |= XFS_RMAP_ATTR_FORK; if (is_bmbt) rmap.rm_flags |= XFS_RMAP_BMBT_BLOCK; rmap.rm_startblock = agbno; rmap.rm_blockcount = len; return slab_add(ag_rmaps[agno].ar_raw_rmaps, &rmap); } /* * Add a reverse mapping for an inode fork's block mapping btree block. */ int rmap_add_bmbt_rec( struct xfs_mount *mp, xfs_ino_t ino, int whichfork, xfs_fsblock_t fsbno) { xfs_agnumber_t agno; xfs_agblock_t agbno; if (!rmap_needs_work(mp)) return 0; agno = XFS_FSB_TO_AGNO(mp, fsbno); agbno = XFS_FSB_TO_AGBNO(mp, fsbno); ASSERT(agno != NULLAGNUMBER); ASSERT(agno < mp->m_sb.sb_agcount); ASSERT(agbno + 1 <= mp->m_sb.sb_agblocks); return __rmap_add_raw_rec(mp, agno, agbno, 1, ino, whichfork == XFS_ATTR_FORK, true); } /* * Add a reverse mapping for a per-AG fixed metadata extent. */ int rmap_add_ag_rec( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner) { if (!rmap_needs_work(mp)) return 0; ASSERT(agno != NULLAGNUMBER); ASSERT(agno < mp->m_sb.sb_agcount); ASSERT(agbno + len <= mp->m_sb.sb_agblocks); return __rmap_add_raw_rec(mp, agno, agbno, len, owner, false, false); } /* * Merge adjacent raw rmaps and add them to the main rmap list. */ int rmap_fold_raw_recs( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_slab_cursor *cur = NULL; struct xfs_rmap_irec *prev, *rec; size_t old_sz; int error = 0; old_sz = slab_count(ag_rmaps[agno].ar_rmaps); if (slab_count(ag_rmaps[agno].ar_raw_rmaps) == 0) goto no_raw; qsort_slab(ag_rmaps[agno].ar_raw_rmaps, rmap_compare); error = init_slab_cursor(ag_rmaps[agno].ar_raw_rmaps, rmap_compare, &cur); if (error) goto err; prev = pop_slab_cursor(cur); rec = pop_slab_cursor(cur); while (prev && rec) { if (rmaps_are_mergeable(prev, rec)) { prev->rm_blockcount += rec->rm_blockcount; rec = pop_slab_cursor(cur); continue; } error = slab_add(ag_rmaps[agno].ar_rmaps, prev); if (error) goto err; prev = rec; rec = pop_slab_cursor(cur); } if (prev) { error = slab_add(ag_rmaps[agno].ar_rmaps, prev); if (error) goto err; } free_slab(&ag_rmaps[agno].ar_raw_rmaps); error = init_slab(&ag_rmaps[agno].ar_raw_rmaps, sizeof(struct xfs_rmap_irec)); if (error) do_error( _("Insufficient memory while allocating raw metadata reverse mapping slabs.")); no_raw: if (old_sz) qsort_slab(ag_rmaps[agno].ar_rmaps, rmap_compare); err: free_slab_cursor(&cur); return error; } static int find_first_zero_bit( __uint64_t mask) { int n; int b = 0; for (n = 0; n < sizeof(mask) * NBBY && (mask & 1); n++, mask >>= 1) b++; return b; } static int popcnt( __uint64_t mask) { int n; int b = 0; if (mask == 0) return 0; for (n = 0; n < sizeof(mask) * NBBY; n++, mask >>= 1) if (mask & 1) b++; return b; } /* * Add an allocation group's fixed metadata to the rmap list. This includes * sb/agi/agf/agfl headers, inode chunks, and the log. */ int rmap_add_fixed_ag_rec( struct xfs_mount *mp, xfs_agnumber_t agno) { xfs_fsblock_t fsbno; xfs_agblock_t agbno; ino_tree_node_t *ino_rec; xfs_agino_t agino; int error; int startidx; int nr; if (!rmap_needs_work(mp)) return 0; /* sb/agi/agf/agfl headers */ error = rmap_add_ag_rec(mp, agno, 0, XFS_BNO_BLOCK(mp), XFS_RMAP_OWN_FS); if (error) goto out; /* inodes */ ino_rec = findfirst_inode_rec(agno); for (; ino_rec != NULL; ino_rec = next_ino_rec(ino_rec)) { if (xfs_sb_version_hassparseinodes(&mp->m_sb)) { startidx = find_first_zero_bit(ino_rec->ir_sparse); nr = XFS_INODES_PER_CHUNK - popcnt(ino_rec->ir_sparse); } else { startidx = 0; nr = XFS_INODES_PER_CHUNK; } nr /= mp->m_sb.sb_inopblock; if (nr == 0) nr = 1; agino = ino_rec->ino_startnum + startidx; agbno = XFS_AGINO_TO_AGBNO(mp, agino); if (XFS_AGINO_TO_OFFSET(mp, agino) == 0) { error = rmap_add_ag_rec(mp, agno, agbno, nr, XFS_RMAP_OWN_INODES); if (error) goto out; } } /* log */ fsbno = mp->m_sb.sb_logstart; if (fsbno && XFS_FSB_TO_AGNO(mp, fsbno) == agno) { agbno = XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart); error = rmap_add_ag_rec(mp, agno, agbno, mp->m_sb.sb_logblocks, XFS_RMAP_OWN_LOG); if (error) goto out; } out: return error; } /* * Copy the per-AG btree reverse-mapping data into the rmapbt. * * At rmapbt reconstruction time, the rmapbt will be populated _only_ with * rmaps for file extents, inode chunks, AG headers, and bmbt blocks. While * building the AG btrees we can record all the blocks allocated for each * btree, but we cannot resolve the conflict between the fact that one has to * finish allocating the space for the rmapbt before building the bnobt and the * fact that allocating blocks for the bnobt requires adding rmapbt entries. * Therefore we record in-core the rmaps for each btree and here use the * libxfs rmap functions to finish building the rmap btree. * * During AGF/AGFL reconstruction in phase 5, rmaps for the AG btrees are * recorded in memory. The rmapbt has not been set up yet, so we need to be * able to "expand" the AGFL without updating the rmapbt. After we've written * out the new AGF header the new rmapbt is available, so this function reads * each AGFL to generate rmap entries. These entries are merged with the AG * btree rmap entries, and then we use libxfs' rmap functions to add them to * the rmapbt, after which it is fully regenerated. */ int rmap_store_ag_btree_rec( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_slab_cursor *rm_cur; struct xfs_rmap_irec *rm_rec = NULL; struct xfs_buf *agbp = NULL; struct xfs_buf *agflbp = NULL; struct xfs_trans *tp; struct xfs_trans_res tres = {0}; __be32 *agfl_bno, *b; int error = 0; struct xfs_owner_info oinfo; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; /* Release the ar_rmaps; they were put into the rmapbt during p5. */ free_slab(&ag_rmaps[agno].ar_rmaps); error = init_slab(&ag_rmaps[agno].ar_rmaps, sizeof(struct xfs_rmap_irec)); if (error) goto err; /* Add the AGFL blocks to the rmap list */ error = -libxfs_trans_read_buf( mp, NULL, mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, &agflbp, &xfs_agfl_buf_ops); if (error) goto err; /* * Sometimes, the blocks at the beginning of the AGFL are there * because we overestimated how many blocks we needed to rebuild * the freespace btrees. ar_flcount records the number of * blocks in this situation. Since those blocks already have an * rmap, we only need to add rmap records for AGFL blocks past * that point in the AGFL because those blocks are a result of a * no-rmap no-shrink freelist fixup that we did earlier. */ agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); b = agfl_bno + ag_rmaps[agno].ar_flcount; while (*b != NULLAGBLOCK && b - agfl_bno < XFS_AGFL_SIZE(mp)) { error = rmap_add_ag_rec(mp, agno, be32_to_cpu(*b), 1, XFS_RMAP_OWN_AG); if (error) goto err; b++; } libxfs_putbuf(agflbp); agflbp = NULL; /* Merge all the raw rmaps into the main list */ error = rmap_fold_raw_recs(mp, agno); if (error) goto err; /* Create cursors to refcount structures */ error = init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare, &rm_cur); if (error) goto err; /* Insert rmaps into the btree one at a time */ rm_rec = pop_slab_cursor(rm_cur); while (rm_rec) { error = -libxfs_trans_alloc(mp, &tres, 16, 0, 0, &tp); if (error) goto err_slab; error = -libxfs_alloc_read_agf(mp, tp, agno, 0, &agbp); if (error) goto err_trans; ASSERT(XFS_RMAP_NON_INODE_OWNER(rm_rec->rm_owner)); libxfs_rmap_ag_owner(&oinfo, rm_rec->rm_owner); error = -libxfs_rmap_alloc(tp, agbp, agno, rm_rec->rm_startblock, rm_rec->rm_blockcount, &oinfo); if (error) goto err_trans; error = -libxfs_trans_commit(tp); if (error) goto err_slab; fix_freelist(mp, agno, false); rm_rec = pop_slab_cursor(rm_cur); } free_slab_cursor(&rm_cur); return 0; err_trans: libxfs_trans_cancel(tp); err_slab: free_slab_cursor(&rm_cur); err: if (agflbp) libxfs_putbuf(agflbp); return error; } #ifdef RMAP_DEBUG static void rmap_dump( const char *msg, xfs_agnumber_t agno, struct xfs_rmap_irec *rmap) { printf("%s: %p agno=%u pblk=%llu own=%lld lblk=%llu len=%u flags=0x%x\n", msg, rmap, (unsigned int)agno, (unsigned long long)rmap->rm_startblock, (unsigned long long)rmap->rm_owner, (unsigned long long)rmap->rm_offset, (unsigned int)rmap->rm_blockcount, (unsigned int)rmap->rm_flags); } #else # define rmap_dump(m, a, r) #endif /* * Rebuilding the Reference Count & Reverse Mapping Btrees * * The reference count (refcnt) and reverse mapping (rmap) btrees are * rebuilt during phase 5, like all other AG btrees. Therefore, reverse * mappings must be processed into reference counts at the end of phase * 4, and the rmaps must be recorded during phase 4. There is a need to * access the rmaps in physical block order, but no particular need for * random access, so the slab.c code provides a big logical array * (consisting of smaller slabs) and some inorder iterator functions. * * Once we've recorded all the reverse mappings, we're ready to * translate the rmaps into refcount entries. Imagine the rmap entries * as rectangles representing extents of physical blocks, and that the * rectangles can be laid down to allow them to overlap each other; then * we know that we must emit a refcnt btree entry wherever the amount of * overlap changes, i.e. the emission stimulus is level-triggered: * * - --- * -- ----- ---- --- ------ * -- ---- ----------- ---- --------- * -------------------------------- ----------- * ^ ^ ^^ ^^ ^ ^^ ^^^ ^^^^ ^ ^^ ^ ^ ^ * 2 1 23 21 3 43 234 2123 1 01 2 3 0 * * For our purposes, a rmap is a tuple (startblock, len, fileoff, owner). * * Note that in the actual refcnt btree we don't store the refcount < 2 * cases because the bnobt tells us which blocks are free; single-use * blocks aren't recorded in the bnobt or the refcntbt. If the rmapbt * supports storing multiple entries covering a given block we could * theoretically dispense with the refcntbt and simply count rmaps, but * that's inefficient in the (hot) write path, so we'll take the cost of * the extra tree to save time. Also there's no guarantee that rmap * will be enabled. * * Given an array of rmaps sorted by physical block number, a starting * physical block (sp), a bag to hold rmaps that cover sp, and the next * physical block where the level changes (np), we can reconstruct the * refcount btree as follows: * * While there are still unprocessed rmaps in the array, * - Set sp to the physical block (pblk) of the next unprocessed rmap. * - Add to the bag all rmaps in the array where startblock == sp. * - Set np to the physical block where the bag size will change. This * is the minimum of (the pblk of the next unprocessed rmap) and * (startblock + len of each rmap in the bag). * - Record the bag size as old_bag_size. * * - While the bag isn't empty, * - Remove from the bag all rmaps where startblock + len == np. * - Add to the bag all rmaps in the array where startblock == np. * - If the bag size isn't old_bag_size, store the refcount entry * (sp, np - sp, bag_size) in the refcnt btree. * - If the bag is empty, break out of the inner loop. * - Set old_bag_size to the bag size * - Set sp = np. * - Set np to the physical block where the bag size will change. * This is the minimum of (the pblk of the next unprocessed rmap) * and (startblock + len of each rmap in the bag). * * An implementation detail is that because this processing happens * during phase 4, the refcount entries are stored in an array so that * phase 5 can load them into the refcount btree. The rmaps can be * loaded directly into the rmap btree during phase 5 as well. */ /* * Mark all inodes in the reverse-mapping observation stack as requiring the * reflink inode flag, if the stack depth is greater than 1. */ static void mark_inode_rl( struct xfs_mount *mp, struct xfs_bag *rmaps) { xfs_agnumber_t iagno; struct xfs_rmap_irec *rmap; struct ino_tree_node *irec; int off; size_t idx; xfs_agino_t ino; if (bag_count(rmaps) < 2) return; /* Reflink flag accounting */ foreach_bag_ptr(rmaps, idx, rmap) { ASSERT(!XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner)); iagno = XFS_INO_TO_AGNO(mp, rmap->rm_owner); ino = XFS_INO_TO_AGINO(mp, rmap->rm_owner); pthread_mutex_lock(&ag_locks[iagno].lock); irec = find_inode_rec(mp, iagno, ino); off = get_inode_offset(mp, rmap->rm_owner, irec); /* lock here because we might go outside this ag */ set_inode_is_rl(irec, off); pthread_mutex_unlock(&ag_locks[iagno].lock); } } /* * Emit a refcount object for refcntbt reconstruction during phase 5. */ #define REFCOUNT_CLAMP(nr) ((nr) > MAXREFCOUNT ? MAXREFCOUNT : (nr)) static void refcount_emit( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, size_t nr_rmaps) { struct xfs_refcount_irec rlrec; int error; struct xfs_slab *rlslab; rlslab = ag_rmaps[agno].ar_refcount_items; ASSERT(nr_rmaps > 0); dbg_printf("REFL: agno=%u pblk=%u, len=%u -> refcount=%zu\n", agno, agbno, len, nr_rmaps); rlrec.rc_startblock = agbno; rlrec.rc_blockcount = len; rlrec.rc_refcount = REFCOUNT_CLAMP(nr_rmaps); error = slab_add(rlslab, &rlrec); if (error) do_error( _("Insufficient memory while recreating refcount tree.")); } #undef REFCOUNT_CLAMP /* * Transform a pile of physical block mapping observations into refcount data * for eventual rebuilding of the btrees. */ #define RMAP_END(r) ((r)->rm_startblock + (r)->rm_blockcount) int compute_refcounts( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_bag *stack_top = NULL; struct xfs_slab *rmaps; struct xfs_slab_cursor *rmaps_cur; struct xfs_rmap_irec *array_cur; struct xfs_rmap_irec *rmap; xfs_agblock_t sbno; /* first bno of this rmap set */ xfs_agblock_t cbno; /* first bno of this refcount set */ xfs_agblock_t nbno; /* next bno where rmap set changes */ size_t n, idx; size_t old_stack_nr; int error; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; rmaps = ag_rmaps[agno].ar_rmaps; error = init_slab_cursor(rmaps, rmap_compare, &rmaps_cur); if (error) return error; error = init_bag(&stack_top); if (error) goto err; /* While there are rmaps to be processed... */ n = 0; while (n < slab_count(rmaps)) { array_cur = peek_slab_cursor(rmaps_cur); sbno = cbno = array_cur->rm_startblock; /* Push all rmaps with pblk == sbno onto the stack */ for (; array_cur && array_cur->rm_startblock == sbno; array_cur = peek_slab_cursor(rmaps_cur)) { advance_slab_cursor(rmaps_cur); n++; rmap_dump("push0", agno, array_cur); error = bag_add(stack_top, array_cur); if (error) goto err; } mark_inode_rl(mp, stack_top); /* Set nbno to the bno of the next refcount change */ if (n < slab_count(rmaps) && array_cur) nbno = array_cur->rm_startblock; else nbno = NULLAGBLOCK; foreach_bag_ptr(stack_top, idx, rmap) { nbno = min(nbno, RMAP_END(rmap)); } /* Emit reverse mappings, if needed */ ASSERT(nbno > sbno); old_stack_nr = bag_count(stack_top); /* While stack isn't empty... */ while (bag_count(stack_top)) { /* Pop all rmaps that end at nbno */ foreach_bag_ptr_reverse(stack_top, idx, rmap) { if (RMAP_END(rmap) != nbno) continue; rmap_dump("pop", agno, rmap); error = bag_remove(stack_top, idx); if (error) goto err; } /* Push array items that start at nbno */ for (; array_cur && array_cur->rm_startblock == nbno; array_cur = peek_slab_cursor(rmaps_cur)) { advance_slab_cursor(rmaps_cur); n++; rmap_dump("push1", agno, array_cur); error = bag_add(stack_top, array_cur); if (error) goto err; } mark_inode_rl(mp, stack_top); /* Emit refcount if necessary */ ASSERT(nbno > cbno); if (bag_count(stack_top) != old_stack_nr) { if (old_stack_nr > 1) { refcount_emit(mp, agno, cbno, nbno - cbno, old_stack_nr); } cbno = nbno; } /* Stack empty, go find the next rmap */ if (bag_count(stack_top) == 0) break; old_stack_nr = bag_count(stack_top); sbno = nbno; /* Set nbno to the bno of the next refcount change */ if (n < slab_count(rmaps)) nbno = array_cur->rm_startblock; else nbno = NULLAGBLOCK; foreach_bag_ptr(stack_top, idx, rmap) { nbno = min(nbno, RMAP_END(rmap)); } /* Emit reverse mappings, if needed */ ASSERT(nbno > sbno); } } err: free_bag(&stack_top); free_slab_cursor(&rmaps_cur); return error; } #undef RMAP_END /* * Return the number of rmap objects for an AG. */ size_t rmap_record_count( struct xfs_mount *mp, xfs_agnumber_t agno) { return slab_count(ag_rmaps[agno].ar_rmaps); } /* * Return a slab cursor that will return rmap objects in order. */ int rmap_init_cursor( xfs_agnumber_t agno, struct xfs_slab_cursor **cur) { return init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare, cur); } /* * Disable the refcount btree check. */ void rmap_avoid_check(void) { rmapbt_suspect = true; } /* Look for an rmap in the rmapbt that matches a given rmap. */ static int rmap_lookup( struct xfs_btree_cur *bt_cur, struct xfs_rmap_irec *rm_rec, struct xfs_rmap_irec *tmp, int *have) { int error; /* Use the regular btree retrieval routine. */ error = -libxfs_rmap_lookup_le(bt_cur, rm_rec->rm_startblock, rm_rec->rm_blockcount, rm_rec->rm_owner, rm_rec->rm_offset, rm_rec->rm_flags, have); if (error) return error; if (*have == 0) return error; return -libxfs_rmap_get_rec(bt_cur, tmp, have); } /* Look for an rmap in the rmapbt that matches a given rmap. */ static int rmap_lookup_overlapped( struct xfs_btree_cur *bt_cur, struct xfs_rmap_irec *rm_rec, struct xfs_rmap_irec *tmp, int *have) { /* Have to use our fancy version for overlapped */ return -libxfs_rmap_lookup_le_range(bt_cur, rm_rec->rm_startblock, rm_rec->rm_owner, rm_rec->rm_offset, rm_rec->rm_flags, tmp, have); } /* Does the btree rmap cover the observed rmap? */ #define NEXTP(x) ((x)->rm_startblock + (x)->rm_blockcount) #define NEXTL(x) ((x)->rm_offset + (x)->rm_blockcount) static bool rmap_is_good( struct xfs_rmap_irec *observed, struct xfs_rmap_irec *btree) { /* Can't have mismatches in the flags or the owner. */ if (btree->rm_flags != observed->rm_flags || btree->rm_owner != observed->rm_owner) return false; /* * Btree record can't physically start after the observed * record, nor can it end before the observed record. */ if (btree->rm_startblock > observed->rm_startblock || NEXTP(btree) < NEXTP(observed)) return false; /* If this is metadata or bmbt, we're done. */ if (XFS_RMAP_NON_INODE_OWNER(observed->rm_owner) || (observed->rm_flags & XFS_RMAP_BMBT_BLOCK)) return true; /* * Btree record can't logically start after the observed * record, nor can it end before the observed record. */ if (btree->rm_offset > observed->rm_offset || NEXTL(btree) < NEXTL(observed)) return false; return true; } #undef NEXTP #undef NEXTL /* * Compare the observed reverse mappings against what's in the ag btree. */ int rmaps_verify_btree( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_slab_cursor *rm_cur; struct xfs_btree_cur *bt_cur = NULL; int error; int have; struct xfs_buf *agbp = NULL; struct xfs_rmap_irec *rm_rec; struct xfs_rmap_irec tmp; struct xfs_perag *pag; /* per allocation group data */ if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; if (rmapbt_suspect) { if (no_modify && agno == 0) do_warn(_("would rebuild corrupt rmap btrees.\n")); return 0; } /* Create cursors to refcount structures */ error = rmap_init_cursor(agno, &rm_cur); if (error) return error; error = -libxfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) goto err; /* Leave the per-ag data "uninitialized" since we rewrite it later */ pag = libxfs_perag_get(mp, agno); pag->pagf_init = 0; libxfs_perag_put(pag); bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, agno); if (!bt_cur) { error = -ENOMEM; goto err; } rm_rec = pop_slab_cursor(rm_cur); while (rm_rec) { error = rmap_lookup(bt_cur, rm_rec, &tmp, &have); if (error) goto err; /* * Using the range query is expensive, so only do it if * the regular lookup doesn't find anything or if it doesn't * match the observed rmap. */ if (xfs_sb_version_hasreflink(&bt_cur->bc_mp->m_sb) && (!have || !rmap_is_good(rm_rec, &tmp))) { error = rmap_lookup_overlapped(bt_cur, rm_rec, &tmp, &have); if (error) goto err; } if (!have) { do_warn( _("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \ %s%soff %"PRIu64"\n"), agno, rm_rec->rm_startblock, (rm_rec->rm_flags & XFS_RMAP_UNWRITTEN) ? _("unwritten ") : "", rm_rec->rm_blockcount, rm_rec->rm_owner, (rm_rec->rm_flags & XFS_RMAP_ATTR_FORK) ? _("attr ") : "", (rm_rec->rm_flags & XFS_RMAP_BMBT_BLOCK) ? _("bmbt ") : "", rm_rec->rm_offset); goto next_loop; } /* Compare each refcount observation against the btree's */ if (!rmap_is_good(rm_rec, &tmp)) { do_warn( _("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \ %"PRIu64"; should be (%u/%u) %slen %u owner %"PRId64" %s%soff %"PRIu64"\n"), agno, tmp.rm_startblock, (tmp.rm_flags & XFS_RMAP_UNWRITTEN) ? _("unwritten ") : "", tmp.rm_blockcount, tmp.rm_owner, (tmp.rm_flags & XFS_RMAP_ATTR_FORK) ? _("attr ") : "", (tmp.rm_flags & XFS_RMAP_BMBT_BLOCK) ? _("bmbt ") : "", tmp.rm_offset, agno, rm_rec->rm_startblock, (rm_rec->rm_flags & XFS_RMAP_UNWRITTEN) ? _("unwritten ") : "", rm_rec->rm_blockcount, rm_rec->rm_owner, (rm_rec->rm_flags & XFS_RMAP_ATTR_FORK) ? _("attr ") : "", (rm_rec->rm_flags & XFS_RMAP_BMBT_BLOCK) ? _("bmbt ") : "", rm_rec->rm_offset); goto next_loop; } next_loop: rm_rec = pop_slab_cursor(rm_cur); } err: if (bt_cur) libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); if (agbp) libxfs_putbuf(agbp); free_slab_cursor(&rm_cur); return 0; } /* * Compare the key fields of two rmap records -- positive if key1 > key2, * negative if key1 < key2, and zero if equal. */ __int64_t rmap_diffkeys( struct xfs_rmap_irec *kp1, struct xfs_rmap_irec *kp2) { __u64 oa; __u64 ob; __int64_t d; struct xfs_rmap_irec tmp; tmp = *kp1; tmp.rm_flags &= ~XFS_RMAP_REC_FLAGS; oa = libxfs_rmap_irec_offset_pack(&tmp); tmp = *kp2; tmp.rm_flags &= ~XFS_RMAP_REC_FLAGS; ob = libxfs_rmap_irec_offset_pack(&tmp); d = (__int64_t)kp1->rm_startblock - kp2->rm_startblock; if (d) return d; if (kp1->rm_owner > kp2->rm_owner) return 1; else if (kp2->rm_owner > kp1->rm_owner) return -1; if (oa > ob) return 1; else if (ob > oa) return -1; return 0; } /* Compute the high key of an rmap record. */ void rmap_high_key_from_rec( struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key) { int adj; adj = rec->rm_blockcount - 1; key->rm_startblock = rec->rm_startblock + adj; key->rm_owner = rec->rm_owner; key->rm_offset = rec->rm_offset; key->rm_flags = rec->rm_flags & XFS_RMAP_KEY_FLAGS; if (XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) || (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)) return; key->rm_offset += adj; } /* * Record that an inode had the reflink flag set when repair started. The * inode reflink flag will be adjusted as necessary. */ void record_inode_reflink_flag( struct xfs_mount *mp, struct xfs_dinode *dino, xfs_agnumber_t agno, xfs_agino_t ino, xfs_ino_t lino) { struct ino_tree_node *irec; int off; ASSERT(XFS_AGINO_TO_INO(mp, agno, ino) == be64_to_cpu(dino->di_ino)); if (!(be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_REFLINK)) return; irec = find_inode_rec(mp, agno, ino); off = get_inode_offset(mp, lino, irec); ASSERT(!inode_was_rl(irec, off)); set_inode_was_rl(irec, off); dbg_printf("set was_rl lino=%llu was=0x%llx\n", (unsigned long long)lino, (unsigned long long)irec->ino_was_rl); } /* * Fix an inode's reflink flag. */ static int fix_inode_reflink_flag( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino, bool set) { struct xfs_dinode *dino; struct xfs_buf *buf; if (set) do_warn( _("setting reflink flag on inode %"PRIu64"\n"), XFS_AGINO_TO_INO(mp, agno, agino)); else if (!no_modify) /* && !set */ do_warn( _("clearing reflink flag on inode %"PRIu64"\n"), XFS_AGINO_TO_INO(mp, agno, agino)); if (no_modify) return 0; buf = get_agino_buf(mp, agno, agino, &dino); if (!buf) return 1; ASSERT(XFS_AGINO_TO_INO(mp, agno, agino) == be64_to_cpu(dino->di_ino)); if (set) dino->di_flags2 |= cpu_to_be64(XFS_DIFLAG2_REFLINK); else dino->di_flags2 &= cpu_to_be64(~XFS_DIFLAG2_REFLINK); libxfs_dinode_calc_crc(mp, dino); libxfs_writebuf(buf, 0); return 0; } /* * Fix discrepancies between the state of the inode reflink flag and our * observations as to whether or not the inode really needs it. */ int fix_inode_reflink_flags( struct xfs_mount *mp, xfs_agnumber_t agno) { struct ino_tree_node *irec; int bit; __uint64_t was; __uint64_t is; __uint64_t diff; __uint64_t mask; int error = 0; xfs_agino_t agino; /* * Update the reflink flag for any inode where there's a discrepancy * between the inode flag and whether or not we found any reflinked * extents. */ for (irec = findfirst_inode_rec(agno); irec != NULL; irec = next_ino_rec(irec)) { ASSERT((irec->ino_was_rl & irec->ir_free) == 0); ASSERT((irec->ino_is_rl & irec->ir_free) == 0); was = irec->ino_was_rl; is = irec->ino_is_rl; if (was == is) continue; diff = was ^ is; dbg_printf("mismatch ino=%llu was=0x%lx is=0x%lx dif=0x%lx\n", (unsigned long long)XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum), was, is, diff); for (bit = 0, mask = 1; bit < 64; bit++, mask <<= 1) { agino = bit + irec->ino_startnum; if (!(diff & mask)) continue; else if (was & mask) error = fix_inode_reflink_flag(mp, agno, agino, false); else if (is & mask) error = fix_inode_reflink_flag(mp, agno, agino, true); else ASSERT(0); if (error) do_error( _("Unable to fix reflink flag on inode %"PRIu64".\n"), XFS_AGINO_TO_INO(mp, agno, agino)); } } return error; } /* * Return the number of refcount objects for an AG. */ size_t refcount_record_count( struct xfs_mount *mp, xfs_agnumber_t agno) { return slab_count(ag_rmaps[agno].ar_refcount_items); } /* * Return a slab cursor that will return refcount objects in order. */ int init_refcount_cursor( xfs_agnumber_t agno, struct xfs_slab_cursor **cur) { return init_slab_cursor(ag_rmaps[agno].ar_refcount_items, NULL, cur); } /* * Disable the refcount btree check. */ void refcount_avoid_check(void) { refcbt_suspect = true; } /* * Compare the observed reference counts against what's in the ag btree. */ int check_refcounts( struct xfs_mount *mp, xfs_agnumber_t agno) { struct xfs_slab_cursor *rl_cur; struct xfs_btree_cur *bt_cur = NULL; int error; int have; int i; struct xfs_buf *agbp = NULL; struct xfs_refcount_irec *rl_rec; struct xfs_refcount_irec tmp; struct xfs_perag *pag; /* per allocation group data */ if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; if (refcbt_suspect) { if (no_modify && agno == 0) do_warn(_("would rebuild corrupt refcount btrees.\n")); return 0; } /* Create cursors to refcount structures */ error = init_refcount_cursor(agno, &rl_cur); if (error) return error; error = -libxfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) goto err; /* Leave the per-ag data "uninitialized" since we rewrite it later */ pag = libxfs_perag_get(mp, agno); pag->pagf_init = 0; libxfs_perag_put(pag); bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); if (!bt_cur) { error = -ENOMEM; goto err; } rl_rec = pop_slab_cursor(rl_cur); while (rl_rec) { /* Look for a refcount record in the btree */ error = -libxfs_refcount_lookup_le(bt_cur, rl_rec->rc_startblock, &have); if (error) goto err; if (!have) { do_warn( _("Missing reference count record for (%u/%u) len %u count %u\n"), agno, rl_rec->rc_startblock, rl_rec->rc_blockcount, rl_rec->rc_refcount); goto next_loop; } error = -libxfs_refcount_get_rec(bt_cur, &tmp, &i); if (error) goto err; if (!i) { do_warn( _("Missing reference count record for (%u/%u) len %u count %u\n"), agno, rl_rec->rc_startblock, rl_rec->rc_blockcount, rl_rec->rc_refcount); goto next_loop; } /* Compare each refcount observation against the btree's */ if (tmp.rc_startblock != rl_rec->rc_startblock || tmp.rc_blockcount < rl_rec->rc_blockcount || tmp.rc_refcount < rl_rec->rc_refcount) do_warn( _("Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) len %u nlinks %u\n"), agno, tmp.rc_startblock, tmp.rc_blockcount, tmp.rc_refcount, agno, rl_rec->rc_startblock, rl_rec->rc_blockcount, rl_rec->rc_refcount); next_loop: rl_rec = pop_slab_cursor(rl_cur); } err: if (bt_cur) libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); if (agbp) libxfs_putbuf(agbp); free_slab_cursor(&rl_cur); return 0; } /* * Regenerate the AGFL so that we don't run out of it while rebuilding the * rmap btree. If skip_rmapbt is true, don't update the rmapbt (most probably * because we're updating the rmapbt). */ void fix_freelist( struct xfs_mount *mp, xfs_agnumber_t agno, bool skip_rmapbt) { xfs_alloc_arg_t args; xfs_trans_t *tp; struct xfs_trans_res tres = {0}; int flags; int error; memset(&args, 0, sizeof(args)); args.mp = mp; args.agno = agno; args.alignment = 1; args.pag = libxfs_perag_get(mp, agno); error = -libxfs_trans_alloc(mp, &tres, libxfs_alloc_min_freelist(mp, args.pag), 0, 0, &tp); if (error) do_error(_("failed to fix AGFL on AG %d, error %d\n"), agno, error); args.tp = tp; /* * Prior to rmapbt, all we had to do to fix the freelist is "expand" * the fresh AGFL header from empty to full. That hasn't changed. For * rmapbt, however, things change a bit. * * When we're stuffing the rmapbt with the AG btree rmaps the tree can * expand, so we need to keep the AGFL well-stocked for the expansion. * However, this expansion can cause the bnobt/cntbt to shrink, which * can make the AGFL eligible for shrinking. Shrinking involves * freeing rmapbt entries, but since we haven't finished loading the * rmapbt with the btree rmaps it's possible for the remove operation * to fail. The AGFL block is large enough at this point to absorb any * blocks freed from the bnobt/cntbt, so we can disable shrinking. * * During the initial AGFL regeneration during AGF generation in phase5 * we must also disable rmapbt modifications because the AGF that * libxfs reads does not yet point to the new rmapbt. These initial * AGFL entries are added just prior to adding the AG btree block rmaps * to the rmapbt. It's ok to pass NOSHRINK here too, since the AGFL is * empty and cannot shrink. */ flags = XFS_ALLOC_FLAG_NOSHRINK; if (skip_rmapbt) flags |= XFS_ALLOC_FLAG_NORMAP; error = -libxfs_alloc_fix_freelist(&args, flags); libxfs_perag_put(args.pag); if (error) { do_error(_("failed to fix AGFL on AG %d, error %d\n"), agno, error); } libxfs_trans_commit(tp); } /* * Remember how many AGFL entries came from excess AG btree allocations and * therefore already have rmap entries. */ void rmap_store_agflcount( struct xfs_mount *mp, xfs_agnumber_t agno, int count) { if (!rmap_needs_work(mp)) return; ag_rmaps[agno].ar_flcount = count; } xfsprogs-4.9.0+nmu1ubuntu2/repair/rmap.h0000644000000000000000000000540613033541503015062 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef RMAP_H_ #define RMAP_H_ extern bool collect_rmaps; extern bool rmap_needs_work(struct xfs_mount *); extern void rmaps_init(struct xfs_mount *); extern void rmaps_free(struct xfs_mount *); extern int rmap_add_rec(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *); extern int rmap_finish_collecting_fork_recs(struct xfs_mount *mp, xfs_agnumber_t agno); extern int rmap_add_ag_rec(struct xfs_mount *, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner); extern int rmap_add_bmbt_rec(struct xfs_mount *, xfs_ino_t, int, xfs_fsblock_t); extern int rmap_fold_raw_recs(struct xfs_mount *mp, xfs_agnumber_t agno); extern bool rmaps_are_mergeable(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); extern int rmap_add_fixed_ag_rec(struct xfs_mount *, xfs_agnumber_t); extern int rmap_store_ag_btree_rec(struct xfs_mount *, xfs_agnumber_t); extern size_t rmap_record_count(struct xfs_mount *, xfs_agnumber_t); extern int rmap_init_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); extern void rmap_avoid_check(void); extern int rmaps_verify_btree(struct xfs_mount *, xfs_agnumber_t); extern __int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1, struct xfs_rmap_irec *kp2); extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key); extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); extern size_t refcount_record_count(struct xfs_mount *, xfs_agnumber_t); extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); extern void refcount_avoid_check(void); extern int check_refcounts(struct xfs_mount *, xfs_agnumber_t); extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *, xfs_agnumber_t, xfs_agino_t, xfs_ino_t); extern int fix_inode_reflink_flags(struct xfs_mount *, xfs_agnumber_t); extern void fix_freelist(struct xfs_mount *, xfs_agnumber_t, bool); extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int); #endif /* RMAP_H_ */ xfsprogs-4.9.0+nmu1ubuntu2/repair/rt.c0000644000000000000000000001437713063067173014563 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "dinode.h" #include "protos.h" #include "err_protos.h" #include "rt.h" #define xfs_highbit64 libxfs_highbit64 /* for XFS_RTBLOCKLOG macro */ void rtinit(xfs_mount_t *mp) { if (mp->m_sb.sb_rblocks == 0) return; /* * realtime init -- blockmap initialization is * handled by incore_init() */ /* sumfile = calloc(mp->m_rsumsize, 1); */ if ((btmcompute = calloc(mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize, 1)) == NULL) do_error( _("couldn't allocate memory for incore realtime bitmap.\n")); if ((sumcompute = calloc(mp->m_rsumsize, 1)) == NULL) do_error( _("couldn't allocate memory for incore realtime summary info.\n")); } /* * generate the real-time bitmap and summary info based on the * incore realtime extent map. */ int generate_rtinfo(xfs_mount_t *mp, xfs_rtword_t *words, xfs_suminfo_t *sumcompute) { xfs_rtblock_t extno; xfs_rtblock_t start_ext; int bitsperblock; int bmbno; xfs_rtword_t freebit; xfs_rtword_t bits; int start_bmbno; int i; int offs; int log; int len; int in_extent; ASSERT(mp->m_rbmip == NULL); bitsperblock = mp->m_sb.sb_blocksize * NBBY; extno = start_ext = 0; bmbno = in_extent = start_bmbno = 0; /* * slower but simple, don't play around with trying to set * things one word at a time, just set bit as required. * Have to * track start and end (size) of each range of * free extents to set the summary info properly. */ while (extno < mp->m_sb.sb_rextents) { freebit = 1; *words = 0; bits = 0; for (i = 0; i < sizeof(xfs_rtword_t) * NBBY && extno < mp->m_sb.sb_rextents; i++, extno++) { if (get_rtbmap(extno) == XR_E_FREE) { sb_frextents++; bits |= freebit; if (in_extent == 0) { start_ext = extno; start_bmbno = bmbno; in_extent = 1; } } else if (in_extent == 1) { len = (int) (extno - start_ext); log = XFS_RTBLOCKLOG(len); offs = XFS_SUMOFFS(mp, log, start_bmbno); sumcompute[offs]++; in_extent = 0; } freebit <<= 1; } *words = bits; words++; if (extno % bitsperblock == 0) bmbno++; } if (in_extent == 1) { len = (int) (extno - start_ext); log = XFS_RTBLOCKLOG(len); offs = XFS_SUMOFFS(mp, log, start_bmbno); sumcompute[offs]++; } return(0); } #if 0 /* * returns 1 if bad, 0 if good */ int check_summary(xfs_mount_t *mp) { xfs_rfsblock_t bno; xfs_suminfo_t *csp; xfs_suminfo_t *fsp; int log; int error = 0; error = 0; csp = sumcompute; fsp = sumfile; for (log = 0; log < mp->m_rsumlevels; log++) { for (bno = 0; bno < mp->m_sb.sb_rbmblocks; bno++, csp++, fsp++) { if (*csp != *fsp) { do_warn( _("rt summary mismatch, size %d block %llu, file: %d, computed: %d\n"), log, bno, *fsp, *csp); error = 1; } } } return(error); } /* * examine the real-time bitmap file and compute summary * info off it. Should probably be changed to compute * the summary information off the incore computed bitmap * instead of the realtime bitmap file */ void process_rtbitmap(xfs_mount_t *mp, xfs_dinode_t *dino, blkmap_t *blkmap) { int error; int bit; int bitsperblock; int bmbno; int end_bmbno; xfs_fsblock_t bno; xfs_buf_t *bp; xfs_rtblock_t extno; int i; int len; int log; int offs; int prevbit; int start_bmbno; int start_bit; xfs_rtword_t *words; ASSERT(mp->m_rbmip == NULL); bitsperblock = mp->m_sb.sb_blocksize * NBBY; prevbit = 0; extno = 0; error = 0; end_bmbno = howmany(be64_to_cpu(dino->di_size), mp->m_sb.sb_blocksize); for (bmbno = 0; bmbno < end_bmbno; bmbno++) { bno = blkmap_get(blkmap, bmbno); if (bno == NULLFSBLOCK) { do_warn(_("can't find block %d for rtbitmap inode\n"), bmbno); error = 1; continue; } bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), XFS_FSB_TO_BB(mp, 1), NULL); if (!bp) { do_warn(_("can't read block %d for rtbitmap inode\n"), bmbno); error = 1; continue; } words = (xfs_rtword_t *)bp->b_un.b_addr; for (bit = 0; bit < bitsperblock && extno < mp->m_sb.sb_rextents; bit++, extno++) { if (xfs_isset(words, bit)) { set_rtbmap(extno, XR_E_FREE); sb_frextents++; if (prevbit == 0) { start_bmbno = bmbno; start_bit = bit; prevbit = 1; } } else if (prevbit == 1) { len = (bmbno - start_bmbno) * bitsperblock + (bit - start_bit); log = XFS_RTBLOCKLOG(len); offs = XFS_SUMOFFS(mp, log, start_bmbno); sumcompute[offs]++; prevbit = 0; } } libxfs_putbuf(bp); if (extno == mp->m_sb.sb_rextents) break; } if (prevbit == 1) { len = (bmbno - start_bmbno) * bitsperblock + (bit - start_bit); log = XFS_RTBLOCKLOG(len); offs = XFS_SUMOFFS(mp, log, start_bmbno); sumcompute[offs]++; } } /* * copy the real-time summary file data into memory */ void process_rtsummary(xfs_mount_t *mp, xfs_dinode_t *dino, blkmap_t *blkmap) { xfs_fsblock_t bno; xfs_buf_t *bp; char *bytes; int sumbno; for (sumbno = 0; sumbno < blkmap->count; sumbno++) { bno = blkmap_get(blkmap, sumbno); if (bno == NULLFSBLOCK) { do_warn(_("block %d for rtsummary inode is missing\n"), sumbno); error++; continue; } bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), XFS_FSB_TO_BB(mp, 1), NULL); if (!bp) { do_warn(_("can't read block %d for rtsummary inode\n"), sumbno); error++; continue; } bytes = bp->b_un.b_addr; memmove((char *)sumfile + sumbno * mp->m_sb.sb_blocksize, bytes, mp->m_sb.sb_blocksize); libxfs_putbuf(bp); } } #endif xfsprogs-4.9.0+nmu1ubuntu2/repair/rt.h0000644000000000000000000000206013063067173014552 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ struct blkmap; void rtinit(xfs_mount_t *mp); int generate_rtinfo(xfs_mount_t *mp, xfs_rtword_t *words, xfs_suminfo_t *sumcompute); #if 0 int check_summary(xfs_mount_t *mp); void process_rtbitmap(xfs_mount_t *mp, xfs_dinode_t *dino, struct blkmap *blkmap); void process_rtsummary(xfs_mount_t *mp, struct blkmap *blkmap); #endif xfsprogs-4.9.0+nmu1ubuntu2/repair/sb.c0000644000000000000000000004670713063067172014543 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxcmd.h" #include "libxlog.h" #include "agheader.h" #include "globals.h" #include "protos.h" #include "err_protos.h" #include "xfs_multidisk.h" #define BSIZE (1024 * 1024) /* * copy the fields of a superblock that are present in primary and * secondaries -- preserve fields that are different in the primary. */ static void copy_sb(xfs_sb_t *source, xfs_sb_t *dest) { xfs_ino_t rootino; xfs_ino_t rbmino; xfs_ino_t rsumino; xfs_ino_t uquotino; xfs_ino_t gquotino; xfs_ino_t pquotino; __uint16_t versionnum; rootino = dest->sb_rootino; rbmino = dest->sb_rbmino; rsumino = dest->sb_rsumino; uquotino = dest->sb_uquotino; gquotino = dest->sb_gquotino; pquotino = dest->sb_pquotino; versionnum = dest->sb_versionnum; *dest = *source; dest->sb_rootino = rootino; dest->sb_rbmino = rbmino; dest->sb_rsumino = rsumino; dest->sb_uquotino = uquotino; dest->sb_gquotino = gquotino; dest->sb_pquotino = pquotino; dest->sb_versionnum = versionnum; /* * copy over version bits that are stamped into all * secondaries and cannot be changed at run time in * the primary superblock */ if (xfs_sb_version_hasdalign(source)) dest->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT; if (xfs_sb_version_hasextflgbit(source)) dest->sb_versionnum |= XFS_SB_VERSION_EXTFLGBIT; /* * these are all supposed to be zero or will get reset anyway */ dest->sb_icount = 0; dest->sb_ifree = 0; dest->sb_fdblocks = 0; dest->sb_frextents = 0; memset(source->sb_fname, 0, 12); } int verify_sb_blocksize(xfs_sb_t *sb) { /* check to make sure blocksize is legal 2^N, 9 <= N <= 16 */ if (sb->sb_blocksize == 0) return XR_BAD_BLOCKSIZE; if (sb->sb_blocksize != (1 << sb->sb_blocklog)) return XR_BAD_BLOCKLOG; if (sb->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || sb->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG) return XR_BAD_BLOCKLOG; return 0; } /* * find a secondary superblock, copy it into the sb buffer. * start is the point to begin reading BSIZE bytes. * skip contains a byte-count of how far to advance for next read. */ static int __find_secondary_sb( xfs_sb_t *rsb, __uint64_t start, __uint64_t skip) { xfs_off_t off; xfs_sb_t *sb; xfs_sb_t bufsb; char *c_bufsb; int done; int i; int dirty; int retval; int bsize; sb = (xfs_sb_t *)memalign(libxfs_device_alignment(), BSIZE); if (!sb) { do_error( _("error finding secondary superblock -- failed to memalign buffer\n")); exit(1); } memset(&bufsb, 0, sizeof(xfs_sb_t)); retval = 0; dirty = 0; bsize = 0; /* * skip first sector since we know that's bad */ for (done = 0, off = start; !done ; off += skip) { /* * read disk 1 MByte at a time. */ if (lseek(x.dfd, off, SEEK_SET) != off) { done = 1; } if (!done && (bsize = read(x.dfd, sb, BSIZE)) <= 0) { done = 1; } do_warn("."); /* * check the buffer 512 bytes at a time since * we don't know how big the sectors really are. */ for (i = 0; !done && i < bsize; i += BBSIZE) { c_bufsb = (char *)sb + i; libxfs_sb_from_disk(&bufsb, (xfs_dsb_t *)c_bufsb); if (verify_sb(c_bufsb, &bufsb, 0) != XR_OK) continue; do_warn(_("found candidate secondary superblock...\n")); /* * found one. now verify it by looking * for other secondaries. */ memmove(rsb, &bufsb, sizeof(xfs_sb_t)); rsb->sb_inprogress = 0; copied_sunit = 1; if (verify_set_primary_sb(rsb, 0, &dirty) == XR_OK) { do_warn( _("verified secondary superblock...\n")); done = 1; retval = 1; } else { do_warn( _("unable to verify superblock, continuing...\n")); } } } free(sb); return retval; } static int guess_default_geometry( __uint64_t *agsize, __uint64_t *agcount, libxfs_init_t *x) { struct fs_topology ft; int blocklog; __uint64_t dblocks; int multidisk; memset(&ft, 0, sizeof(ft)); get_topology(x, &ft, 1); /* * get geometry from get_topology result. * Use default block size (2^12) */ blocklog = 12; multidisk = ft.dswidth | ft.dsunit; dblocks = x->dsize >> (blocklog - BBSHIFT); calc_default_ag_geometry(blocklog, dblocks, multidisk, agsize, agcount); return blocklog; } int find_secondary_sb(xfs_sb_t *rsb) { int retval = 0; __uint64_t agcount; __uint64_t agsize; __uint64_t skip; int blocklog; /* * Attempt to find secondary sb with a coarse approach, * first trying agblocks and blocksize read from sb, providing * they're sane. */ do_warn(_("\nattempting to find secondary superblock...\n")); if (verify_sb_blocksize(rsb) == 0) { skip = (__uint64_t)rsb->sb_agblocks * rsb->sb_blocksize; if (skip >= XFS_AG_MIN_BYTES && skip <= XFS_AG_MAX_BYTES) retval = __find_secondary_sb(rsb, skip, skip); } /* If that failed, retry coarse approach, using default geometry */ if (!retval) { blocklog = guess_default_geometry(&agsize, &agcount, &x); skip = agsize << blocklog; retval = __find_secondary_sb(rsb, skip, skip); } /* If that failed, fall back to the brute force method */ if (!retval) retval = __find_secondary_sb(rsb, XFS_AG_MIN_BYTES, BSIZE); return retval; } /* * Calculate what the inode alignment field ought to be based on internal * superblock info and determine if it is valid. * * For standard v5 superblocks, the inode alignment must either match * XFS_INODE_BIG_CLUSTER_SIZE or a multiple based on the inode size. For v5 * superblocks with sparse inode chunks enabled, inode alignment must match the * inode chunk size. * * Return true if the alignment is valid, false otherwise. */ static bool sb_validate_ino_align(struct xfs_sb *sb) { xfs_extlen_t align; if (!xfs_sb_version_hasalign(sb)) return true; /* standard cluster size alignment is always valid */ align = XFS_INODE_BIG_CLUSTER_SIZE >> sb->sb_blocklog; if (align == sb->sb_inoalignmt) return true; /* alignment scaled by inode size is v5 only for now */ if (!xfs_sb_version_hascrc(sb)) return false; align = (XFS_INODE_BIG_CLUSTER_SIZE * sb->sb_inodesize / XFS_DINODE_MIN_SIZE) >> sb->sb_blocklog; if (align == sb->sb_inoalignmt) return true; /* * Sparse inodes requires inoalignmt to match full inode chunk size and * spino_align to match the scaled alignment (as calculated above). */ if (xfs_sb_version_hassparseinodes(sb)) { if (align != sb->sb_spino_align) return false; align = (sb->sb_inodesize * XFS_INODES_PER_CHUNK) >> sb->sb_blocklog; if (align == sb->sb_inoalignmt) return true; } return false; } /* * verify a superblock -- does not verify root inode # * can only check that geometry info is internally * consistent. because of growfs, that's no guarantee * of correctness (e.g. geometry may have changed) * * fields verified or consistency checked: * * sb_magicnum * * sb_versionnum * * sb_inprogress * * sb_blocksize (as a group) * sb_blocklog * * geometry info - sb_dblocks (as a group) * sb_agcount * sb_agblocks * sb_agblklog * * inode info - sb_inodesize (x-checked with geo info) * sb_inopblock * * sector size info - * sb_sectsize * sb_sectlog * sb_logsectsize * sb_logsectlog * * not checked here - * sb_rootino * sb_fname * sb_fpack * sb_logstart * sb_uuid * * ALL real-time fields * final 4 summary counters */ int verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb) { __uint32_t bsize; int i; int ret; /* check magic number and version number */ if (sb->sb_magicnum != XFS_SB_MAGIC) return(XR_BAD_MAGIC); if (!xfs_sb_good_version(sb)) return(XR_BAD_VERSION); /* does sb think mkfs really finished ? */ if (is_primary_sb && sb->sb_inprogress == 1) return(XR_BAD_INPROGRESS); /* * before going *any further*, validate the sector size and if the * version says we should have CRCs enabled, validate that. */ /* check to make sure sectorsize is legal 2^N, 9 <= N <= 15 */ if (sb->sb_sectsize == 0) return(XR_BAD_SECT_SIZE_DATA); bsize = 1; for (i = 0; bsize < sb->sb_sectsize && i < sizeof(sb->sb_sectsize) * NBBY; i++) { bsize <<= 1; } if (i < XFS_MIN_SECTORSIZE_LOG || i > XFS_MAX_SECTORSIZE_LOG) return(XR_BAD_SECT_SIZE_DATA); /* check sb sectorsize field against sb sectlog field */ if (i != sb->sb_sectlog) return(XR_BAD_SECT_SIZE_DATA); /* sector size in range - CRC check time */ if (xfs_sb_version_hascrc(sb) && !libxfs_verify_cksum(sb_buf, sb->sb_sectsize, XFS_SB_CRC_OFF)) return XR_BAD_CRC; /* check to ensure blocksize and blocklog are legal */ ret = verify_sb_blocksize(sb); if (ret != 0) return ret; /* sanity check ag count, size fields against data size field */ if (sb->sb_dblocks == 0 || sb->sb_dblocks > ((__uint64_t)sb->sb_agcount * sb->sb_agblocks) || sb->sb_dblocks < ((__uint64_t)(sb->sb_agcount - 1) * sb->sb_agblocks + XFS_MIN_AG_BLOCKS)) return(XR_BAD_FS_SIZE_DATA); if (sb->sb_agblklog != (__uint8_t)libxfs_log2_roundup(sb->sb_agblocks)) return(XR_BAD_FS_SIZE_DATA); if (sb->sb_inodesize < XFS_DINODE_MIN_SIZE || sb->sb_inodesize > XFS_DINODE_MAX_SIZE || sb->sb_inopblock != howmany(sb->sb_blocksize,sb->sb_inodesize)) return(XR_BAD_INO_SIZE_DATA); if (xfs_sb_version_hassector(sb)) { /* check to make sure log sector is legal 2^N, 9 <= N <= 15 */ if (sb->sb_logsectsize == 0) return(XR_BAD_SECT_SIZE_DATA); bsize = 1; for (i = 0; bsize < sb->sb_logsectsize && i < sizeof(sb->sb_logsectsize) * NBBY; i++) { bsize <<= 1; } if (i < XFS_MIN_SECTORSIZE_LOG || i > XFS_MAX_SECTORSIZE_LOG) return(XR_BAD_SECT_SIZE_DATA); /* check sb log sectorsize field against sb log sectlog field */ if (i != sb->sb_logsectlog) return(XR_BAD_SECT_SIZE_DATA); } /* * real-time extent size is always set */ if (sb->sb_rextsize * sb->sb_blocksize > XFS_MAX_RTEXTSIZE) return(XR_BAD_RT_GEO_DATA); if (sb->sb_rextsize * sb->sb_blocksize < XFS_MIN_RTEXTSIZE) return(XR_BAD_RT_GEO_DATA); if (sb->sb_rblocks == 0) { if (sb->sb_rextents != 0) return(XR_BAD_RT_GEO_DATA); if (sb->sb_rbmblocks != 0) return(XR_BAD_RT_GEO_DATA); if (sb->sb_rextslog != 0) return(XR_BAD_RT_GEO_DATA); if (sb->sb_frextents != 0) return(XR_BAD_RT_GEO_DATA); } else { /* * if we have a real-time partition, sanity-check geometry */ if (sb->sb_rblocks / sb->sb_rextsize != sb->sb_rextents) return(XR_BAD_RT_GEO_DATA); if (sb->sb_rextslog != libxfs_highbit32((unsigned int)sb->sb_rextents)) return(XR_BAD_RT_GEO_DATA); if (sb->sb_rbmblocks != (xfs_extlen_t) howmany(sb->sb_rextents, NBBY * sb->sb_blocksize)) return(XR_BAD_RT_GEO_DATA); } /* * verify correctness of inode alignment if it's there */ if (!sb_validate_ino_align(sb)) return(XR_BAD_INO_ALIGN); /* * verify max. % of inodes (sb_imax_pct) */ if (sb->sb_imax_pct > 100) return(XR_BAD_INO_MAX_PCT); /* * verify stripe alignment fields if present */ if (xfs_sb_version_hasdalign(sb)) { if ((!sb->sb_unit && sb->sb_width) || (sb->sb_unit && sb->sb_agblocks % sb->sb_unit)) return(XR_BAD_SB_UNIT); if ((sb->sb_unit && !sb->sb_width) || (sb->sb_width && sb->sb_unit && sb->sb_width % sb->sb_unit)) return(XR_BAD_SB_WIDTH); } return(XR_OK); } void write_primary_sb(xfs_sb_t *sbp, int size) { xfs_dsb_t *buf; if (no_modify) return; buf = memalign(libxfs_device_alignment(), size); if (buf == NULL) { do_error(_("failed to memalign superblock buffer\n")); return; } memset(buf, 0, size); if (lseek(x.dfd, 0LL, SEEK_SET) != 0LL) { free(buf); do_error(_("couldn't seek to offset 0 in filesystem\n")); } libxfs_sb_to_disk(buf, sbp); if (xfs_sb_version_hascrc(sbp)) xfs_update_cksum((char *)buf, size, XFS_SB_CRC_OFF); if (write(x.dfd, buf, size) != size) { free(buf); do_error(_("primary superblock write failed!\n")); } free(buf); } /* * get a possible superblock -- checks for internal consistency */ int get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno) { int error, rval; xfs_dsb_t *buf; buf = memalign(libxfs_device_alignment(), size); if (buf == NULL) { do_error( _("error reading superblock %u -- failed to memalign buffer\n"), agno); exit(1); } memset(buf, 0, size); memset(sbp, 0, sizeof(*sbp)); /* try and read it first */ if (lseek(x.dfd, off, SEEK_SET) != off) { do_warn( _("error reading superblock %u -- seek to offset %" PRId64 " failed\n"), agno, off); free(buf); return(XR_EOF); } if ((rval = read(x.dfd, buf, size)) != size) { error = errno; do_warn( _("superblock read failed, offset %" PRId64 ", size %d, ag %u, rval %d\n"), off, size, agno, rval); do_error("%s\n", strerror(error)); } libxfs_sb_from_disk(sbp, buf); rval = verify_sb((char *)buf, sbp, agno == 0); free(buf); return rval; } /* returns element on list with highest reference count */ static fs_geo_list_t * get_best_geo(fs_geo_list_t *list) { int cnt = 0; fs_geo_list_t *current, *rval = NULL; current = list; while (current != NULL) { if (current->refs > cnt) { rval = current; cnt = current->refs; } current = current->next; } return(rval); } /* adds geometry info to linked list. returns (sometimes new) head of list */ static fs_geo_list_t * add_geo(fs_geo_list_t *list, fs_geometry_t *geo_p, int index) { fs_geo_list_t *current = list; while (current != NULL) { if (memcmp(geo_p, ¤t->geo, sizeof(fs_geometry_t)) == 0) { current->refs++; return(list); } current = current->next; } if ((current = malloc(sizeof(fs_geo_list_t))) == NULL) { do_error(_("couldn't malloc geometry structure\n")); exit(1); } current->geo = *geo_p; current->refs = 1; current->next = list; current->index = index; return(current); } static void free_geo(fs_geo_list_t *list) { fs_geo_list_t *next; fs_geo_list_t *current; for (current = list; current != NULL; current = next) { next = current->next; free(current); } } void get_sb_geometry(fs_geometry_t *geo, xfs_sb_t *sbp) { memset(geo, 0, sizeof(fs_geometry_t)); /* * blindly set fields that we know are always good */ geo->sb_blocksize = sbp->sb_blocksize; geo->sb_dblocks = sbp->sb_dblocks; geo->sb_rblocks = sbp->sb_rblocks; geo->sb_rextents = sbp->sb_rextents; geo->sb_logstart = sbp->sb_logstart; geo->sb_rextsize = sbp->sb_rextsize; geo->sb_agblocks = sbp->sb_agblocks; geo->sb_agcount = sbp->sb_agcount; geo->sb_rbmblocks = sbp->sb_rbmblocks; geo->sb_logblocks = sbp->sb_logblocks; geo->sb_sectsize = sbp->sb_sectsize; geo->sb_inodesize = sbp->sb_inodesize; if (xfs_sb_version_hasalign(sbp)) geo->sb_ialignbit = 1; if (xfs_sb_version_hasdalign(sbp)) geo->sb_salignbit = 1; if (xfs_sb_version_hasextflgbit(sbp)) geo->sb_extflgbit = 1; geo->sb_fully_zeroed = 1; } /* * the way to verify that a primary sb is consistent with the * filesystem is find the secondaries given the info in the * primary and compare the geometries in the secondaries against * the geometry indicated by the primary. * * returns 0 if ok, else error code (XR_EOF, XR_INSUFF_SEC_SB, etc). */ int verify_set_primary_sb(xfs_sb_t *rsb, int sb_index, int *sb_modified) { xfs_off_t off; fs_geometry_t geo; xfs_sb_t *sb; fs_geo_list_t *list; fs_geo_list_t *current; xfs_agnumber_t agno; int num_sbs; int size; int num_ok; int retval; /* * We haven't been able to validate the sector size yet properly * (e.g. in the case of repairing an image in a file), so we need to * take into account sector mismatches and so use the maximum possible * sector size rather than the sector size in @rsb. */ size = NUM_AGH_SECTS * (1 << (XFS_MAX_SECTORSIZE_LOG)); list = NULL; num_ok = 0; *sb_modified = 0; num_sbs = rsb->sb_agcount; sb = (xfs_sb_t *) alloc_ag_buf(size); /* * put the primary sb geometry info onto the geometry list */ get_sb_geometry(&geo, rsb); list = add_geo(list, &geo, sb_index); /* * scan the secondaries and check them off as we get them so we only * process each one once */ for (agno = 1; agno < rsb->sb_agcount; agno++) { off = (xfs_off_t)agno * rsb->sb_agblocks << rsb->sb_blocklog; retval = get_sb(sb, off, size, agno); if (retval == XR_EOF) goto out_free_list; if (retval == XR_OK) { /* * save away geometry info. don't bother checking the * sb against the agi/agf as the odds of the sb being * corrupted in a way that it is internally consistent * but not consistent with the rest of the filesystem is * really really low. */ get_sb_geometry(&geo, sb); list = add_geo(list, &geo, agno); num_ok++; } } /* * see if we have enough superblocks to bother with */ retval = 0; if (num_ok < num_sbs / 2) { retval = XR_INSUFF_SEC_SB; goto out_free_list; } current = get_best_geo(list); /* * check that enough sbs agree that we're willing to * go with this geometry. if not, print out the * geometry and a message about the force option. */ switch (num_sbs) { case 2: /* * If we only have two allocation groups, and the superblock * in the second allocation group differs from the primary * superblock we can't verify the geometry information. * Warn the user about this situation and get out unless * explicitly overridden. */ if (current->refs != 2) { if (!force_geo) { do_warn( _("Only two AGs detected and they do not match - " "cannot validate filesystem geometry.\n" "Use the -o force_geometry option to proceed.\n")); exit(1); } } goto out_free_list; case 1: /* * If we only have a single allocation group there is no * secondary superblock that we can use to verify the geometry * information. Warn the user about this situation and get * out unless explicitly overridden. */ if (!force_geo) { do_warn( _("Only one AG detected - " "cannot validate filesystem geometry.\n" "Use the -o force_geometry option to proceed.\n")); exit(1); } goto out_free_list; default: /* * at least half of the probed superblocks have * to agree. if they don't, this fs is probably * too far gone anyway considering the fact that * XFS normally doesn't alter the secondary superblocks. */ if (current->refs < num_sbs / 2) { do_warn( _("Not enough matching superblocks - cannot proceed.\n")); exit(1); } } /* * set the geometry into primary superblock if necessary. */ if (current->index != sb_index) { *sb_modified = 1; off = (xfs_off_t)current->index * current->geo.sb_agblocks * current->geo.sb_blocksize; if (get_sb(sb, off, current->geo.sb_sectsize, current->index) != XR_OK) do_error(_("could not read superblock\n")); copy_sb(sb, rsb); /* * turn off inprogress bit since this is the primary. * also save away values that we need to ensure are * consistent in the other secondaries. */ rsb->sb_inprogress = 0; sb_inoalignmt = sb->sb_inoalignmt; sb_unit = sb->sb_unit; sb_width = sb->sb_width; } out_free_list: free_geo(list); free(sb); return retval; } xfsprogs-4.9.0+nmu1ubuntu2/repair/scan.c0000644000000000000000000020210413063067172015044 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "avl.h" #include "globals.h" #include "agheader.h" #include "incore.h" #include "protos.h" #include "err_protos.h" #include "dinode.h" #include "scan.h" #include "versions.h" #include "bmap.h" #include "progress.h" #include "threads.h" #include "slab.h" #include "rmap.h" static xfs_mount_t *mp = NULL; /* * Variables to validate AG header values against the manual count * from the btree traversal. */ struct aghdr_cnts { xfs_agnumber_t agno; xfs_extlen_t agffreeblks; xfs_extlen_t agflongest; __uint64_t agfbtreeblks; __uint32_t agicount; __uint32_t agifreecount; __uint64_t fdblocks; __uint64_t usedblocks; __uint64_t ifreecount; __uint32_t fibtfreecount; }; void set_mp(xfs_mount_t *mpp) { libxfs_bcache_purge(); mp = mpp; } static void scan_sbtree( xfs_agblock_t root, int nlevels, xfs_agnumber_t agno, int suspect, void (*func)(struct xfs_btree_block *block, int level, xfs_agblock_t bno, xfs_agnumber_t agno, int suspect, int isroot, __uint32_t magic, void *priv), int isroot, __uint32_t magic, void *priv, const struct xfs_buf_ops *ops) { xfs_buf_t *bp; bp = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, root), XFS_FSB_TO_BB(mp, 1), 0, ops); if (!bp) { do_error(_("can't read btree block %d/%d\n"), agno, root); return; } if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) { do_warn(_("btree block %d/%d is suspect, error %d\n"), agno, root, bp->b_error); suspect = 1; } (*func)(XFS_BUF_TO_BLOCK(bp), nlevels - 1, root, agno, suspect, isroot, magic, priv); libxfs_putbuf(bp); } /* * returns 1 on bad news (inode needs to be cleared), 0 on good */ int scan_lbtree( xfs_fsblock_t root, int nlevels, int (*func)(struct xfs_btree_block *block, int level, int type, int whichfork, xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, __uint64_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, __uint64_t magic), int type, int whichfork, xfs_ino_t ino, xfs_rfsblock_t *tot, __uint64_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, __uint64_t magic, const struct xfs_buf_ops *ops) { xfs_buf_t *bp; int err; int dirty = 0; bool badcrc = false; bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, root), XFS_FSB_TO_BB(mp, 1), 0, ops); if (!bp) { do_error(_("can't read btree block %d/%d\n"), XFS_FSB_TO_AGNO(mp, root), XFS_FSB_TO_AGBNO(mp, root)); return(1); } /* * only check for bad CRC here - caller will determine if there * is a corruption or not and whether it got corrected and so needs * writing back. CRC errors always imply we need to write the block. */ if (bp->b_error == -EFSBADCRC) { do_warn(_("btree block %d/%d is suspect, error %d\n"), XFS_FSB_TO_AGNO(mp, root), XFS_FSB_TO_AGBNO(mp, root), bp->b_error); badcrc = true; } err = (*func)(XFS_BUF_TO_BLOCK(bp), nlevels - 1, type, whichfork, root, ino, tot, nex, blkmapp, bm_cursor, isroot, check_dups, &dirty, magic); ASSERT(dirty == 0 || (dirty && !no_modify)); if ((dirty || badcrc) && !no_modify) libxfs_writebuf(bp, 0); else libxfs_putbuf(bp); return(err); } int scan_bmapbt( struct xfs_btree_block *block, int level, int type, int whichfork, xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, __uint64_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, __uint64_t magic) { int i; int err; xfs_bmbt_ptr_t *pp; xfs_bmbt_key_t *pkey; xfs_bmbt_rec_t *rp; xfs_fileoff_t first_key; xfs_fileoff_t last_key; char *forkname = get_forkname(whichfork); int numrecs; xfs_agnumber_t agno; xfs_agblock_t agbno; int state; int error; /* * unlike the ag freeblock btrees, if anything looks wrong * in an inode bmap tree, just bail. it's possible that * we'll miss a case where the to-be-toasted inode and * another inode are claiming the same block but that's * highly unlikely. */ if (be32_to_cpu(block->bb_magic) != magic) { do_warn( _("bad magic # %#x in inode %" PRIu64 " (%s fork) bmbt block %" PRIu64 "\n"), be32_to_cpu(block->bb_magic), ino, forkname, bno); return(1); } if (be16_to_cpu(block->bb_level) != level) { do_warn( _("expected level %d got %d in inode %" PRIu64 ", (%s fork) bmbt block %" PRIu64 "\n"), level, be16_to_cpu(block->bb_level), ino, forkname, bno); return(1); } if (magic == XFS_BMAP_CRC_MAGIC) { /* verify owner */ if (be64_to_cpu(block->bb_u.l.bb_owner) != ino) { do_warn( _("expected owner inode %" PRIu64 ", got %llu, bmbt block %" PRIu64 "\n"), ino, be64_to_cpu(block->bb_u.l.bb_owner), bno); return 1; } /* verify block number */ if (be64_to_cpu(block->bb_u.l.bb_blkno) != XFS_FSB_TO_DADDR(mp, bno)) { do_warn( _("expected block %" PRIu64 ", got %llu, bmbt block %" PRIu64 "\n"), XFS_FSB_TO_DADDR(mp, bno), be64_to_cpu(block->bb_u.l.bb_blkno), bno); return 1; } /* verify uuid */ if (platform_uuid_compare(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid) != 0) { do_warn( _("wrong FS UUID, bmbt block %" PRIu64 "\n"), bno); return 1; } } if (check_dups == 0) { /* * check sibling pointers. if bad we have a conflict * between the sibling pointers and the child pointers * in the parent block. blow out the inode if that happens */ if (bm_cursor->level[level].fsbno != NULLFSBLOCK) { /* * this is not the first block on this level * so the cursor for this level has recorded the * values for this's block left-sibling. */ if (bno != bm_cursor->level[level].right_fsbno) { do_warn( _("bad fwd (right) sibling pointer (saw %" PRIu64 " parent block says %" PRIu64 ")\n" "\tin inode %" PRIu64 " (%s fork) bmap btree block %" PRIu64 "\n"), bm_cursor->level[level].right_fsbno, bno, ino, forkname, bm_cursor->level[level].fsbno); return(1); } if (be64_to_cpu(block->bb_u.l.bb_leftsib) != bm_cursor->level[level].fsbno) { do_warn( _("bad back (left) sibling pointer (saw %llu parent block says %" PRIu64 ")\n" "\tin inode %" PRIu64 " (%s fork) bmap btree block %" PRIu64 "\n"), (unsigned long long) be64_to_cpu(block->bb_u.l.bb_leftsib), bm_cursor->level[level].fsbno, ino, forkname, bno); return(1); } } else { /* * This is the first or only block on this level. * Check that the left sibling pointer is NULL */ if (be64_to_cpu(block->bb_u.l.bb_leftsib) != NULLFSBLOCK) { do_warn( _("bad back (left) sibling pointer (saw %llu should be NULL (0))\n" "\tin inode %" PRIu64 " (%s fork) bmap btree block %" PRIu64 "\n"), (unsigned long long) be64_to_cpu(block->bb_u.l.bb_leftsib), ino, forkname, bno); return(1); } } /* * update cursor block pointers to reflect this block */ bm_cursor->level[level].fsbno = bno; bm_cursor->level[level].left_fsbno = be64_to_cpu(block->bb_u.l.bb_leftsib); bm_cursor->level[level].right_fsbno = be64_to_cpu(block->bb_u.l.bb_rightsib); agno = XFS_FSB_TO_AGNO(mp, bno); agbno = XFS_FSB_TO_AGBNO(mp, bno); pthread_mutex_lock(&ag_locks[agno].lock); state = get_bmap(agno, agbno); switch (state) { case XR_E_INUSE1: /* * block was claimed as in use data by the rmap * btree, but has not been found in the data extent * map for the inode. That means this bmbt block hasn't * yet been claimed as in use, which means -it's ours- */ case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: set_bmap(agno, agbno, XR_E_INUSE); break; case XR_E_FS_MAP: case XR_E_INUSE: /* * we'll try and continue searching here since * the block looks like it's been claimed by file * to store user data, a directory to store directory * data, or the space allocation btrees but since * we made it here, the block probably * contains btree data. */ set_bmap(agno, agbno, XR_E_MULT); do_warn( _("inode 0x%" PRIx64 "bmap block 0x%" PRIx64 " claimed, state is %d\n"), ino, bno, state); break; case XR_E_MULT: case XR_E_INUSE_FS: set_bmap(agno, agbno, XR_E_MULT); do_warn( _("inode 0x%" PRIx64 " bmap block 0x%" PRIx64 " claimed, state is %d\n"), ino, bno, state); /* * if we made it to here, this is probably a bmap block * that is being used by *another* file as a bmap block * so the block will be valid. Both files should be * trashed along with any other file that impinges on * any blocks referenced by either file. So we * continue searching down this btree to mark all * blocks duplicate */ break; case XR_E_BAD_STATE: default: do_warn( _("bad state %d, inode %" PRIu64 " bmap block 0x%" PRIx64 "\n"), state, ino, bno); break; } pthread_mutex_unlock(&ag_locks[agno].lock); } else { /* * attribute fork for realtime files is in the regular * filesystem */ if (type != XR_INO_RTDATA || whichfork != XFS_DATA_FORK) { if (search_dup_extent(XFS_FSB_TO_AGNO(mp, bno), XFS_FSB_TO_AGBNO(mp, bno), XFS_FSB_TO_AGBNO(mp, bno) + 1)) return(1); } else { if (search_rt_dup_extent(mp, bno)) return(1); } } (*tot)++; numrecs = be16_to_cpu(block->bb_numrecs); /* Record BMBT blocks in the reverse-mapping data. */ if (check_dups && collect_rmaps) { error = rmap_add_bmbt_rec(mp, ino, whichfork, bno); if (error) do_error( _("couldn't add inode %"PRIu64" bmbt block %"PRIu64" reverse-mapping data."), ino, bno); } if (level == 0) { if (numrecs > mp->m_bmap_dmxr[0] || (isroot == 0 && numrecs < mp->m_bmap_dmnr[0])) { do_warn( _("inode %" PRIu64 " bad # of bmap records (%u, min - %u, max - %u)\n"), ino, numrecs, mp->m_bmap_dmnr[0], mp->m_bmap_dmxr[0]); return(1); } rp = XFS_BMBT_REC_ADDR(mp, block, 1); *nex += numrecs; /* * XXX - if we were going to fix up the btree record, * we'd do it right here. For now, if there's a problem, * we'll bail out and presumably clear the inode. */ if (check_dups == 0) { err = process_bmbt_reclist(mp, rp, &numrecs, type, ino, tot, blkmapp, &first_key, &last_key, whichfork); if (err) return 1; /* * check that key ordering is monotonically increasing. * if the last_key value in the cursor is set to * NULLFILEOFF, then we know this is the first block * on the leaf level and we shouldn't check the * last_key value. */ if (first_key <= bm_cursor->level[level].last_key && bm_cursor->level[level].last_key != NULLFILEOFF) { do_warn( _("out-of-order bmap key (file offset) in inode %" PRIu64 ", %s fork, fsbno %" PRIu64 "\n"), ino, forkname, bno); return(1); } /* * update cursor keys to reflect this block. * don't have to check if last_key is > first_key * since that gets checked by process_bmbt_reclist. */ bm_cursor->level[level].first_key = first_key; bm_cursor->level[level].last_key = last_key; return 0; } else { return scan_bmbt_reclist(mp, rp, &numrecs, type, ino, tot, whichfork); } } if (numrecs > mp->m_bmap_dmxr[1] || (isroot == 0 && numrecs < mp->m_bmap_dmnr[1])) { do_warn( _("inode %" PRIu64 " bad # of bmap records (%u, min - %u, max - %u)\n"), ino, numrecs, mp->m_bmap_dmnr[1], mp->m_bmap_dmxr[1]); return(1); } pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); pkey = XFS_BMBT_KEY_ADDR(mp, block, 1); last_key = NULLFILEOFF; for (i = 0, err = 0; i < numrecs; i++) { /* * XXX - if we were going to fix up the interior btree nodes, * we'd do it right here. For now, if there's a problem, * we'll bail out and presumably clear the inode. */ if (!verify_dfsbno(mp, be64_to_cpu(pp[i]))) { do_warn( _("bad bmap btree ptr 0x%llx in ino %" PRIu64 "\n"), (unsigned long long) be64_to_cpu(pp[i]), ino); return(1); } err = scan_lbtree(be64_to_cpu(pp[i]), level, scan_bmapbt, type, whichfork, ino, tot, nex, blkmapp, bm_cursor, 0, check_dups, magic, &xfs_bmbt_buf_ops); if (err) return(1); /* * fix key (offset) mismatches between the first key * in the child block (as recorded in the cursor) and the * key in the interior node referencing the child block. * * fixes cases where entries have been shifted between * child blocks but the parent hasn't been updated. We * don't have to worry about the key values in the cursor * not being set since we only look at the key values of * our child and those are guaranteed to be set by the * call to scan_lbtree() above. */ if (check_dups == 0 && be64_to_cpu(pkey[i].br_startoff) != bm_cursor->level[level-1].first_key) { if (!no_modify) { do_warn( _("correcting bt key (was %llu, now %" PRIu64 ") in inode %" PRIu64 "\n" "\t\t%s fork, btree block %" PRIu64 "\n"), (unsigned long long) be64_to_cpu(pkey[i].br_startoff), bm_cursor->level[level-1].first_key, ino, forkname, bno); *dirty = 1; pkey[i].br_startoff = cpu_to_be64( bm_cursor->level[level-1].first_key); } else { do_warn( _("bad btree key (is %llu, should be %" PRIu64 ") in inode %" PRIu64 "\n" "\t\t%s fork, btree block %" PRIu64 "\n"), (unsigned long long) be64_to_cpu(pkey[i].br_startoff), bm_cursor->level[level-1].first_key, ino, forkname, bno); } } } /* * If we're the last node at our level, check that the last child * block's forward sibling pointer is NULL. */ if (check_dups == 0 && bm_cursor->level[level].right_fsbno == NULLFSBLOCK && bm_cursor->level[level - 1].right_fsbno != NULLFSBLOCK) { do_warn( _("bad fwd (right) sibling pointer (saw %" PRIu64 " should be NULLFSBLOCK)\n" "\tin inode %" PRIu64 " (%s fork) bmap btree block %" PRIu64 "\n"), bm_cursor->level[level - 1].right_fsbno, ino, forkname, bm_cursor->level[level - 1].fsbno); return(1); } /* * update cursor keys to reflect this block */ if (check_dups == 0) { bm_cursor->level[level].first_key = be64_to_cpu(pkey[0].br_startoff); bm_cursor->level[level].last_key = be64_to_cpu(pkey[numrecs - 1].br_startoff); } return(0); } static void scan_allocbt( struct xfs_btree_block *block, int level, xfs_agblock_t bno, xfs_agnumber_t agno, int suspect, int isroot, __uint32_t magic, void *priv) { struct aghdr_cnts *agcnts = priv; const char *name; int i; xfs_alloc_ptr_t *pp; xfs_alloc_rec_t *rp; int hdr_errors = 0; int numrecs; int state; xfs_extlen_t lastcount = 0; xfs_agblock_t lastblock = 0; switch (magic) { case XFS_ABTB_CRC_MAGIC: case XFS_ABTB_MAGIC: name = "bno"; break; case XFS_ABTC_CRC_MAGIC: case XFS_ABTC_MAGIC: name = "cnt"; break; default: name = "(unknown)"; assert(0); break; } if (be32_to_cpu(block->bb_magic) != magic) { do_warn(_("bad magic # %#x in bt%s block %d/%d\n"), be32_to_cpu(block->bb_magic), name, agno, bno); hdr_errors++; if (suspect) return; } /* * All freespace btree blocks except the roots are freed for a * fully used filesystem, thus they are counted towards the * free data block counter. */ if (!isroot) { agcnts->agfbtreeblks++; agcnts->fdblocks++; } if (be16_to_cpu(block->bb_level) != level) { do_warn(_("expected level %d got %d in bt%s block %d/%d\n"), level, be16_to_cpu(block->bb_level), name, agno, bno); hdr_errors++; if (suspect) return; } /* * check for btree blocks multiply claimed */ state = get_bmap(agno, bno); if (state != XR_E_UNKNOWN) { set_bmap(agno, bno, XR_E_MULT); do_warn( _("%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), name, state, agno, bno, suspect); return; } set_bmap(agno, bno, XR_E_FS_MAP); numrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (numrecs > mp->m_alloc_mxr[0]) { numrecs = mp->m_alloc_mxr[0]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_alloc_mnr[0]) { numrecs = mp->m_alloc_mnr[0]; hdr_errors++; } if (hdr_errors) { do_warn( _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_alloc_mnr[0], mp->m_alloc_mxr[0], name, agno, bno); suspect++; } rp = XFS_ALLOC_REC_ADDR(mp, block, 1); for (i = 0; i < numrecs; i++) { xfs_agblock_t b, end; xfs_extlen_t len, blen; b = be32_to_cpu(rp[i].ar_startblock); len = be32_to_cpu(rp[i].ar_blockcount); end = b + len; if (b == 0 || !verify_agbno(mp, agno, b)) { do_warn( _("invalid start block %u in record %u of %s btree block %u/%u\n"), b, i, name, agno, bno); continue; } if (len == 0 || !verify_agbno(mp, agno, end - 1)) { do_warn( _("invalid length %u in record %u of %s btree block %u/%u\n"), len, i, name, agno, bno); continue; } if (magic == XFS_ABTB_MAGIC || magic == XFS_ABTB_CRC_MAGIC) { if (b <= lastblock) { do_warn(_( "out-of-order bno btree record %d (%u %u) block %u/%u\n"), i, b, len, agno, bno); } else { lastblock = b; } } else { agcnts->fdblocks += len; agcnts->agffreeblks += len; if (len > agcnts->agflongest) agcnts->agflongest = len; if (len < lastcount) { do_warn(_( "out-of-order cnt btree record %d (%u %u) block %u/%u\n"), i, b, len, agno, bno); } else { lastcount = len; } } for ( ; b < end; b += blen) { state = get_bmap_ext(agno, b, end, &blen); switch (state) { case XR_E_UNKNOWN: set_bmap(agno, b, XR_E_FREE1); break; case XR_E_FREE1: /* * no warning messages -- we'll catch * FREE1 blocks later */ if (magic == XFS_ABTC_MAGIC || magic == XFS_ABTC_CRC_MAGIC) { set_bmap_ext(agno, b, blen, XR_E_FREE); break; } default: do_warn( _("block (%d,%d-%d) multiply claimed by %s space tree, state - %d\n"), agno, b, b + blen - 1, name, state); break; } } } return; } /* * interior record */ pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); if (numrecs > mp->m_alloc_mxr[1]) { numrecs = mp->m_alloc_mxr[1]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_alloc_mnr[1]) { numrecs = mp->m_alloc_mnr[1]; hdr_errors++; } /* * don't pass bogus tree flag down further if this block * looked ok. bail out if two levels in a row look bad. */ if (hdr_errors) { do_warn( _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_alloc_mnr[1], mp->m_alloc_mxr[1], name, agno, bno); if (suspect) return; suspect++; } else if (suspect) { suspect = 0; } for (i = 0; i < numrecs; i++) { xfs_agblock_t bno = be32_to_cpu(pp[i]); /* * XXX - put sibling detection right here. * we know our sibling chain is good. So as we go, * we check the entry before and after each entry. * If either of the entries references a different block, * check the sibling pointer. If there's a sibling * pointer mismatch, try and extract as much data * as possible. */ if (bno != 0 && verify_agbno(mp, agno, bno)) { switch (magic) { case XFS_ABTB_CRC_MAGIC: case XFS_ABTB_MAGIC: scan_sbtree(bno, level, agno, suspect, scan_allocbt, 0, magic, priv, &xfs_allocbt_buf_ops); break; case XFS_ABTC_CRC_MAGIC: case XFS_ABTC_MAGIC: scan_sbtree(bno, level, agno, suspect, scan_allocbt, 0, magic, priv, &xfs_allocbt_buf_ops); break; } } } } static bool ino_issparse( struct xfs_inobt_rec *rp, int offset) { if (!xfs_sb_version_hassparseinodes(&mp->m_sb)) return false; return xfs_inobt_is_sparse_disk(rp, offset); } /* See if the rmapbt owners agree with our observations. */ static void process_rmap_rec( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t b, xfs_agblock_t end, xfs_extlen_t blen, int64_t owner, int state, const char *name) { switch (state) { case XR_E_UNKNOWN: switch (owner) { case XFS_RMAP_OWN_FS: case XFS_RMAP_OWN_LOG: set_bmap_ext(agno, b, blen, XR_E_INUSE_FS1); break; case XFS_RMAP_OWN_AG: case XFS_RMAP_OWN_INOBT: set_bmap_ext(agno, b, blen, XR_E_FS_MAP1); break; case XFS_RMAP_OWN_INODES: set_bmap_ext(agno, b, blen, XR_E_INO1); break; case XFS_RMAP_OWN_REFC: set_bmap_ext(agno, b, blen, XR_E_REFC); break; case XFS_RMAP_OWN_COW: set_bmap_ext(agno, b, blen, XR_E_COW); break; case XFS_RMAP_OWN_NULL: /* still unknown */ break; default: /* file data */ set_bmap_ext(agno, b, blen, XR_E_INUSE1); break; } break; case XR_E_INUSE_FS: if (owner == XFS_RMAP_OWN_FS || owner == XFS_RMAP_OWN_LOG) break; do_warn( _("Static meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), agno, b, b + blen - 1, name, state, owner); break; case XR_E_FS_MAP: if (owner == XFS_RMAP_OWN_AG || owner == XFS_RMAP_OWN_INOBT) break; do_warn( _("AG meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), agno, b, b + blen - 1, name, state, owner); break; case XR_E_INO: if (owner == XFS_RMAP_OWN_INODES) break; do_warn( _("inode block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), agno, b, b + blen - 1, name, state, owner); break; case XR_E_REFC: if (owner == XFS_RMAP_OWN_REFC) break; do_warn( _("AG refcount block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), agno, b, b + blen - 1, name, state, owner); break; case XR_E_INUSE: if (owner >= 0 && owner < mp->m_sb.sb_dblocks) break; do_warn( _("in use block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), agno, b, b + blen - 1, name, state, owner); break; case XR_E_FREE1: case XR_E_FREE: /* * May be on the AGFL. If not, they'll * be caught later. */ break; case XR_E_INUSE1: /* * multiple inode owners are ok with * reflink enabled */ if (xfs_sb_version_hasreflink(&mp->m_sb) && !XFS_RMAP_NON_INODE_OWNER(owner)) break; /* fall through */ default: do_warn( _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), agno, b, b + blen - 1, name, state, owner); break; } } struct rmap_priv { struct aghdr_cnts *agcnts; struct xfs_rmap_irec high_key; struct xfs_rmap_irec last_rec; xfs_agblock_t nr_blocks; }; static bool rmap_in_order( xfs_agblock_t b, xfs_agblock_t lastblock, uint64_t owner, uint64_t lastowner, uint64_t offset, uint64_t lastoffset) { if (b > lastblock) return true; else if (b < lastblock) return false; if (owner > lastowner) return true; else if (owner < lastowner) return false; return offset > lastoffset; } static void scan_rmapbt( struct xfs_btree_block *block, int level, xfs_agblock_t bno, xfs_agnumber_t agno, int suspect, int isroot, __uint32_t magic, void *priv) { const char *name = "rmap"; int i; xfs_rmap_ptr_t *pp; struct xfs_rmap_rec *rp; struct rmap_priv *rmap_priv = priv; int hdr_errors = 0; int numrecs; int state; xfs_agblock_t lastblock = 0; uint64_t lastowner = 0; uint64_t lastoffset = 0; struct xfs_rmap_key *kp; struct xfs_rmap_irec key = {0}; if (magic != XFS_RMAP_CRC_MAGIC) { name = "(unknown)"; hdr_errors++; suspect++; goto out; } if (be32_to_cpu(block->bb_magic) != magic) { do_warn(_("bad magic # %#x in bt%s block %d/%d\n"), be32_to_cpu(block->bb_magic), name, agno, bno); hdr_errors++; if (suspect) goto out; } /* * All RMAP btree blocks except the roots are freed for a * fully empty filesystem, thus they are counted towards the * free data block counter. */ if (!isroot) { rmap_priv->agcnts->agfbtreeblks++; rmap_priv->agcnts->fdblocks++; } rmap_priv->nr_blocks++; if (be16_to_cpu(block->bb_level) != level) { do_warn(_("expected level %d got %d in bt%s block %d/%d\n"), level, be16_to_cpu(block->bb_level), name, agno, bno); hdr_errors++; if (suspect) goto out; } /* check for btree blocks multiply claimed */ state = get_bmap(agno, bno); if (!(state == XR_E_UNKNOWN || state == XR_E_FS_MAP1)) { set_bmap(agno, bno, XR_E_MULT); do_warn( _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), name, state, agno, bno, suspect); goto out; } set_bmap(agno, bno, XR_E_FS_MAP); numrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (numrecs > mp->m_rmap_mxr[0]) { numrecs = mp->m_rmap_mxr[0]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_rmap_mnr[0]) { numrecs = mp->m_rmap_mnr[0]; hdr_errors++; } if (hdr_errors) { do_warn( _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_rmap_mnr[0], mp->m_rmap_mxr[0], name, agno, bno); suspect++; } rp = XFS_RMAP_REC_ADDR(block, 1); for (i = 0; i < numrecs; i++) { xfs_agblock_t b, end; xfs_extlen_t len, blen; int64_t owner, offset; b = be32_to_cpu(rp[i].rm_startblock); len = be32_to_cpu(rp[i].rm_blockcount); owner = be64_to_cpu(rp[i].rm_owner); offset = be64_to_cpu(rp[i].rm_offset); key.rm_flags = 0; key.rm_startblock = b; key.rm_blockcount = len; key.rm_owner = owner; if (libxfs_rmap_irec_offset_unpack(offset, &key)) { /* Look for impossible flags. */ do_warn( _("invalid flags in record %u of %s btree block %u/%u\n"), i, name, agno, bno); continue; } end = key.rm_startblock + key.rm_blockcount; /* Make sure agbno & len make sense. */ if (!verify_agbno(mp, agno, b)) { do_warn( _("invalid start block %u in record %u of %s btree block %u/%u\n"), b, i, name, agno, bno); continue; } if (len == 0 || !verify_agbno(mp, agno, end - 1)) { do_warn( _("invalid length %u in record %u of %s btree block %u/%u\n"), len, i, name, agno, bno); continue; } /* Look for impossible owners. */ if (!((owner > XFS_RMAP_OWN_MIN && owner <= XFS_RMAP_OWN_FS) || (XFS_INO_TO_AGNO(mp, owner) < mp->m_sb.sb_agcount && XFS_AGINO_TO_AGBNO(mp, XFS_INO_TO_AGINO(mp, owner)) < mp->m_sb.sb_agblocks))) do_warn( _("invalid owner in rmap btree record %d (%"PRId64" %u) block %u/%u\n"), i, owner, len, agno, bno); /* Look for impossible record field combinations. */ if (XFS_RMAP_NON_INODE_OWNER(key.rm_owner)) { if (key.rm_flags) do_warn( _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with flags\n"), i, agno, bno, name); if (key.rm_offset) do_warn( _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with offset\n"), i, agno, bno, name); } /* Check for out of order records. */ if (i == 0) { advance: lastblock = b; lastowner = owner; lastoffset = offset; } else { bool bad; if (xfs_sb_version_hasreflink(&mp->m_sb)) bad = !rmap_in_order(b, lastblock, owner, lastowner, offset, lastoffset); else bad = b <= lastblock; if (bad) do_warn( _("out-of-order rmap btree record %d (%u %"PRId64" %"PRIx64" %u) block %u/%u\n"), i, b, owner, offset, len, agno, bno); else goto advance; } /* Is this mergeable with the previous record? */ if (rmaps_are_mergeable(&rmap_priv->last_rec, &key)) { do_warn( _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"), i, agno, bno, name); rmap_priv->last_rec.rm_blockcount += key.rm_blockcount; } else rmap_priv->last_rec = key; /* Check that we don't go past the high key. */ key.rm_startblock += key.rm_blockcount - 1; if (!XFS_RMAP_NON_INODE_OWNER(key.rm_owner) && !(key.rm_flags & XFS_RMAP_BMBT_BLOCK)) key.rm_offset += key.rm_blockcount - 1; key.rm_blockcount = 0; if (rmap_diffkeys(&key, &rmap_priv->high_key) > 0) { do_warn( _("record %d greater than high key of block (%u/%u) in %s tree\n"), i, agno, bno, name); } /* Check for block owner collisions. */ for ( ; b < end; b += blen) { state = get_bmap_ext(agno, b, end, &blen); process_rmap_rec(mp, agno, b, end, blen, owner, state, name); } } goto out; } /* * interior record */ pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]); if (numrecs > mp->m_rmap_mxr[1]) { numrecs = mp->m_rmap_mxr[1]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_rmap_mnr[1]) { numrecs = mp->m_rmap_mnr[1]; hdr_errors++; } /* * don't pass bogus tree flag down further if this block * looked ok. bail out if two levels in a row look bad. */ if (hdr_errors) { do_warn( _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_rmap_mnr[1], mp->m_rmap_mxr[1], name, agno, bno); if (suspect) goto out; suspect++; } else if (suspect) { suspect = 0; } /* check the node's high keys */ for (i = 0; !isroot && i < numrecs; i++) { kp = XFS_RMAP_HIGH_KEY_ADDR(block, i + 1); key.rm_flags = 0; key.rm_startblock = be32_to_cpu(kp->rm_startblock); key.rm_owner = be64_to_cpu(kp->rm_owner); if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), &key)) { /* Look for impossible flags. */ do_warn( _("invalid flags in key %u of %s btree block %u/%u\n"), i, name, agno, bno); continue; } if (rmap_diffkeys(&key, &rmap_priv->high_key) > 0) do_warn( _("key %d greater than high key of block (%u/%u) in %s tree\n"), i, agno, bno, name); } for (i = 0; i < numrecs; i++) { xfs_agblock_t bno = be32_to_cpu(pp[i]); /* * XXX - put sibling detection right here. * we know our sibling chain is good. So as we go, * we check the entry before and after each entry. * If either of the entries references a different block, * check the sibling pointer. If there's a sibling * pointer mismatch, try and extract as much data * as possible. */ kp = XFS_RMAP_HIGH_KEY_ADDR(block, i + 1); rmap_priv->high_key.rm_flags = 0; rmap_priv->high_key.rm_startblock = be32_to_cpu(kp->rm_startblock); rmap_priv->high_key.rm_owner = be64_to_cpu(kp->rm_owner); if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), &rmap_priv->high_key)) { /* Look for impossible flags. */ do_warn( _("invalid flags in high key %u of %s btree block %u/%u\n"), i, name, agno, bno); continue; } if (bno != 0 && verify_agbno(mp, agno, bno)) { scan_sbtree(bno, level, agno, suspect, scan_rmapbt, 0, magic, priv, &xfs_rmapbt_buf_ops); } } out: if (suspect) rmap_avoid_check(); } struct refc_priv { struct xfs_refcount_irec last_rec; xfs_agblock_t nr_blocks; }; static void scan_refcbt( struct xfs_btree_block *block, int level, xfs_agblock_t bno, xfs_agnumber_t agno, int suspect, int isroot, __uint32_t magic, void *priv) { const char *name = "refcount"; int i; xfs_refcount_ptr_t *pp; struct xfs_refcount_rec *rp; int hdr_errors = 0; int numrecs; int state; xfs_agblock_t lastblock = 0; struct refc_priv *refc_priv = priv; if (magic != XFS_REFC_CRC_MAGIC) { name = "(unknown)"; hdr_errors++; suspect++; goto out; } if (be32_to_cpu(block->bb_magic) != magic) { do_warn(_("bad magic # %#x in %s btree block %d/%d\n"), be32_to_cpu(block->bb_magic), name, agno, bno); hdr_errors++; if (suspect) goto out; } if (be16_to_cpu(block->bb_level) != level) { do_warn(_("expected level %d got %d in %s btree block %d/%d\n"), level, be16_to_cpu(block->bb_level), name, agno, bno); hdr_errors++; if (suspect) goto out; } refc_priv->nr_blocks++; /* check for btree blocks multiply claimed */ state = get_bmap(agno, bno); if (!(state == XR_E_UNKNOWN || state == XR_E_REFC)) { set_bmap(agno, bno, XR_E_MULT); do_warn( _("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), name, state, agno, bno, suspect); goto out; } set_bmap(agno, bno, XR_E_FS_MAP); numrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (numrecs > mp->m_refc_mxr[0]) { numrecs = mp->m_refc_mxr[0]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_refc_mnr[0]) { numrecs = mp->m_refc_mnr[0]; hdr_errors++; } if (hdr_errors) { do_warn( _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_refc_mnr[0], mp->m_refc_mxr[0], name, agno, bno); suspect++; } rp = XFS_REFCOUNT_REC_ADDR(block, 1); for (i = 0; i < numrecs; i++) { xfs_agblock_t b, agb, end; xfs_extlen_t len; xfs_nlink_t nr; b = agb = be32_to_cpu(rp[i].rc_startblock); len = be32_to_cpu(rp[i].rc_blockcount); nr = be32_to_cpu(rp[i].rc_refcount); if (b >= XFS_REFC_COW_START && nr != 1) do_warn( _("leftover CoW extent has incorrect refcount in record %u of %s btree block %u/%u\n"), i, name, agno, bno); if (nr == 1) { if (agb < XFS_REFC_COW_START) do_warn( _("leftover CoW extent has invalid startblock in record %u of %s btree block %u/%u\n"), i, name, agno, bno); agb -= XFS_REFC_COW_START; } end = agb + len; if (!verify_agbno(mp, agno, agb)) { do_warn( _("invalid start block %u in record %u of %s btree block %u/%u\n"), b, i, name, agno, bno); continue; } if (len == 0 || !verify_agbno(mp, agno, end - 1)) { do_warn( _("invalid length %u in record %u of %s btree block %u/%u\n"), len, i, name, agno, bno); continue; } if (nr == 1) { xfs_agblock_t c; xfs_extlen_t cnr; for (c = agb; c < end; c += cnr) { state = get_bmap_ext(agno, c, end, &cnr); switch (state) { case XR_E_UNKNOWN: case XR_E_COW: do_warn( _("leftover CoW extent (%u/%u) len %u\n"), agno, c, cnr); set_bmap_ext(agno, c, cnr, XR_E_FREE); break; default: do_warn( _("extent (%u/%u) len %u claimed, state is %d\n"), agno, c, cnr, state); break; } } } else if (nr < 2 || nr > MAXREFCOUNT) { do_warn( _("invalid reference count %u in record %u of %s btree block %u/%u\n"), nr, i, name, agno, bno); continue; } if (b && b <= lastblock) { do_warn(_( "out-of-order %s btree record %d (%u %u) block %u/%u\n"), name, i, b, len, agno, bno); } else { lastblock = b; } /* Is this record mergeable with the last one? */ if (refc_priv->last_rec.rc_startblock + refc_priv->last_rec.rc_blockcount == b && refc_priv->last_rec.rc_refcount == nr) { do_warn( _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"), i, agno, bno, name); refc_priv->last_rec.rc_blockcount += len; } else { refc_priv->last_rec.rc_startblock = b; refc_priv->last_rec.rc_blockcount = len; refc_priv->last_rec.rc_refcount = nr; } /* XXX: probably want to mark the reflinked areas? */ } goto out; } /* * interior record */ pp = XFS_REFCOUNT_PTR_ADDR(block, 1, mp->m_refc_mxr[1]); if (numrecs > mp->m_refc_mxr[1]) { numrecs = mp->m_refc_mxr[1]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_refc_mnr[1]) { numrecs = mp->m_refc_mnr[1]; hdr_errors++; } /* * don't pass bogus tree flag down further if this block * looked ok. bail out if two levels in a row look bad. */ if (hdr_errors) { do_warn( _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"), be16_to_cpu(block->bb_numrecs), mp->m_refc_mnr[1], mp->m_refc_mxr[1], name, agno, bno); if (suspect) goto out; suspect++; } else if (suspect) { suspect = 0; } for (i = 0; i < numrecs; i++) { xfs_agblock_t bno = be32_to_cpu(pp[i]); if (bno != 0 && verify_agbno(mp, agno, bno)) { scan_sbtree(bno, level, agno, suspect, scan_refcbt, 0, magic, priv, &xfs_refcountbt_buf_ops); } } out: if (suspect) refcount_avoid_check(); return; } /* * The following helpers are to help process and validate individual on-disk * inode btree records. We have two possible inode btrees with slightly * different semantics. Many of the validations and actions are equivalent, such * as record alignment constraints, etc. Other validations differ, such as the * fact that the inode chunk block allocation state is set by the content of the * core inobt and verified by the content of the finobt. * * The following structures are used to facilitate common validation routines * where the only difference between validation of the inobt or finobt might be * the error messages that results in the event of failure. */ enum inobt_type { INOBT, FINOBT }; const char *inobt_names[] = { "inobt", "finobt" }; static int verify_single_ino_chunk_align( xfs_agnumber_t agno, enum inobt_type type, struct xfs_inobt_rec *rp, int suspect, bool *skip) { const char *inobt_name = inobt_names[type]; xfs_ino_t lino; xfs_agino_t ino; xfs_agblock_t agbno; int off; *skip = false; ino = be32_to_cpu(rp->ir_startino); off = XFS_AGINO_TO_OFFSET(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, ino); lino = XFS_AGINO_TO_INO(mp, agno, ino); /* * on multi-block block chunks, all chunks start at the beginning of the * block. with multi-chunk blocks, all chunks must start on 64-inode * boundaries since each block can hold N complete chunks. if fs has * aligned inodes, all chunks must start at a fs_ino_alignment*N'th * agbno. skip recs with badly aligned starting inodes. */ if (ino == 0 || (inodes_per_block <= XFS_INODES_PER_CHUNK && off != 0) || (inodes_per_block > XFS_INODES_PER_CHUNK && off % XFS_INODES_PER_CHUNK != 0) || (fs_aligned_inodes && fs_ino_alignment && agbno % fs_ino_alignment != 0)) { do_warn( _("badly aligned %s rec (starting inode = %" PRIu64 ")\n"), inobt_name, lino); suspect++; } /* * verify numeric validity of inode chunk first before inserting into a * tree. don't have to worry about the overflow case because the * starting ino number of a chunk can only get within 255 inodes of max * (NULLAGINO). if it gets closer, the agino number will be illegal as * the agbno will be too large. */ if (verify_aginum(mp, agno, ino)) { do_warn( _("bad starting inode # (%" PRIu64 " (0x%x 0x%x)) in %s rec, skipping rec\n"), lino, agno, ino, inobt_name); *skip = true; return ++suspect; } if (verify_aginum(mp, agno, ino + XFS_INODES_PER_CHUNK - 1)) { do_warn( _("bad ending inode # (%" PRIu64 " (0x%x 0x%zx)) in %s rec, skipping rec\n"), lino + XFS_INODES_PER_CHUNK - 1, agno, ino + XFS_INODES_PER_CHUNK - 1, inobt_name); *skip = true; return ++suspect; } return suspect; } /* * Process the state of individual inodes in an on-disk inobt record and import * into the appropriate in-core tree based on whether the on-disk tree is * suspect. Return the total and free inode counts based on the record free and * hole masks. */ static int import_single_ino_chunk( xfs_agnumber_t agno, enum inobt_type type, struct xfs_inobt_rec *rp, int suspect, int *p_nfree, int *p_ninodes) { struct ino_tree_node *ino_rec = NULL; const char *inobt_name = inobt_names[type]; xfs_agino_t ino; int j; int nfree; int ninodes; ino = be32_to_cpu(rp->ir_startino); if (!suspect) { if (XFS_INOBT_IS_FREE_DISK(rp, 0)) ino_rec = set_inode_free_alloc(mp, agno, ino); else ino_rec = set_inode_used_alloc(mp, agno, ino); for (j = 1; j < XFS_INODES_PER_CHUNK; j++) { if (XFS_INOBT_IS_FREE_DISK(rp, j)) set_inode_free(ino_rec, j); else set_inode_used(ino_rec, j); } } else { for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { if (XFS_INOBT_IS_FREE_DISK(rp, j)) add_aginode_uncertain(mp, agno, ino + j, 1); else add_aginode_uncertain(mp, agno, ino + j, 0); } } /* * Mark sparse inodes as such in the in-core tree. Verify that sparse * inodes are free and that freecount is consistent with the free mask. */ nfree = ninodes = 0; for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { if (ino_issparse(rp, j)) { if (!suspect && !XFS_INOBT_IS_FREE_DISK(rp, j)) { do_warn( _("ir_holemask/ir_free mismatch, %s chunk %d/%u, holemask 0x%x free 0x%llx\n"), inobt_name, agno, ino, be16_to_cpu(rp->ir_u.sp.ir_holemask), be64_to_cpu(rp->ir_free)); suspect++; } if (!suspect && ino_rec) set_inode_sparse(ino_rec, j); } else { /* count fields track non-sparse inos */ if (XFS_INOBT_IS_FREE_DISK(rp, j)) nfree++; ninodes++; } } *p_nfree = nfree; *p_ninodes = ninodes; return suspect; } static int scan_single_ino_chunk( xfs_agnumber_t agno, xfs_inobt_rec_t *rp, int suspect) { xfs_ino_t lino; xfs_agino_t ino; xfs_agblock_t agbno; int j; int nfree; int ninodes; int off; int state; ino_tree_node_t *first_rec, *last_rec; int freecount; bool skip = false; ino = be32_to_cpu(rp->ir_startino); off = XFS_AGINO_TO_OFFSET(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, ino); lino = XFS_AGINO_TO_INO(mp, agno, ino); freecount = inorec_get_freecount(mp, rp); /* * Verify record alignment, start/end inode numbers, etc. */ suspect = verify_single_ino_chunk_align(agno, INOBT, rp, suspect, &skip); if (skip) return suspect; /* * set state of each block containing inodes */ if (off == 0 && !suspect) { for (j = 0; j < XFS_INODES_PER_CHUNK; j += mp->m_sb.sb_inopblock) { /* inodes in sparse chunks don't use blocks */ if (ino_issparse(rp, j)) continue; agbno = XFS_AGINO_TO_AGBNO(mp, ino + j); state = get_bmap(agno, agbno); switch (state) { case XR_E_INO: break; case XR_E_UNKNOWN: case XR_E_INO1: /* seen by rmap */ set_bmap(agno, agbno, XR_E_INO); break; case XR_E_INUSE_FS: case XR_E_INUSE_FS1: if (agno == 0 && ino + j >= first_prealloc_ino && ino + j < last_prealloc_ino) { set_bmap(agno, agbno, XR_E_INO); break; } /* fall through */ default: /* XXX - maybe should mark block a duplicate */ do_warn( _("inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); return ++suspect; } } } /* * ensure only one avl entry per chunk */ find_inode_rec_range(mp, agno, ino, ino + XFS_INODES_PER_CHUNK, &first_rec, &last_rec); if (first_rec != NULL) { /* * this chunk overlaps with one (or more) * already in the tree */ do_warn( _("inode rec for ino %" PRIu64 " (%d/%d) overlaps existing rec (start %d/%d)\n"), lino, agno, ino, agno, first_rec->ino_startnum); suspect++; /* * if the 2 chunks start at the same place, * then we don't have to put this one * in the uncertain list. go to the next one. */ if (first_rec->ino_startnum == ino) return suspect; } /* * Import the state of individual inodes into the appropriate in-core * trees, mark them free or used, and get the resulting total and free * inode counts. */ nfree = ninodes = 0; suspect = import_single_ino_chunk(agno, INOBT, rp, suspect, &nfree, &ninodes); if (nfree != freecount) { do_warn( _("ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n"), agno, ino, freecount, nfree); } /* verify sparse record formats have a valid inode count */ if (xfs_sb_version_hassparseinodes(&mp->m_sb) && ninodes != rp->ir_u.sp.ir_count) { do_warn( _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"), agno, ino, rp->ir_u.sp.ir_count, ninodes); } return suspect; } static int scan_single_finobt_chunk( xfs_agnumber_t agno, xfs_inobt_rec_t *rp, int suspect) { xfs_ino_t lino; xfs_agino_t ino; xfs_agblock_t agbno; int j; int nfree; int ninodes; int off; int state; ino_tree_node_t *first_rec, *last_rec; int freecount; bool skip = false; ino = be32_to_cpu(rp->ir_startino); off = XFS_AGINO_TO_OFFSET(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, ino); lino = XFS_AGINO_TO_INO(mp, agno, ino); freecount = inorec_get_freecount(mp, rp); /* * Verify record alignment, start/end inode numbers, etc. */ suspect = verify_single_ino_chunk_align(agno, FINOBT, rp, suspect, &skip); if (skip) return suspect; /* * cross check state of each block containing inodes referenced by the * finobt against what we have already scanned from the alloc inobt. */ if (off == 0 && !suspect) { for (j = 0; j < XFS_INODES_PER_CHUNK; j += mp->m_sb.sb_inopblock) { agbno = XFS_AGINO_TO_AGBNO(mp, ino + j); state = get_bmap(agno, agbno); /* sparse inodes should not refer to inode blocks */ if (ino_issparse(rp, j)) { if (state == XR_E_INO) { do_warn( _("sparse inode chunk claims inode block, finobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); suspect++; } continue; } switch (state) { case XR_E_INO: break; case XR_E_INO1: /* seen by rmap */ set_bmap(agno, agbno, XR_E_INO); break; case XR_E_UNKNOWN: do_warn( _("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); set_bmap(agno, agbno, XR_E_INO); suspect++; break; case XR_E_INUSE_FS: case XR_E_INUSE_FS1: if (agno == 0 && ino + j >= first_prealloc_ino && ino + j < last_prealloc_ino) { do_warn( _("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); set_bmap(agno, agbno, XR_E_INO); suspect++; break; } /* fall through */ default: do_warn( _("inode chunk claims used block, finobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); return ++suspect; } } } /* * ensure we have an incore entry for each chunk */ find_inode_rec_range(mp, agno, ino, ino + XFS_INODES_PER_CHUNK, &first_rec, &last_rec); if (first_rec) { if (suspect) return suspect; /* * verify consistency between finobt record and incore state */ if (first_rec->ino_startnum != ino) { do_warn( _("finobt rec for ino %" PRIu64 " (%d/%u) does not match existing rec (%d/%d)\n"), lino, agno, ino, agno, first_rec->ino_startnum); return ++suspect; } nfree = ninodes = 0; for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { int isfree = XFS_INOBT_IS_FREE_DISK(rp, j); int issparse = ino_issparse(rp, j); if (!issparse) ninodes++; if (isfree && !issparse) nfree++; /* * inode allocation state should be consistent between * the inobt and finobt */ if (!suspect && isfree != is_inode_free(first_rec, j)) suspect++; if (!suspect && issparse != is_inode_sparse(first_rec, j)) suspect++; } goto check_freecount; } /* * The finobt contains a record that the previous inobt scan never * found. Warn about it and import the inodes into the appropriate * trees. * * Note that this should do the right thing if the previous inobt scan * had added these inodes to the uncertain tree. If the finobt is not * suspect, these inodes should supercede the uncertain ones. Otherwise, * the uncertain tree helpers handle the case where uncertain inodes * already exist. */ do_warn(_("undiscovered finobt record, ino %" PRIu64 " (%d/%u)\n"), lino, agno, ino); nfree = ninodes = 0; suspect = import_single_ino_chunk(agno, FINOBT, rp, suspect, &nfree, &ninodes); check_freecount: /* * Verify that the record freecount matches the actual number of free * inodes counted in the record. Don't increment 'suspect' here, since * we have already verified the allocation state of the individual * inodes against the in-core state. This will have already incremented * 'suspect' if something is wrong. If suspect hasn't been set at this * point, these warnings mean that we have a simple freecount * inconsistency or a stray finobt record (as opposed to a broader tree * corruption). Issue a warning and continue the scan. The final btree * reconstruction will correct this naturally. */ if (nfree != freecount) { do_warn( _("finobt ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n"), agno, ino, freecount, nfree); } if (!nfree) { do_warn( _("finobt record with no free inodes, inode chunk %d/%u\n"), agno, ino); } /* verify sparse record formats have a valid inode count */ if (xfs_sb_version_hassparseinodes(&mp->m_sb) && ninodes != rp->ir_u.sp.ir_count) { do_warn( _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"), agno, ino, rp->ir_u.sp.ir_count, ninodes); } return suspect; } /* * this one walks the inode btrees sucking the info there into * the incore avl tree. We try and rescue corrupted btree records * to minimize our chances of losing inodes. Inode info from potentially * corrupt sources could be bogus so rather than put the info straight * into the tree, instead we put it on a list and try and verify the * info in the next phase by examining what's on disk. At that point, * we'll be able to figure out what's what and stick the corrected info * into the tree. We do bail out at some point and give up on a subtree * so as to avoid walking randomly all over the ag. * * Note that it's also ok if the free/inuse info wrong, we can correct * that when we examine the on-disk inode. The important thing is to * get the start and alignment of the inode chunks right. Those chunks * that we aren't sure about go into the uncertain list. */ static void scan_inobt( struct xfs_btree_block *block, int level, xfs_agblock_t bno, xfs_agnumber_t agno, int suspect, int isroot, __uint32_t magic, void *priv) { struct aghdr_cnts *agcnts = priv; int i; int numrecs; int state; xfs_inobt_ptr_t *pp; xfs_inobt_rec_t *rp; int hdr_errors; int freecount; hdr_errors = 0; if (be32_to_cpu(block->bb_magic) != magic) { do_warn(_("bad magic # %#x in inobt block %d/%d\n"), be32_to_cpu(block->bb_magic), agno, bno); hdr_errors++; bad_ino_btree = 1; if (suspect) return; } if (be16_to_cpu(block->bb_level) != level) { do_warn(_("expected level %d got %d in inobt block %d/%d\n"), level, be16_to_cpu(block->bb_level), agno, bno); hdr_errors++; bad_ino_btree = 1; if (suspect) return; } /* * check for btree blocks multiply claimed, any unknown/free state * is ok in the bitmap block. */ state = get_bmap(agno, bno); switch (state) { case XR_E_FS_MAP1: /* already been seen by an rmap scan */ case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: set_bmap(agno, bno, XR_E_FS_MAP); break; default: set_bmap(agno, bno, XR_E_MULT); do_warn( _("inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), state, agno, bno, suspect); } numrecs = be16_to_cpu(block->bb_numrecs); /* * leaf record in btree */ if (level == 0) { /* check for trashed btree block */ if (numrecs > mp->m_inobt_mxr[0]) { numrecs = mp->m_inobt_mxr[0]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_inobt_mnr[0]) { numrecs = mp->m_inobt_mnr[0]; hdr_errors++; } if (hdr_errors) { bad_ino_btree = 1; do_warn(_("dubious inode btree block header %d/%d\n"), agno, bno); suspect++; } rp = XFS_INOBT_REC_ADDR(mp, block, 1); /* * step through the records, each record points to * a chunk of inodes. The start of inode chunks should * be block-aligned. Each inode btree rec should point * to the start of a block of inodes or the start of a group * of INODES_PER_CHUNK (64) inodes. off is the offset into * the block. skip processing of bogus records. */ for (i = 0; i < numrecs; i++) { freecount = inorec_get_freecount(mp, &rp[i]); if (magic == XFS_IBT_MAGIC || magic == XFS_IBT_CRC_MAGIC) { int icount = XFS_INODES_PER_CHUNK; /* * ir_count holds the inode count for all * records on fs' with sparse inode support */ if (xfs_sb_version_hassparseinodes(&mp->m_sb)) icount = rp[i].ir_u.sp.ir_count; agcnts->agicount += icount; agcnts->agifreecount += freecount; agcnts->ifreecount += freecount; suspect = scan_single_ino_chunk(agno, &rp[i], suspect); } else { /* * the finobt tracks records with free inodes, * so only the free inode count is expected to be * consistent with the agi */ agcnts->fibtfreecount += freecount; suspect = scan_single_finobt_chunk(agno, &rp[i], suspect); } } if (suspect) bad_ino_btree = 1; return; } /* * interior record, continue on */ if (numrecs > mp->m_inobt_mxr[1]) { numrecs = mp->m_inobt_mxr[1]; hdr_errors++; } if (isroot == 0 && numrecs < mp->m_inobt_mnr[1]) { numrecs = mp->m_inobt_mnr[1]; hdr_errors++; } pp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]); /* * don't pass bogus tree flag down further if this block * looked ok. bail out if two levels in a row look bad. */ if (suspect && !hdr_errors) suspect = 0; if (hdr_errors) { bad_ino_btree = 1; if (suspect) return; else suspect++; } for (i = 0; i < numrecs; i++) { if (be32_to_cpu(pp[i]) != 0 && verify_agbno(mp, agno, be32_to_cpu(pp[i]))) scan_sbtree(be32_to_cpu(pp[i]), level, agno, suspect, scan_inobt, 0, magic, priv, &xfs_inobt_buf_ops); } } static void scan_freelist( xfs_agf_t *agf, struct aghdr_cnts *agcnts) { xfs_buf_t *agflbuf; xfs_agnumber_t agno; xfs_agblock_t bno; int count; int i; __be32 *freelist; agno = be32_to_cpu(agf->agf_seqno); if (XFS_SB_BLOCK(mp) != XFS_AGFL_BLOCK(mp) && XFS_AGF_BLOCK(mp) != XFS_AGFL_BLOCK(mp) && XFS_AGI_BLOCK(mp) != XFS_AGFL_BLOCK(mp)) set_bmap(agno, XFS_AGFL_BLOCK(mp), XR_E_INUSE_FS); if (be32_to_cpu(agf->agf_flcount) == 0) return; agflbuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, &xfs_agfl_buf_ops); if (!agflbuf) { do_abort(_("can't read agfl block for ag %d\n"), agno); return; } if (agflbuf->b_error == -EFSBADCRC) do_warn(_("agfl has bad CRC for ag %d\n"), agno); freelist = XFS_BUF_TO_AGFL_BNO(mp, agflbuf); i = be32_to_cpu(agf->agf_flfirst); if (no_modify) { /* agf values not fixed in verify_set_agf, so recheck */ if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp) || be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) { do_warn(_("agf %d freelist blocks bad, skipping " "freelist scan\n"), i); return; } } count = 0; for (;;) { bno = be32_to_cpu(freelist[i]); if (verify_agbno(mp, agno, bno)) set_bmap(agno, bno, XR_E_FREE); else do_warn(_("bad agbno %u in agfl, agno %d\n"), bno, agno); count++; if (i == be32_to_cpu(agf->agf_fllast)) break; if (++i == XFS_AGFL_SIZE(mp)) i = 0; } if (count != be32_to_cpu(agf->agf_flcount)) { do_warn(_("freeblk count %d != flcount %d in ag %d\n"), count, be32_to_cpu(agf->agf_flcount), agno); } agcnts->fdblocks += count; libxfs_putbuf(agflbuf); } static void validate_agf( struct xfs_agf *agf, xfs_agnumber_t agno, struct aghdr_cnts *agcnts) { xfs_agblock_t bno; __uint32_t magic; bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]); if (bno != 0 && verify_agbno(mp, agno, bno)) { magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTB_CRC_MAGIC : XFS_ABTB_MAGIC; scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]), agno, 0, scan_allocbt, 1, magic, agcnts, &xfs_allocbt_buf_ops); } else { do_warn(_("bad agbno %u for btbno root, agno %d\n"), bno, agno); } bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]); if (bno != 0 && verify_agbno(mp, agno, bno)) { magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTC_CRC_MAGIC : XFS_ABTC_MAGIC; scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]), agno, 0, scan_allocbt, 1, magic, agcnts, &xfs_allocbt_buf_ops); } else { do_warn(_("bad agbno %u for btbcnt root, agno %d\n"), bno, agno); } if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { struct rmap_priv priv; memset(&priv.high_key, 0xFF, sizeof(priv.high_key)); priv.high_key.rm_blockcount = 0; priv.agcnts = agcnts; priv.last_rec.rm_owner = XFS_RMAP_OWN_UNKNOWN; priv.nr_blocks = 0; bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); if (bno != 0 && verify_agbno(mp, agno, bno)) { scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]), agno, 0, scan_rmapbt, 1, XFS_RMAP_CRC_MAGIC, &priv, &xfs_rmapbt_buf_ops); if (be32_to_cpu(agf->agf_rmap_blocks) != priv.nr_blocks) do_warn(_("bad rmapbt block count %u, saw %u\n"), priv.nr_blocks, be32_to_cpu(agf->agf_rmap_blocks)); } else { do_warn(_("bad agbno %u for rmapbt root, agno %d\n"), bno, agno); rmap_avoid_check(); } } if (xfs_sb_version_hasreflink(&mp->m_sb)) { bno = be32_to_cpu(agf->agf_refcount_root); if (bno != 0 && verify_agbno(mp, agno, bno)) { struct refc_priv priv; memset(&priv, 0, sizeof(priv)); scan_sbtree(bno, be32_to_cpu(agf->agf_refcount_level), agno, 0, scan_refcbt, 1, XFS_REFC_CRC_MAGIC, &priv, &xfs_refcountbt_buf_ops); if (be32_to_cpu(agf->agf_refcount_blocks) != priv.nr_blocks) do_warn(_("bad refcountbt block count %u, saw %u\n"), priv.nr_blocks, be32_to_cpu(agf->agf_refcount_blocks)); } else { do_warn(_("bad agbno %u for refcntbt root, agno %d\n"), bno, agno); refcount_avoid_check(); } } if (be32_to_cpu(agf->agf_freeblks) != agcnts->agffreeblks) { do_warn(_("agf_freeblks %u, counted %u in ag %u\n"), be32_to_cpu(agf->agf_freeblks), agcnts->agffreeblks, agno); } if (be32_to_cpu(agf->agf_longest) != agcnts->agflongest) { do_warn(_("agf_longest %u, counted %u in ag %u\n"), be32_to_cpu(agf->agf_longest), agcnts->agflongest, agno); } if (xfs_sb_version_haslazysbcount(&mp->m_sb) && be32_to_cpu(agf->agf_btreeblks) != agcnts->agfbtreeblks) { do_warn(_("agf_btreeblks %u, counted %" PRIu64 " in ag %u\n"), be32_to_cpu(agf->agf_btreeblks), agcnts->agfbtreeblks, agno); } } static void validate_agi( struct xfs_agi *agi, xfs_agnumber_t agno, struct aghdr_cnts *agcnts) { xfs_agblock_t bno; int i; __uint32_t magic; bno = be32_to_cpu(agi->agi_root); if (bno != 0 && verify_agbno(mp, agno, bno)) { magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC : XFS_IBT_MAGIC; scan_sbtree(bno, be32_to_cpu(agi->agi_level), agno, 0, scan_inobt, 1, magic, agcnts, &xfs_inobt_buf_ops); } else { do_warn(_("bad agbno %u for inobt root, agno %d\n"), be32_to_cpu(agi->agi_root), agno); } if (xfs_sb_version_hasfinobt(&mp->m_sb)) { bno = be32_to_cpu(agi->agi_free_root); if (bno != 0 && verify_agbno(mp, agno, bno)) { magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC; scan_sbtree(bno, be32_to_cpu(agi->agi_free_level), agno, 0, scan_inobt, 1, magic, agcnts, &xfs_inobt_buf_ops); } else { do_warn(_("bad agbno %u for finobt root, agno %d\n"), be32_to_cpu(agi->agi_free_root), agno); } } if (be32_to_cpu(agi->agi_count) != agcnts->agicount) { do_warn(_("agi_count %u, counted %u in ag %u\n"), be32_to_cpu(agi->agi_count), agcnts->agicount, agno); } if (be32_to_cpu(agi->agi_freecount) != agcnts->agifreecount) { do_warn(_("agi_freecount %u, counted %u in ag %u\n"), be32_to_cpu(agi->agi_freecount), agcnts->agifreecount, agno); } if (xfs_sb_version_hasfinobt(&mp->m_sb) && be32_to_cpu(agi->agi_freecount) != agcnts->fibtfreecount) { do_warn(_("agi_freecount %u, counted %u in ag %u finobt\n"), be32_to_cpu(agi->agi_freecount), agcnts->fibtfreecount, agno); } for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) { xfs_agino_t agino = be32_to_cpu(agi->agi_unlinked[i]); if (agino != NULLAGINO) { do_warn( _("agi unlinked bucket %d is %u in ag %u (inode=%" PRIu64 ")\n"), i, agino, agno, XFS_AGINO_TO_INO(mp, agno, agino)); } } } /* * Scan an AG for obvious corruption. */ static void scan_ag( work_queue_t *wq, xfs_agnumber_t agno, void *arg) { struct aghdr_cnts *agcnts = arg; struct xfs_agf *agf; struct xfs_buf *agfbuf = NULL; int agf_dirty = 0; struct xfs_agi *agi; struct xfs_buf *agibuf = NULL; int agi_dirty = 0; struct xfs_sb *sb = NULL; struct xfs_buf *sbbuf = NULL; int sb_dirty = 0; int status; char *objname = NULL; sb = (struct xfs_sb *)calloc(BBTOB(XFS_FSS_TO_BB(mp, 1)), 1); if (!sb) { do_error(_("can't allocate memory for superblock\n")); return; } sbbuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), 0, &xfs_sb_buf_ops); if (!sbbuf) { objname = _("root superblock"); goto out_free_sb; } libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbbuf)); agfbuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, &xfs_agf_buf_ops); if (!agfbuf) { objname = _("agf block"); goto out_free_sbbuf; } agf = XFS_BUF_TO_AGF(agfbuf); agibuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, &xfs_agi_buf_ops); if (!agibuf) { objname = _("agi block"); goto out_free_agfbuf; } agi = XFS_BUF_TO_AGI(agibuf); /* fix up bad ag headers */ status = verify_set_agheader(mp, sbbuf, sb, agf, agi, agno); if (status & XR_AG_SB_SEC) { if (!no_modify) sb_dirty = 1; /* * clear bad sector bit because we don't want * to skip further processing. we just want to * ensure that we write out the modified sb buffer. */ status &= ~XR_AG_SB_SEC; } if (status & XR_AG_SB) { if (!no_modify) { do_warn(_("reset bad sb for ag %d\n"), agno); sb_dirty = 1; } else { do_warn(_("would reset bad sb for ag %d\n"), agno); } } if (status & XR_AG_AGF) { if (!no_modify) { do_warn(_("reset bad agf for ag %d\n"), agno); agf_dirty = 1; } else { do_warn(_("would reset bad agf for ag %d\n"), agno); } } if (status & XR_AG_AGI) { if (!no_modify) { do_warn(_("reset bad agi for ag %d\n"), agno); agi_dirty = 1; } else { do_warn(_("would reset bad agi for ag %d\n"), agno); } } if (status && no_modify) { do_warn(_("bad uncorrected agheader %d, skipping ag...\n"), agno); goto out_free_agibuf; } scan_freelist(agf, agcnts); validate_agf(agf, agno, agcnts); validate_agi(agi, agno, agcnts); ASSERT(agi_dirty == 0 || (agi_dirty && !no_modify)); ASSERT(agf_dirty == 0 || (agf_dirty && !no_modify)); ASSERT(sb_dirty == 0 || (sb_dirty && !no_modify)); /* * Only pay attention to CRC/verifier errors if we can correct them. * Note that we can get uncorrected EFSCORRUPTED errors here because * the verifier will flag on out of range values that we can't correct * until phase 5 when we have all the information necessary to rebuild * the freespace/inode btrees. We can correct bad CRC errors * immediately, though. */ if (!no_modify) { agi_dirty += (agibuf->b_error == -EFSBADCRC); agf_dirty += (agfbuf->b_error == -EFSBADCRC); sb_dirty += (sbbuf->b_error == -EFSBADCRC); } if (agi_dirty && !no_modify) libxfs_writebuf(agibuf, 0); else libxfs_putbuf(agibuf); if (agf_dirty && !no_modify) libxfs_writebuf(agfbuf, 0); else libxfs_putbuf(agfbuf); if (sb_dirty && !no_modify) { if (agno == 0) memcpy(&mp->m_sb, sb, sizeof(xfs_sb_t)); libxfs_sb_to_disk(XFS_BUF_TO_SBP(sbbuf), sb); libxfs_writebuf(sbbuf, 0); } else libxfs_putbuf(sbbuf); free(sb); PROG_RPT_INC(prog_rpt_done[agno], 1); #ifdef XR_INODE_TRACE print_inode_list(i); #endif return; out_free_agibuf: libxfs_putbuf(agibuf); out_free_agfbuf: libxfs_putbuf(agfbuf); out_free_sbbuf: libxfs_putbuf(sbbuf); out_free_sb: free(sb); if (objname) do_error(_("can't get %s for ag %d\n"), objname, agno); } #define SCAN_THREADS 32 void scan_ags( struct xfs_mount *mp, int scan_threads) { struct aghdr_cnts *agcnts; __uint64_t fdblocks = 0; __uint64_t icount = 0; __uint64_t ifreecount = 0; __uint64_t usedblocks = 0; xfs_agnumber_t i; work_queue_t wq; agcnts = malloc(mp->m_sb.sb_agcount * sizeof(*agcnts)); if (!agcnts) { do_abort(_("no memory for ag header counts\n")); return; } memset(agcnts, 0, mp->m_sb.sb_agcount * sizeof(*agcnts)); create_work_queue(&wq, mp, scan_threads); for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, scan_ag, i, &agcnts[i]); destroy_work_queue(&wq); /* tally up the counts */ for (i = 0; i < mp->m_sb.sb_agcount; i++) { fdblocks += agcnts[i].fdblocks; icount += agcnts[i].agicount; ifreecount += agcnts[i].ifreecount; usedblocks += agcnts[i].usedblocks; } free(agcnts); /* * Validate that our manual counts match the superblock. */ if (mp->m_sb.sb_icount != icount) { do_warn(_("sb_icount %" PRIu64 ", counted %" PRIu64 "\n"), mp->m_sb.sb_icount, icount); } if (mp->m_sb.sb_ifree != ifreecount) { do_warn(_("sb_ifree %" PRIu64 ", counted %" PRIu64 "\n"), mp->m_sb.sb_ifree, ifreecount); } if (mp->m_sb.sb_fdblocks != fdblocks) { do_warn(_("sb_fdblocks %" PRIu64 ", counted %" PRIu64 "\n"), mp->m_sb.sb_fdblocks, fdblocks); } if (usedblocks && usedblocks != mp->m_sb.sb_dblocks - fdblocks) { do_warn(_("used blocks %" PRIu64 ", counted %" PRIu64 "\n"), mp->m_sb.sb_dblocks - fdblocks, usedblocks); } } xfsprogs-4.9.0+nmu1ubuntu2/repair/scan.h0000644000000000000000000000336113063067173015056 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XR_SCAN_H #define _XR_SCAN_H struct blkmap; int scan_lbtree( xfs_fsblock_t root, int nlevels, int (*func)(struct xfs_btree_block *block, int level, int type, int whichfork, xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, __uint64_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, __uint64_t magic), int type, int whichfork, xfs_ino_t ino, xfs_rfsblock_t *tot, __uint64_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, __uint64_t magic, const struct xfs_buf_ops *ops); int scan_bmapbt( struct xfs_btree_block *block, int level, int type, int whichfork, xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, __uint64_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, __uint64_t magic); void scan_ags( struct xfs_mount *mp, int scan_threads); #endif /* _XR_SCAN_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/slab.c0000644000000000000000000002457413033541503015046 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "slab.h" #undef SLAB_DEBUG #ifdef SLAB_DEBUG # define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0) #else # define dbg_printf(f, a...) #endif /* * Slab Arrays and Bags * * The slab array is a dynamically growable linear array. Internally it * maintains a list of slabs of increasing size; when a slab fills up, another * is allocated. Each slab is sorted individually, which means that one must * use an iterator to walk the entire logical array, sorted order or otherwise. * Array items can neither be removed nor accessed randomly, since (at the * moment) the only user of them (storing reverse mappings) doesn't need either * piece. Pointers are not stable across sort operations. * * A bag is a collection of pointers. The bag can be added to or removed from * arbitrarily, and the bag items can be iterated. Bags are used to process * rmaps into refcount btree entries. */ /* * Slabs -- each slab_hdr holds an array of items; when a slab_hdr fills up, we * allocate a new one and add to that one. The slab object coordinates the * slab_hdrs. */ /* Each slab holds at least 4096 items */ #define MIN_SLAB_NR 4096 /* and cannot be larger than 128M */ #define MAX_SLAB_SIZE (128 * 1048576) struct xfs_slab_hdr { size_t sh_nr; size_t sh_inuse; /* items in use */ struct xfs_slab_hdr *sh_next; /* next slab hdr */ /* objects follow */ }; struct xfs_slab { size_t s_item_sz; /* item size */ size_t s_nr_slabs; /* # of slabs */ size_t s_nr_items; /* # of items */ struct xfs_slab_hdr *s_first; /* first slab header */ struct xfs_slab_hdr *s_last; /* last sh_next pointer */ }; /* * Slab cursors -- each slab_hdr_cursor tracks a slab_hdr; the slab_cursor * tracks the slab_hdr_cursors. If a compare_fn is specified, the cursor * returns objects in increasing order (if you've previously sorted the * slabs with qsort_slab()). If compare_fn == NULL, it returns slab items * in order. */ struct xfs_slab_hdr_cursor { struct xfs_slab_hdr *hdr; /* a slab header */ size_t loc; /* where we are in the slab */ }; typedef int (*xfs_slab_compare_fn)(const void *, const void *); struct xfs_slab_cursor { size_t nr; /* # of per-slab cursors */ struct xfs_slab *slab; /* pointer to the slab */ struct xfs_slab_hdr_cursor *last_hcur; /* last header we took from */ xfs_slab_compare_fn compare_fn; /* compare items */ struct xfs_slab_hdr_cursor hcur[0]; /* per-slab cursors */ }; /* * Bags -- each bag is an array of pointers items; when a bag fills up, we * resize it. */ #define MIN_BAG_SIZE 4096 struct xfs_bag { size_t bg_nr; /* number of pointers */ size_t bg_inuse; /* number of slots in use */ void **bg_ptrs; /* pointers */ }; #define BAG_SIZE(nr) (sizeof(struct xfs_bag) + ((nr) * sizeof(void *))) #define BAG_END(bag) (&(bag)->bg_ptrs[(bag)->bg_nr]) /* * Create a slab to hold some objects of a particular size. */ int init_slab( struct xfs_slab **slab, size_t item_size) { struct xfs_slab *ptr; ptr = calloc(1, sizeof(struct xfs_slab)); if (!ptr) return -ENOMEM; ptr->s_item_sz = item_size; ptr->s_last = NULL; *slab = ptr; return 0; } /* * Frees a slab. */ void free_slab( struct xfs_slab **slab) { struct xfs_slab *ptr; struct xfs_slab_hdr *hdr; struct xfs_slab_hdr *nhdr; ptr = *slab; if (!ptr) return; hdr = ptr->s_first; while (hdr) { nhdr = hdr->sh_next; free(hdr); hdr = nhdr; } free(ptr); *slab = NULL; } static void * slab_ptr( struct xfs_slab *slab, struct xfs_slab_hdr *hdr, size_t idx) { char *p; ASSERT(idx < hdr->sh_inuse); p = (char *)(hdr + 1); p += slab->s_item_sz * idx; return p; } /* * Add an item to the slab. */ int slab_add( struct xfs_slab *slab, void *item) { struct xfs_slab_hdr *hdr; void *p; hdr = slab->s_last; if (!hdr || hdr->sh_inuse == hdr->sh_nr) { size_t n; n = (hdr ? hdr->sh_nr * 2 : MIN_SLAB_NR); if (n * slab->s_item_sz > MAX_SLAB_SIZE) n = MAX_SLAB_SIZE / slab->s_item_sz; hdr = malloc(sizeof(struct xfs_slab_hdr) + (n * slab->s_item_sz)); if (!hdr) return -ENOMEM; hdr->sh_nr = n; hdr->sh_inuse = 0; hdr->sh_next = NULL; if (slab->s_last) slab->s_last->sh_next = hdr; if (!slab->s_first) slab->s_first = hdr; slab->s_last = hdr; slab->s_nr_slabs++; } hdr->sh_inuse++; p = slab_ptr(slab, hdr, hdr->sh_inuse - 1); memcpy(p, item, slab->s_item_sz); slab->s_nr_items++; return 0; } #include "threads.h" struct qsort_slab { struct xfs_slab *slab; struct xfs_slab_hdr *hdr; int (*compare_fn)(const void *, const void *); }; static void qsort_slab_helper( struct work_queue *wq, xfs_agnumber_t agno, void *arg) { struct qsort_slab *qs = arg; qsort(slab_ptr(qs->slab, qs->hdr, 0), qs->hdr->sh_inuse, qs->slab->s_item_sz, qs->compare_fn); free(qs); } /* * Sort the items in the slab. Do not run this method if there are any * cursors holding on to the slab. */ void qsort_slab( struct xfs_slab *slab, int (*compare_fn)(const void *, const void *)) { struct work_queue wq; struct xfs_slab_hdr *hdr; struct qsort_slab *qs; /* * If we don't have that many slabs, we're probably better * off skipping all the thread overhead. */ if (slab->s_nr_slabs <= 4) { hdr = slab->s_first; while (hdr) { qsort(slab_ptr(slab, hdr, 0), hdr->sh_inuse, slab->s_item_sz, compare_fn); hdr = hdr->sh_next; } return; } create_work_queue(&wq, NULL, libxfs_nproc()); hdr = slab->s_first; while (hdr) { qs = malloc(sizeof(struct qsort_slab)); qs->slab = slab; qs->hdr = hdr; qs->compare_fn = compare_fn; queue_work(&wq, qsort_slab_helper, 0, qs); hdr = hdr->sh_next; } destroy_work_queue(&wq); } /* * init_slab_cursor() -- Create a slab cursor to iterate the slab items. * * @slab: The slab. * @compare_fn: If specified, use this function to return items in ascending order. * @cur: The new cursor. */ int init_slab_cursor( struct xfs_slab *slab, int (*compare_fn)(const void *, const void *), struct xfs_slab_cursor **cur) { struct xfs_slab_cursor *c; struct xfs_slab_hdr_cursor *hcur; struct xfs_slab_hdr *hdr; c = malloc(sizeof(struct xfs_slab_cursor) + (sizeof(struct xfs_slab_hdr_cursor) * slab->s_nr_slabs)); if (!c) return -ENOMEM; c->nr = slab->s_nr_slabs; c->slab = slab; c->compare_fn = compare_fn; c->last_hcur = NULL; hcur = (struct xfs_slab_hdr_cursor *)(c + 1); hdr = slab->s_first; while (hdr) { hcur->hdr = hdr; hcur->loc = 0; hcur++; hdr = hdr->sh_next; } *cur = c; return 0; } /* * Free the slab cursor. */ void free_slab_cursor( struct xfs_slab_cursor **cur) { if (!*cur) return; free(*cur); *cur = NULL; } /* * Return the smallest item in the slab, without advancing the iterator. * The slabs must be sorted prior to the creation of the cursor. */ void * peek_slab_cursor( struct xfs_slab_cursor *cur) { struct xfs_slab_hdr_cursor *hcur; void *p = NULL; void *q; size_t i; cur->last_hcur = NULL; /* no compare function; inorder traversal */ if (!cur->compare_fn) { if (!cur->last_hcur) cur->last_hcur = &cur->hcur[0]; hcur = cur->last_hcur; while (hcur < &cur->hcur[cur->nr] && hcur->loc >= hcur->hdr->sh_inuse) hcur++; if (hcur == &cur->hcur[cur->nr]) return NULL; p = slab_ptr(cur->slab, hcur->hdr, hcur->loc); cur->last_hcur = hcur; return p; } /* otherwise return things in increasing order */ for (i = 0, hcur = &cur->hcur[i]; i < cur->nr; i++, hcur++) { if (hcur->loc >= hcur->hdr->sh_inuse) continue; q = slab_ptr(cur->slab, hcur->hdr, hcur->loc); if (!p || cur->compare_fn(p, q) > 0) { p = q; cur->last_hcur = hcur; } } return p; } /* * After a peek operation, advance the cursor. */ void advance_slab_cursor( struct xfs_slab_cursor *cur) { ASSERT(cur->last_hcur); cur->last_hcur->loc++; } /* * Retrieve the next item in the slab and advance the cursor. */ void * pop_slab_cursor( struct xfs_slab_cursor *cur) { void *p; p = peek_slab_cursor(cur); if (p) advance_slab_cursor(cur); return p; } /* * Return the number of items in the slab. */ size_t slab_count( struct xfs_slab *slab) { return slab->s_nr_items; } /* * Create a bag to point to some objects. */ int init_bag( struct xfs_bag **bag) { struct xfs_bag *ptr; ptr = calloc(1, sizeof(struct xfs_bag)); if (!ptr) return -ENOMEM; ptr->bg_ptrs = calloc(MIN_BAG_SIZE, sizeof(void *)); if (!ptr->bg_ptrs) { free(ptr); return -ENOMEM; } ptr->bg_nr = MIN_BAG_SIZE; *bag = ptr; return 0; } /* * Free a bag of pointers. */ void free_bag( struct xfs_bag **bag) { struct xfs_bag *ptr; ptr = *bag; if (!ptr) return; free(ptr->bg_ptrs); free(ptr); *bag = NULL; } /* * Add an object to the pointer bag. */ int bag_add( struct xfs_bag *bag, void *ptr) { void **p, **x; p = &bag->bg_ptrs[bag->bg_inuse]; if (p == BAG_END(bag)) { /* No free space, alloc more pointers */ size_t nr; nr = bag->bg_nr * 2; x = realloc(bag->bg_ptrs, nr * sizeof(void *)); if (!x) return -ENOMEM; bag->bg_ptrs = x; memset(BAG_END(bag), 0, bag->bg_nr * sizeof(void *)); bag->bg_nr = nr; } bag->bg_ptrs[bag->bg_inuse] = ptr; bag->bg_inuse++; return 0; } /* * Remove a pointer from a bag. */ int bag_remove( struct xfs_bag *bag, size_t nr) { ASSERT(nr < bag->bg_inuse); memmove(&bag->bg_ptrs[nr], &bag->bg_ptrs[nr + 1], (bag->bg_inuse - nr) * sizeof(void *)); bag->bg_inuse--; return 0; } /* * Return the number of items in a bag. */ size_t bag_count( struct xfs_bag *bag) { return bag->bg_inuse; } /* * Return the nth item in a bag. */ void * bag_item( struct xfs_bag *bag, size_t nr) { if (nr >= bag->bg_inuse) return NULL; return bag->bg_ptrs[nr]; } xfsprogs-4.9.0+nmu1ubuntu2/repair/slab.h0000644000000000000000000000421213033541503015036 0ustar /* * Copyright (C) 2016 Oracle. All Rights Reserved. * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef SLAB_H_ #define SLAB_H_ struct xfs_slab; struct xfs_slab_cursor; extern int init_slab(struct xfs_slab **, size_t); extern void free_slab(struct xfs_slab **); extern int slab_add(struct xfs_slab *, void *); extern void qsort_slab(struct xfs_slab *, int (*)(const void *, const void *)); extern size_t slab_count(struct xfs_slab *); extern int init_slab_cursor(struct xfs_slab *, int (*)(const void *, const void *), struct xfs_slab_cursor **); extern void free_slab_cursor(struct xfs_slab_cursor **); extern void *peek_slab_cursor(struct xfs_slab_cursor *); extern void advance_slab_cursor(struct xfs_slab_cursor *); extern void *pop_slab_cursor(struct xfs_slab_cursor *); struct xfs_bag; extern int init_bag(struct xfs_bag **); extern void free_bag(struct xfs_bag **); extern int bag_add(struct xfs_bag *, void *); extern int bag_remove(struct xfs_bag *, size_t); extern size_t bag_count(struct xfs_bag *); extern void *bag_item(struct xfs_bag *, size_t); #define foreach_bag_ptr(bag, idx, ptr) \ for ((idx) = 0, (ptr) = bag_item((bag), (idx)); \ (idx) < bag_count(bag); \ (idx)++, (ptr) = bag_item((bag), (idx))) #define foreach_bag_ptr_reverse(bag, idx, ptr) \ for ((idx) = bag_count(bag) - 1, (ptr) = bag_item((bag), (idx)); \ (ptr) != NULL; \ (idx)--, (ptr) = bag_item((bag), (idx))) #endif /* SLAB_H_ */ xfsprogs-4.9.0+nmu1ubuntu2/repair/threads.c0000644000000000000000000000542013063067172015554 0ustar #include "libxfs.h" #include #include #include "threads.h" #include "err_protos.h" #include "protos.h" #include "globals.h" static void * worker_thread(void *arg) { work_queue_t *wq; work_item_t *wi; wq = (work_queue_t*)arg; /* * Loop pulling work from the passed in work queue. * Check for notification to exit after every chunk of work. */ while (1) { pthread_mutex_lock(&wq->lock); /* * Wait for work. */ while (wq->next_item == NULL && !wq->terminate) { ASSERT(wq->item_count == 0); pthread_cond_wait(&wq->wakeup, &wq->lock); } if (wq->next_item == NULL && wq->terminate) { pthread_mutex_unlock(&wq->lock); break; } /* * Dequeue work from the head of the list. */ ASSERT(wq->item_count > 0); wi = wq->next_item; wq->next_item = wi->next; wq->item_count--; pthread_mutex_unlock(&wq->lock); (wi->function)(wi->queue, wi->agno, wi->arg); free(wi); } return NULL; } void thread_init(void) { sigset_t blocked; /* * block delivery of progress report signal to all threads */ sigemptyset(&blocked); sigaddset(&blocked, SIGHUP); sigaddset(&blocked, SIGALRM); pthread_sigmask(SIG_BLOCK, &blocked, NULL); } void create_work_queue( work_queue_t *wq, xfs_mount_t *mp, int nworkers) { int err; int i; memset(wq, 0, sizeof(work_queue_t)); pthread_cond_init(&wq->wakeup, NULL); pthread_mutex_init(&wq->lock, NULL); wq->mp = mp; wq->thread_count = nworkers; wq->threads = malloc(nworkers * sizeof(pthread_t)); wq->terminate = 0; for (i = 0; i < nworkers; i++) { err = pthread_create(&wq->threads[i], NULL, worker_thread, wq); if (err != 0) { do_error(_("cannot create worker threads, error = [%d] %s\n"), err, strerror(err)); } } } void queue_work( work_queue_t *wq, work_func_t func, xfs_agnumber_t agno, void *arg) { work_item_t *wi; wi = (work_item_t *)malloc(sizeof(work_item_t)); if (wi == NULL) do_error(_("cannot allocate worker item, error = [%d] %s\n"), errno, strerror(errno)); wi->function = func; wi->agno = agno; wi->arg = arg; wi->queue = wq; wi->next = NULL; /* * Now queue the new work structure to the work queue. */ pthread_mutex_lock(&wq->lock); if (wq->next_item == NULL) { wq->next_item = wi; ASSERT(wq->item_count == 0); pthread_cond_signal(&wq->wakeup); } else { wq->last_item->next = wi; } wq->last_item = wi; wq->item_count++; pthread_mutex_unlock(&wq->lock); } void destroy_work_queue( work_queue_t *wq) { int i; pthread_mutex_lock(&wq->lock); wq->terminate = 1; pthread_mutex_unlock(&wq->lock); pthread_cond_broadcast(&wq->wakeup); for (i = 0; i < wq->thread_count; i++) pthread_join(wq->threads[i], NULL); free(wq->threads); pthread_mutex_destroy(&wq->lock); pthread_cond_destroy(&wq->wakeup); } xfsprogs-4.9.0+nmu1ubuntu2/repair/threads.h0000644000000000000000000000151713063067172015564 0ustar #ifndef _XFS_REPAIR_THREADS_H_ #define _XFS_REPAIR_THREADS_H_ void thread_init(void); struct work_queue; typedef void work_func_t(struct work_queue *, xfs_agnumber_t, void *); typedef struct work_item { struct work_item *next; work_func_t *function; struct work_queue *queue; xfs_agnumber_t agno; void *arg; } work_item_t; typedef struct work_queue { work_item_t *next_item; work_item_t *last_item; int item_count; int thread_count; pthread_t *threads; xfs_mount_t *mp; pthread_mutex_t lock; pthread_cond_t wakeup; int terminate; } work_queue_t; void create_work_queue( work_queue_t *wq, xfs_mount_t *mp, int nworkers); void queue_work( work_queue_t *wq, work_func_t func, xfs_agnumber_t agno, void *arg); void destroy_work_queue( work_queue_t *wq); #endif /* _XFS_REPAIR_THREADS_H_ */ xfsprogs-4.9.0+nmu1ubuntu2/repair/versions.c0000644000000000000000000002023413063067172015772 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #define EXTERN #include "versions.h" #undef EXTERN #include "err_protos.h" #include "globals.h" void update_sb_version(xfs_mount_t *mp) { xfs_sb_t *sb; sb = &mp->m_sb; if (fs_attributes && !xfs_sb_version_hasattr(sb)) { ASSERT(fs_attributes_allowed); xfs_sb_version_addattr(sb); } if (fs_attributes2 && !xfs_sb_version_hasattr2(sb)) { ASSERT(fs_attributes2_allowed); xfs_sb_version_addattr2(sb); } /* V2 inode conversion is now always going to happen */ if (!(sb->sb_versionnum & XFS_SB_VERSION_NLINKBIT)) sb->sb_versionnum |= XFS_SB_VERSION_NLINKBIT; /* * fix up the superblock version number and feature bits, * turn off quota bits and flags if the filesystem doesn't * have quotas. */ if (fs_quotas) { if (!xfs_sb_version_hasquota(sb)) { ASSERT(fs_quotas_allowed); xfs_sb_version_addquota(sb); } /* * protect against stray bits in the quota flag field */ if (sb->sb_qflags & ~XFS_MOUNT_QUOTA_ALL) { /* * update the incore superblock, if we're in * no_modify mode, it'll never get flushed out * so this is ok. */ do_warn(_("bogus quota flags 0x%x set in superblock"), sb->sb_qflags & ~XFS_MOUNT_QUOTA_ALL); sb->sb_qflags &= XFS_MOUNT_QUOTA_ALL; if (!no_modify) do_warn(_(", bogus flags will be cleared\n")); else do_warn(_(", bogus flags would be cleared\n")); } } else { sb->sb_qflags = 0; if (xfs_sb_version_hasquota(sb)) { lost_quotas = 1; sb->sb_versionnum &= ~XFS_SB_VERSION_QUOTABIT; } } if (!fs_aligned_inodes && xfs_sb_version_hasalign(sb)) sb->sb_versionnum &= ~XFS_SB_VERSION_ALIGNBIT; } /* * returns 0 if things are fine, 1 if we don't understand * this superblock version. Sets superblock geometry-dependent * global variables. */ int parse_sb_version(xfs_sb_t *sb) { int issue_warning; fs_attributes = 0; fs_attributes2 = 0; fs_inode_nlink = 1; fs_quotas = 0; fs_aligned_inodes = 0; fs_sb_feature_bits = 0; fs_ino_alignment = 0; fs_has_extflgbit = 0; have_uquotino = 0; have_gquotino = 0; have_pquotino = 0; issue_warning = 0; if (sb->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) { do_warn(_("Shared Version bit set. Not supported. Ever.\n")); return 1; } if (sb->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) { do_warn(_("Shared Version bit set. Not supported. Ever.\n")); return 1; } if (sb->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) { do_warn(_("Shared Version bit set. Not supported. Ever.\n")); return 1; } /* * ok, check to make sure that the sb isn't newer * than we are */ if (xfs_sb_version_hasextflgbit(sb)) { fs_has_extflgbit = 1; if (!fs_has_extflgbit_allowed) { issue_warning = 1; do_warn( _("This filesystem has uninitialized extent flags.\n")); } } if (issue_warning) { do_warn( _("This filesystem uses feature(s) not yet supported in this release.\n" "Please run a more recent version of xfs_repair.\n")); return(1); } if (!xfs_sb_good_version(sb)) { do_warn(_("WARNING: unknown superblock version %d\n"), XFS_SB_VERSION_NUM(sb)); do_warn( _("This filesystem contains features not understood by this program.\n")); return(1); } if (XFS_SB_VERSION_NUM(sb) >= XFS_SB_VERSION_4) { if (!fs_sb_feature_bits_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twill be downgraded. This may cause loss of filesystem meta-data\n")); } else { do_warn( _("WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twould be downgraded. This might cause loss of filesystem\n" "\tmeta-data.\n")); } } else { fs_sb_feature_bits = 1; } } /* Look for V5 feature flags we don't know about */ if (XFS_SB_VERSION_NUM(sb) >= XFS_SB_VERSION_5 && (xfs_sb_has_compat_feature(sb, XFS_SB_FEAT_COMPAT_UNKNOWN) || xfs_sb_has_ro_compat_feature(sb, XFS_SB_FEAT_RO_COMPAT_UNKNOWN) || xfs_sb_has_incompat_feature(sb, XFS_SB_FEAT_INCOMPAT_UNKNOWN))) { do_warn( _("Superblock has unknown compat/rocompat/incompat features (0x%x/0x%x/0x%x).\n" "Using a more recent xfs_repair is recommended.\n"), sb->sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN, sb->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_UNKNOWN, sb->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_UNKNOWN); return 1; } if (xfs_sb_version_hasattr(sb)) { if (!fs_attributes_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attributes will be removed.\n")); } else { do_warn( _("WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attributes would be removed.\n")); } } else { fs_attributes = 1; } } if (xfs_sb_version_hasattr2(sb)) { if (!fs_attributes2_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attr2 attributes will be removed.\n")); } else { do_warn( _("WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attr2 attributes would be removed.\n")); } } else { fs_attributes2 = 1; } } if (!(sb->sb_versionnum & XFS_SB_VERSION_NLINKBIT)) { if (!no_modify) { do_warn( _("WARNING: you have a V1 inode filesystem. It will be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n")); } else { do_warn( _("WARNING: you have a V1 inode filesystem. It would be converted to a\n" "\tversion 2 inode filesystem. If you do not want this, run an older\n" "\tversion of xfs_repair.\n")); } } if (xfs_sb_version_hasquota(sb)) { if (!fs_quotas_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem will be downgraded and\n" "\tall quota information will be removed.\n")); } else { do_warn( _("WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem would be downgraded and\n" "\tall quota information would be removed.\n")); } } else { fs_quotas = 1; if (sb->sb_uquotino != 0 && sb->sb_uquotino != NULLFSINO) have_uquotino = 1; if (sb->sb_gquotino != 0 && sb->sb_gquotino != NULLFSINO) have_gquotino = 1; if (sb->sb_pquotino != 0 && sb->sb_pquotino != NULLFSINO) have_pquotino = 1; } } if (xfs_sb_version_hasalign(sb)) { if (fs_aligned_inodes_allowed) { fs_aligned_inodes = 1; fs_ino_alignment = sb->sb_inoalignmt; } else { if (!no_modify) { do_warn( _("WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem will be downgraded.\n" "\tThis will permanently degrade the performance of this filesystem.\n")); } else { do_warn( _("WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem would be downgraded.\n" "\tThis would permanently degrade the performance of this filesystem.\n")); } } } /* * calculate maximum file offset for this geometry */ fs_max_file_offset = 0x7fffffffffffffffLL >> sb->sb_blocklog; return(0); } xfsprogs-4.9.0+nmu1ubuntu2/repair/versions.h0000644000000000000000000000404013063067172015774 0ustar /* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XR_VERSIONS_H #define _XR_VERSIONS_H #ifndef EXTERN #define EXTERN extern #endif /* EXTERN */ /* * possible XFS filesystem features * * attributes (6.2) * inode version 2 (32-bit link counts) (6.2) * quotas (6.2+) * aligned inodes (6.2+) * * bitmask fields happend after 6.2. */ /* * filesystem feature global vars, set to 1 if the feature * is *allowed*, 0 otherwise. These can be set via command-line * options */ EXTERN int fs_attributes_allowed; EXTERN int fs_attributes2_allowed; EXTERN int fs_quotas_allowed; EXTERN int fs_aligned_inodes_allowed; EXTERN int fs_sb_feature_bits_allowed; EXTERN int fs_has_extflgbit_allowed; EXTERN int fs_shared_allowed; /* * filesystem feature global vars, set to 1 if the feature * is on, 0 otherwise */ EXTERN int fs_attributes; EXTERN int fs_attributes2; EXTERN int fs_inode_nlink; EXTERN int fs_quotas; EXTERN int fs_aligned_inodes; EXTERN int fs_sb_feature_bits; EXTERN int fs_has_extflgbit; EXTERN int fs_shared; /* * inode chunk alignment, fsblocks */ EXTERN xfs_extlen_t fs_ino_alignment; /* * modify superblock to reflect current state of global fs * feature vars above */ void update_sb_version(xfs_mount_t *mp); /* * parse current sb to set above feature vars */ int parse_sb_version(xfs_sb_t *sb); #endif /* _XR_VERSIONS_H */ xfsprogs-4.9.0+nmu1ubuntu2/repair/xfs_repair.c0000644000000000000000000006665613063067173016307 0ustar /* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" #include "libxlog.h" #include #include "xfs_multidisk.h" #include "avl.h" #include "avl64.h" #include "globals.h" #include "versions.h" #include "agheader.h" #include "protos.h" #include "incore.h" #include "err_protos.h" #include "prefetch.h" #include "threads.h" #include "progress.h" #include "dinode.h" #include "slab.h" #include "rmap.h" #define rounddown(x, y) (((x)/(y))*(y)) #define XR_MAX_SECT_SIZE (64 * 1024) /* * option tables for getsubopt calls */ /* * -o: user-supplied override options */ static char *o_opts[] = { #define ASSUME_XFS 0 "assume_xfs", #define PRE_65_BETA 1 "fs_is_pre_65_beta", #define IHASH_SIZE 2 "ihash", #define BHASH_SIZE 3 "bhash", #define AG_STRIDE 4 "ag_stride", #define FORCE_GEO 5 "force_geometry", #define PHASE2_THREADS 6 "phase2_threads", NULL }; /* * -c: conversion options */ static char *c_opts[] = { #define CONVERT_LAZY_COUNT 0 "lazycount", NULL }; static int bhash_option_used; static long max_mem_specified; /* in megabytes */ static int phase2_threads = 32; static void usage(void) { do_warn(_( "Usage: %s [options] device\n" "\n" "Options:\n" " -f The device is a file\n" " -L Force log zeroing. Do this as a last resort.\n" " -l logdev Specifies the device where the external log resides.\n" " -m maxmem Maximum amount of memory to be used in megabytes.\n" " -n No modify mode, just checks the filesystem for damage.\n" " -P Disables prefetching.\n" " -r rtdev Specifies the device where the realtime section resides.\n" " -v Verbose output.\n" " -c subopts Change filesystem parameters - use xfs_admin.\n" " -o subopts Override default behaviour, refer to man page.\n" " -t interval Reporting interval in seconds.\n" " -d Repair dangerously.\n" " -V Reports version and exits.\n"), progname); exit(1); } char * err_string(int err_code) { static char *err_message[XR_BAD_ERR_CODE]; static int done; if (!done) { err_message[XR_OK] = _("no error"); err_message[XR_BAD_MAGIC] = _("bad magic number"); err_message[XR_BAD_BLOCKSIZE] = _("bad blocksize field"); err_message[XR_BAD_BLOCKLOG] = _("bad blocksize log field"); err_message[XR_BAD_VERSION] = _("bad or unsupported version"); err_message[XR_BAD_INPROGRESS] = _("filesystem mkfs-in-progress bit set"); err_message[XR_BAD_FS_SIZE_DATA] = _("inconsistent filesystem geometry information"); err_message[XR_BAD_INO_SIZE_DATA] = _("bad inode size or inconsistent with number of inodes/block"), err_message[XR_BAD_SECT_SIZE_DATA] = _("bad sector size"); err_message[XR_AGF_GEO_MISMATCH] = _("AGF geometry info conflicts with filesystem geometry"); err_message[XR_AGI_GEO_MISMATCH] = _("AGI geometry info conflicts with filesystem geometry"); err_message[XR_SB_GEO_MISMATCH] = _("AG superblock geometry info conflicts with filesystem geometry"); err_message[XR_EOF] = _("attempted to perform I/O beyond EOF"); err_message[XR_BAD_RT_GEO_DATA] = _("inconsistent filesystem geometry in realtime filesystem component"); err_message[XR_BAD_INO_MAX_PCT] = _("maximum indicated percentage of inodes > 100%"); err_message[XR_BAD_INO_ALIGN] = _("inconsistent inode alignment value"); err_message[XR_INSUFF_SEC_SB] = _("not enough secondary superblocks with matching geometry"); err_message[XR_BAD_SB_UNIT] = _("bad stripe unit in superblock"); err_message[XR_BAD_SB_WIDTH] = _("bad stripe width in superblock"); err_message[XR_BAD_SVN] = _("bad shared version number in superblock"); err_message[XR_BAD_CRC] = _("bad CRC in superblock"); done = 1; } if (err_code < XR_OK || err_code >= XR_BAD_ERR_CODE) do_abort(_("bad error code - %d\n"), err_code); return(err_message[err_code]); } static void noval(char opt, char *tbl[], int idx) { do_warn(_("-%c %s option cannot have a value\n"), opt, tbl[idx]); usage(); } static void respec(char opt, char *tbl[], int idx) { do_warn("-%c ", opt); if (tbl) do_warn("%s ", tbl[idx]); do_warn(_("option respecified\n")); usage(); } static void unknown(char opt, char *s) { do_warn(_("unknown option -%c %s\n"), opt, s); usage(); } /* * sets only the global argument flags and variables */ static void process_args(int argc, char **argv) { char *p; int c; log_spec = 0; fs_is_dirty = 0; verbose = 0; no_modify = 0; dangerously = 0; isa_file = 0; zap_log = 0; dumpcore = 0; full_ino_ex_data = 0; delete_attr_ok = 1; force_geo = 0; assume_xfs = 0; copied_sunit = 0; sb_inoalignmt = 0; sb_unit = 0; sb_width = 0; fs_attributes_allowed = 1; fs_attributes2_allowed = 1; fs_quotas_allowed = 1; fs_aligned_inodes_allowed = 1; fs_sb_feature_bits_allowed = 1; fs_has_extflgbit_allowed = 1; pre_65_beta = 0; fs_shared_allowed = 1; ag_stride = 0; thread_count = 1; report_interval = PROG_RPT_DEFAULT; /* * XXX have to add suboption processing here * attributes, quotas, nlinks, aligned_inos, sb_fbits */ while ((c = getopt(argc, argv, "c:o:fl:m:r:LnDvVdPt:")) != EOF) { switch (c) { case 'D': dumpcore = 1; break; case 'o': p = optarg; while (*p != '\0') { char *val; switch (getsubopt(&p, o_opts, &val)) { case ASSUME_XFS: if (val) noval('o', o_opts, ASSUME_XFS); if (assume_xfs) respec('o', o_opts, ASSUME_XFS); assume_xfs = 1; break; case PRE_65_BETA: if (val) noval('o', o_opts, PRE_65_BETA); if (pre_65_beta) respec('o', o_opts, PRE_65_BETA); pre_65_beta = 1; break; case IHASH_SIZE: do_warn( _("-o ihash option has been removed and will be ignored\n")); break; case BHASH_SIZE: if (max_mem_specified) do_abort( _("-o bhash option cannot be used with -m option\n")); libxfs_bhash_size = (int)strtol(val, NULL, 0); bhash_option_used = 1; break; case AG_STRIDE: ag_stride = (int)strtol(val, NULL, 0); break; case FORCE_GEO: if (val) noval('o', o_opts, FORCE_GEO); if (force_geo) respec('o', o_opts, FORCE_GEO); force_geo = 1; break; case PHASE2_THREADS: phase2_threads = (int)strtol(val, NULL, 0); break; default: unknown('o', val); break; } } break; case 'c': p = optarg; while (*p) { char *val; switch (getsubopt(&p, c_opts, &val)) { case CONVERT_LAZY_COUNT: lazy_count = (int)strtol(val, NULL, 0); convert_lazy_count = 1; break; default: unknown('c', val); break; } } break; case 'l': log_name = optarg; log_spec = 1; break; case 'r': rt_name = optarg; rt_spec = 1; break; case 'f': isa_file = 1; break; case 'm': if (bhash_option_used) do_abort(_("-m option cannot be used with " "-o bhash option\n")); max_mem_specified = strtol(optarg, NULL, 0); break; case 'L': zap_log = 1; break; case 'n': no_modify = 1; break; case 'd': dangerously = 1; break; case 'v': verbose++; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); case 'P': do_prefetch = 0; break; case 't': report_interval = (int)strtol(optarg, NULL, 0); break; case '?': usage(); } } if (argc - optind != 1) usage(); if ((fs_name = argv[optind]) == NULL) usage(); } void __attribute__((noreturn)) do_error(char const *msg, ...) { va_list args; fprintf(stderr, _("\nfatal error -- ")); va_start(args, msg); vfprintf(stderr, msg, args); if (dumpcore) abort(); exit(1); } /* * like do_error, only the error is internal, no system * error so no oserror processing */ void __attribute__((noreturn)) do_abort(char const *msg, ...) { va_list args; va_start(args, msg); vfprintf(stderr, msg, args); if (dumpcore) abort(); exit(1); } void do_warn(char const *msg, ...) { va_list args; fs_is_dirty = 1; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); } /* no formatting */ void do_log(char const *msg, ...) { va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); } static void calc_mkfs(xfs_mount_t *mp) { xfs_agblock_t fino_bno; int do_inoalign; do_inoalign = mp->m_sinoalign; /* * Pre-calculate the geometry of ag 0. We know what it looks like * because we know what mkfs does: 2 allocation btree roots (by block * and by size), the inode allocation btree root, the free inode * allocation btree root (if enabled) and some number of blocks to * prefill the agfl. * * Because the current shape of the btrees may differ from the current * shape, we open code the mkfs freelist block count here. mkfs creates * single level trees, so the calculation is pertty straight forward for * the trees that use the AGFL. */ bnobt_root = howmany(4 * mp->m_sb.sb_sectsize, mp->m_sb.sb_blocksize); bcntbt_root = bnobt_root + 1; inobt_root = bnobt_root + 2; fino_bno = inobt_root + (2 * min(2, mp->m_ag_maxlevels)) + 1; if (xfs_sb_version_hasfinobt(&mp->m_sb)) fino_bno++; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { fino_bno += min(2, mp->m_rmap_maxlevels); /* agfl blocks */ fino_bno++; } if (xfs_sb_version_hasreflink(&mp->m_sb)) fino_bno++; /* * If the log is allocated in the first allocation group we need to * add the number of blocks used by the log to the above calculation. * * This can happens with filesystems that only have a single * allocation group, or very odd geometries created by old mkfs * versions on very small filesystems. */ if (mp->m_sb.sb_logstart && XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == 0) { /* * XXX(hch): verify that sb_logstart makes sense? */ fino_bno += mp->m_sb.sb_logblocks; } /* * ditto the location of the first inode chunks in the fs ('/') */ if (xfs_sb_version_hasdalign(&mp->m_sb) && do_inoalign) { first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, roundup(fino_bno, mp->m_sb.sb_unit), 0); } else if (xfs_sb_version_hasalign(&mp->m_sb) && mp->m_sb.sb_inoalignmt > 1) { first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, roundup(fino_bno, mp->m_sb.sb_inoalignmt), 0); } else { first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno, 0); } ASSERT(mp->m_ialloc_blks > 0); if (mp->m_ialloc_blks > 1) last_prealloc_ino = first_prealloc_ino + XFS_INODES_PER_CHUNK; else last_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno + 1, 0); /* * now the first 3 inodes in the system */ if (mp->m_sb.sb_rootino != first_prealloc_ino) { do_warn( _("sb root inode value %" PRIu64 " %sinconsistent with calculated value %u\n"), mp->m_sb.sb_rootino, (mp->m_sb.sb_rootino == NULLFSINO ? "(NULLFSINO) ":""), first_prealloc_ino); if (!no_modify) do_warn( _("resetting superblock root inode pointer to %u\n"), first_prealloc_ino); else do_warn( _("would reset superblock root inode pointer to %u\n"), first_prealloc_ino); /* * just set the value -- safe since the superblock * doesn't get flushed out if no_modify is set */ mp->m_sb.sb_rootino = first_prealloc_ino; } if (mp->m_sb.sb_rbmino != first_prealloc_ino + 1) { do_warn( _("sb realtime bitmap inode %" PRIu64 " %sinconsistent with calculated value %u\n"), mp->m_sb.sb_rbmino, (mp->m_sb.sb_rbmino == NULLFSINO ? "(NULLFSINO) ":""), first_prealloc_ino + 1); if (!no_modify) do_warn( _("resetting superblock realtime bitmap ino pointer to %u\n"), first_prealloc_ino + 1); else do_warn( _("would reset superblock realtime bitmap ino pointer to %u\n"), first_prealloc_ino + 1); /* * just set the value -- safe since the superblock * doesn't get flushed out if no_modify is set */ mp->m_sb.sb_rbmino = first_prealloc_ino + 1; } if (mp->m_sb.sb_rsumino != first_prealloc_ino + 2) { do_warn( _("sb realtime summary inode %" PRIu64 " %sinconsistent with calculated value %u\n"), mp->m_sb.sb_rsumino, (mp->m_sb.sb_rsumino == NULLFSINO ? "(NULLFSINO) ":""), first_prealloc_ino + 2); if (!no_modify) do_warn( _("resetting superblock realtime summary ino pointer to %u\n"), first_prealloc_ino + 2); else do_warn( _("would reset superblock realtime summary ino pointer to %u\n"), first_prealloc_ino + 2); /* * just set the value -- safe since the superblock * doesn't get flushed out if no_modify is set */ mp->m_sb.sb_rsumino = first_prealloc_ino + 2; } } /* * v5 superblock metadata track the LSN of last modification and thus require * that the current LSN is always moving forward. The current LSN is reset if * the log has been cleared, which puts the log behind parts of the filesystem * on-disk and can disrupt log recovery. * * We have tracked the maximum LSN of every piece of metadata that has been read * in via the read verifiers. Compare the max LSN with the log and if the log is * behind, bump the cycle number and reformat the log. */ static void format_log_max_lsn( struct xfs_mount *mp) { struct xlog *log = mp->m_log; int max_cycle; int max_block; int new_cycle; xfs_daddr_t logstart; xfs_daddr_t logblocks; int logversion; if (!xfs_sb_version_hascrc(&mp->m_sb)) return; /* * If the log is ahead of the highest metadata LSN we've seen, we're * safe and there's nothing to do. */ max_cycle = CYCLE_LSN(libxfs_max_lsn); max_block = BLOCK_LSN(libxfs_max_lsn); if (max_cycle < log->l_curr_cycle || (max_cycle == log->l_curr_cycle && max_block < log->l_curr_block)) return; /* * Going to the next cycle should be sufficient but we bump by a few * counts to help cover any metadata LSNs we could have missed. */ new_cycle = max_cycle + 3; logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); logblocks = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1; do_warn(_("Maximum metadata LSN (%d:%d) is ahead of log (%d:%d).\n"), max_cycle, max_block, log->l_curr_cycle, log->l_curr_block); if (no_modify) { do_warn(_("Would format log to cycle %d.\n"), new_cycle); return; } do_warn(_("Format log to cycle %d.\n"), new_cycle); libxfs_log_clear(log->l_dev, NULL, logstart, logblocks, &mp->m_sb.sb_uuid, logversion, mp->m_sb.sb_logsunit, XLOG_FMT, new_cycle, true); } /* * mkfs increases the AG count for "multidisk" configurations, we want * to target these for an increase in thread count. Hence check the superlock * geometry information to determine if mkfs considered this a multidisk * configuration. */ static bool is_multidisk_filesystem( struct xfs_mount *mp) { struct xfs_sb *sbp = &mp->m_sb; /* High agcount filesystems are always considered "multidisk" */ if (sbp->sb_agcount >= XFS_MULTIDISK_AGCOUNT) return true; /* * If it doesn't have a sunit/swidth, mkfs didn't consider it a * multi-disk array, so we don't either. */ if (!sbp->sb_unit) return false; ASSERT(sbp->sb_width); return true; } int main(int argc, char **argv) { xfs_mount_t *temp_mp; xfs_mount_t *mp; xfs_dsb_t *dsb; xfs_buf_t *sbp; xfs_mount_t xfs_m; struct xlog log = {0}; char *msgbuf; struct xfs_sb psb; int rval; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); dinode_bmbt_translation_init(); temp_mp = &xfs_m; setbuf(stdout, NULL); process_args(argc, argv); xfs_init(&x); msgbuf = malloc(DURATION_BUF_SIZE); timestamp(PHASE_START, 0, NULL); timestamp(PHASE_END, 0, NULL); /* do phase1 to make sure we have a superblock */ phase1(temp_mp); timestamp(PHASE_END, 1, NULL); if (no_modify && primary_sb_modified) { do_warn(_("Primary superblock would have been modified.\n" "Cannot proceed further in no_modify mode.\n" "Exiting now.\n")); exit(1); } rval = get_sb(&psb, 0, XFS_MAX_SECTORSIZE, 0); if (rval != XR_OK) { do_warn(_("Primary superblock bad after phase 1!\n" "Exiting now.\n")); exit(1); } /* -f forces this, but let's be nice and autodetect it, as well. */ if (!isa_file) { int fd = libxfs_device_to_fd(x.ddev); struct stat statbuf; if (fstat(fd, &statbuf) < 0) do_warn(_("%s: couldn't stat \"%s\"\n"), progname, fs_name); else if (S_ISREG(statbuf.st_mode)) isa_file = 1; } /* * if the sector size of the filesystem we are trying to repair is * smaller than that of the underlying filesystem (i.e. we are repairing * an image), the we have to turn off direct IO because we cannot do IO * smaller than the host filesystem's sector size. */ if (isa_file) { int fd = libxfs_device_to_fd(x.ddev); struct xfs_fsop_geom_v1 geom = { 0 }; if (ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &geom) < 0) { do_log(_("Cannot get host filesystem geometry.\n" "Repair may fail if there is a sector size mismatch between\n" "the image and the host filesystem.\n")); geom.sectsize = BBSIZE; } if (psb.sb_sectsize < geom.sectsize) { long old_flags; old_flags = fcntl(fd, F_GETFL, 0); if (fcntl(fd, F_SETFL, old_flags & ~O_DIRECT) < 0) { do_warn(_( "Sector size on host filesystem larger than image sector size.\n" "Cannot turn off direct IO, so exiting.\n")); exit(1); } } } /* * Prepare the mount structure. Point the log reference to our local * copy so it's available to the various phases. The log bits are * initialized in phase 2. */ memset(&xfs_m, 0, sizeof(xfs_mount_t)); mp = libxfs_mount(&xfs_m, &psb, x.ddev, x.logdev, x.rtdev, 0); if (!mp) { fprintf(stderr, _("%s: cannot repair this filesystem. Sorry.\n"), progname); exit(1); } mp->m_log = &log; /* Spit out function & line on these corruption macros */ if (verbose > 2) mp->m_flags |= LIBXFS_MOUNT_WANT_CORRUPTED; /* * set XFS-independent status vars from the mount/sb structure */ glob_agcount = mp->m_sb.sb_agcount; chunks_pblock = mp->m_sb.sb_inopblock / XFS_INODES_PER_CHUNK; max_symlink_blocks = libxfs_symlink_blocks(mp, MAXPATHLEN); inodes_per_cluster = MAX(mp->m_sb.sb_inopblock, mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog); /* * Automatic striding for high agcount filesystems. * * More AGs indicates that the filesystem is either large or can handle * more IO parallelism. Either way, we should try to process multiple * AGs at a time in such a configuration to try to saturate the * underlying storage and speed the repair process. Only do this if * prefetching is enabled. * * Given mkfs defaults for 16AGs for "multidisk" configurations, we want * to target these for an increase in thread count. Hence a stride value * of 15 is chosen to ensure we get at least 2 AGs being scanned at once * on such filesystems. * * Limit the maximum thread count based on the available CPU power that * is available. If we use too many threads, we might run out of memory * and CPU power before we run out of IO concurrency. We limit to 8 * threads/CPU as this is enough threads to saturate a CPU on fast * devices, yet few enough that it will saturate but won't overload slow * devices. * * Multidisk filesystems can handle more IO parallelism so we should try * to process multiple AGs at a time in such a configuration to try to * saturate the underlying storage and speed the repair process. Only do * this if prefetching is enabled. */ if (!ag_stride && do_prefetch && is_multidisk_filesystem(mp)) { /* * For small agcount multidisk systems, just double the * parallelism. For larger AG count filesystems (32 and above) * use more parallelism, and linearly increase the parallelism * with the number of AGs. */ ag_stride = min(glob_agcount, XFS_MULTIDISK_AGCOUNT / 2) - 1; } if (ag_stride) { int max_threads = platform_nproc() * 8; thread_count = (glob_agcount + ag_stride - 1) / ag_stride; while (thread_count > max_threads) { ag_stride *= 2; thread_count = (glob_agcount + ag_stride - 1) / ag_stride; } if (thread_count > 0) thread_init(); else { thread_count = 1; ag_stride = 0; } } if (ag_stride && report_interval) { init_progress_rpt(); if (msgbuf) { do_log(_(" - reporting progress in intervals of %s\n"), duration(report_interval, msgbuf)); } } /* * Adjust libxfs cache sizes based on system memory, * filesystem size and inode count. * * We'll set the cache size based on 3/4s the memory minus * space used by the inode AVL tree and block usage map. * * Inode AVL tree space is approximately 4 bytes per inode, * block usage map is currently 1 byte for 2 blocks. * * We assume most blocks will be inode clusters. * * Calculations are done in kilobyte units. */ if (!bhash_option_used || max_mem_specified) { unsigned long mem_used; unsigned long max_mem; struct rlimit rlim; libxfs_bcache_purge(); cache_destroy(libxfs_bcache); mem_used = (mp->m_sb.sb_icount >> (10 - 2)) + (mp->m_sb.sb_dblocks >> (10 + 1)) + 50000; /* rough estimate of 50MB overhead */ max_mem = max_mem_specified ? max_mem_specified * 1024 : libxfs_physmem() * 3 / 4; if (getrlimit(RLIMIT_AS, &rlim) != -1 && rlim.rlim_cur != RLIM_INFINITY) { rlim.rlim_cur = rlim.rlim_max; setrlimit(RLIMIT_AS, &rlim); /* use approximately 80% of rlimit to avoid overrun */ max_mem = MIN(max_mem, rlim.rlim_cur / 1280); } else max_mem = MIN(max_mem, (LONG_MAX >> 10) + 1); if (verbose > 1) do_log( _(" - max_mem = %lu, icount = %" PRIu64 ", imem = %" PRIu64 ", dblock = %" PRIu64 ", dmem = %" PRIu64 "\n"), max_mem, mp->m_sb.sb_icount, mp->m_sb.sb_icount >> (10 - 2), mp->m_sb.sb_dblocks, mp->m_sb.sb_dblocks >> (10 + 1)); if (max_mem <= mem_used) { if (max_mem_specified) { do_abort( _("Required memory for repair is greater that the maximum specified\n" "with the -m option. Please increase it to at least %lu.\n"), mem_used / 1024); } do_log( _("Memory available for repair (%luMB) may not be sufficient.\n" "At least %luMB is needed to repair this filesystem efficiently\n" "If repair fails due to lack of memory, please\n"), max_mem / 1024, mem_used / 1024); if (do_prefetch) do_log( _("turn prefetching off (-P) to reduce the memory footprint.\n")); else do_log( _("increase system RAM and/or swap space to at least %luMB.\n"), mem_used * 2 / 1024); max_mem = mem_used; } max_mem -= mem_used; if (max_mem >= (1 << 30)) max_mem = 1 << 30; libxfs_bhash_size = max_mem / (HASH_CACHE_RATIO * (mp->m_inode_cluster_size >> 10)); if (libxfs_bhash_size < 512) libxfs_bhash_size = 512; if (verbose) do_log(_(" - block cache size set to %d entries\n"), libxfs_bhash_size * HASH_CACHE_RATIO); libxfs_bcache = cache_init(0, libxfs_bhash_size, &libxfs_bcache_operations); } /* * calculate what mkfs would do to this filesystem */ calc_mkfs(mp); /* * initialize block alloc map */ init_bmaps(mp); incore_ino_init(mp); incore_ext_init(mp); rmaps_init(mp); /* initialize random globals now that we know the fs geometry */ inodes_per_block = mp->m_sb.sb_inopblock; if (parse_sb_version(&mp->m_sb)) { do_warn( _("Found unsupported filesystem features. Exiting now.\n")); return(1); } /* make sure the per-ag freespace maps are ok so we can mount the fs */ phase2(mp, phase2_threads); timestamp(PHASE_END, 2, NULL); if (do_prefetch) init_prefetch(mp); phase3(mp, phase2_threads); timestamp(PHASE_END, 3, NULL); phase4(mp); timestamp(PHASE_END, 4, NULL); if (no_modify) printf(_("No modify flag set, skipping phase 5\n")); else { phase5(mp); } timestamp(PHASE_END, 5, NULL); /* * Done with the block usage maps, toss them... */ rmaps_free(mp); free_bmaps(mp); if (!bad_ino_btree) { phase6(mp); timestamp(PHASE_END, 6, NULL); phase7(mp, phase2_threads); timestamp(PHASE_END, 7, NULL); } else { do_warn( _("Inode allocation btrees are too corrupted, skipping phases 6 and 7\n")); } if (lost_quotas && !have_uquotino && !have_gquotino && !have_pquotino) { if (!no_modify) { do_warn( _("Warning: no quota inodes were found. Quotas disabled.\n")); } else { do_warn( _("Warning: no quota inodes were found. Quotas would be disabled.\n")); } } else if (lost_quotas) { if (!no_modify) { do_warn( _("Warning: quota inodes were cleared. Quotas disabled.\n")); } else { do_warn( _("Warning: quota inodes would be cleared. Quotas would be disabled.\n")); } } else { if (lost_uquotino) { if (!no_modify) { do_warn( _("Warning: user quota information was cleared.\n" "User quotas can not be enforced until limit information is recreated.\n")); } else { do_warn( _("Warning: user quota information would be cleared.\n" "User quotas could not be enforced until limit information was recreated.\n")); } } if (lost_gquotino) { if (!no_modify) { do_warn( _("Warning: group quota information was cleared.\n" "Group quotas can not be enforced until limit information is recreated.\n")); } else { do_warn( _("Warning: group quota information would be cleared.\n" "Group quotas could not be enforced until limit information was recreated.\n")); } } if (lost_pquotino) { if (!no_modify) { do_warn( _("Warning: project quota information was cleared.\n" "Project quotas can not be enforced until limit information is recreated.\n")); } else { do_warn( _("Warning: project quota information would be cleared.\n" "Project quotas could not be enforced until limit information was recreated.\n")); } } } if (ag_stride && report_interval) stop_progress_rpt(); if (no_modify) { /* * Warn if the current LSN is problematic and the log requires a * reformat. */ format_log_max_lsn(mp); do_log( _("No modify flag set, skipping filesystem flush and exiting.\n")); if (verbose) summary_report(); if (fs_is_dirty) return(1); return(0); } /* * Clear the quota flags if they're on. */ sbp = libxfs_getsb(mp, 0); if (!sbp) do_error(_("couldn't get superblock\n")); dsb = XFS_BUF_TO_SBP(sbp); if (be16_to_cpu(dsb->sb_qflags) & XFS_ALL_QUOTA_CHKD) { do_warn(_("Note - quota info will be regenerated on next " "quota mount.\n")); dsb->sb_qflags &= cpu_to_be16(~XFS_ALL_QUOTA_CHKD); } if (copied_sunit) { do_warn( _("Note - stripe unit (%d) and width (%d) were copied from a backup superblock.\n" "Please reset with mount -o sunit=,swidth= if necessary\n"), be32_to_cpu(dsb->sb_unit), be32_to_cpu(dsb->sb_width)); } libxfs_writebuf(sbp, 0); /* * Done. Flush all cached buffers and inodes first to ensure all * verifiers are run (where we discover the max metadata LSN), reformat * the log if necessary and unmount. */ libxfs_bcache_flush(); format_log_max_lsn(mp); libxfs_umount(mp); if (x.rtdev) libxfs_device_close(x.rtdev); if (x.logdev && x.logdev != x.ddev) libxfs_device_close(x.logdev); libxfs_device_close(x.ddev); if (verbose) summary_report(); do_log(_("done\n")); if (dangerously && !no_modify) do_warn( _("Repair of readonly mount complete. Immediate reboot encouraged.\n")); pftrace_done(); free(msgbuf); return (0); } xfsprogs-4.9.0+nmu1ubuntu2/rtcp/0000755000000000000000000000000013063067174013445 5ustar xfsprogs-4.9.0+nmu1ubuntu2/rtcp/Makefile0000644000000000000000000000056413063067171015107 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_rtcp CFILES = xfs_rtcp.c LLDFLAGS = -static default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: -include .dep xfsprogs-4.9.0+nmu1ubuntu2/rtcp/xfs_rtcp.c0000644000000000000000000002062513063067171015443 0ustar /* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libxfs.h" int rtcp(char *, char *, int); int xfsrtextsize(char *path); int pflag; char *progname; void usage(void) { fprintf(stderr, _("%s [-e extsize] [-p] [-V] source target\n"), progname); exit(2); } int main(int argc, char **argv) { int c, i, r, errflg = 0; struct stat s2; int extsize = - 1; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((c = getopt(argc, argv, "pe:V")) != EOF) { switch (c) { case 'e': extsize = atoi(optarg); break; case 'p': pflag = 1; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); default: errflg++; } } /* * Check for sufficient arguments or a usage error. */ argc -= optind; argv = &argv[optind]; if (argc < 2) { fprintf(stderr, _("%s: must specify files to copy\n"), progname); errflg++; } if (errflg) usage(); /* * If there is more than a source and target, * the last argument (the target) must be a directory * which really exists. */ if (argc > 2) { if (stat(argv[argc-1], &s2) < 0) { fprintf(stderr, _("%s: stat of %s failed\n"), progname, argv[argc-1]); exit(2); } if (!S_ISDIR(s2.st_mode)) { fprintf(stderr, _("%s: final argument is not directory\n"), progname); usage(); } } /* * Perform a multiple argument rtcp by * multiple invocations of rtcp(). */ r = 0; for (i = 0; i < argc-1; i++) r += rtcp(argv[i], argv[argc-1], extsize); /* * Show errors by nonzero exit code. */ exit(r?2:0); } int rtcp( char *source, char *target, int fextsize) { int fromfd, tofd, readct, writect, iosz, reopen; int remove = 0, rtextsize; char *sp, *fbuf, *ptr; char tbuf[ PATH_MAX ]; struct stat s1, s2; struct fsxattr fsxattr; struct dioattr dioattr; /* * While source or target have trailing /, remove them * unless only "/". */ sp = source + strlen(source); if (sp) { while (*--sp == '/' && sp > source) *sp = '\0'; } sp = target + strlen(target); if (sp) { while (*--sp == '/' && sp > target) *sp = '\0'; } if ( stat(source, &s1) ) { fprintf(stderr, _("%s: failed stat on %s: %s\n"), progname, source, strerror(errno)); return( -1); } /* * check for a realtime partition */ snprintf(tbuf, sizeof(tbuf), "%s", target); if ( stat(target, &s2) ) { if (!S_ISDIR(s2.st_mode)) { /* take out target file name */ if ((ptr = strrchr(tbuf, '/')) != NULL) *ptr = '\0'; else snprintf(tbuf, sizeof(tbuf), "."); } } if ( (rtextsize = xfsrtextsize( tbuf )) <= 0 ) { fprintf(stderr, _("%s: %s filesystem has no realtime partition\n"), progname, tbuf); return( -1 ); } /* * check if target is a directory */ snprintf(tbuf, sizeof(tbuf), "%s", target); if ( !stat(target, &s2) ) { if (S_ISDIR(s2.st_mode)) { snprintf(tbuf, sizeof(tbuf), "%s/%s", target, basename(source)); } } if ( stat(tbuf, &s2) ) { /* * create the file if it does not exist */ if ( (tofd = open(tbuf, O_RDWR|O_CREAT|O_DIRECT, 0666)) < 0 ) { fprintf(stderr, _("%s: open of %s failed: %s\n"), progname, tbuf, strerror(errno)); return( -1 ); } remove = 1; /* * mark the file as a realtime file */ fsxattr.fsx_xflags = FS_XFLAG_REALTIME; if (fextsize != -1 ) fsxattr.fsx_extsize = fextsize; else fsxattr.fsx_extsize = 0; if ( xfsctl(tbuf, tofd, FS_IOC_FSSETXATTR, &fsxattr) ) { fprintf(stderr, _("%s: set attributes on %s failed: %s\n"), progname, tbuf, strerror(errno)); close( tofd ); unlink( tbuf ); return( -1 ); } } else { /* * open existing file */ if ( (tofd = open(tbuf, O_RDWR|O_DIRECT)) < 0 ) { fprintf(stderr, _("%s: open of %s failed: %s\n"), progname, tbuf, strerror(errno)); return( -1 ); } if ( xfsctl(tbuf, tofd, FS_IOC_FSGETXATTR, &fsxattr) ) { fprintf(stderr, _("%s: get attributes of %s failed: %s\n"), progname, tbuf, strerror(errno)); close( tofd ); return( -1 ); } /* * check if the existing file is already a realtime file */ if ( !(fsxattr.fsx_xflags & FS_XFLAG_REALTIME) ) { fprintf(stderr, _("%s: %s is not a realtime file.\n"), progname, tbuf); close( tofd ); return( -1 ); } /* * check for matching extent size */ if ( (fextsize != -1) && (fsxattr.fsx_extsize != fextsize) ) { fprintf(stderr, _("%s: %s file extent size is %d, " "instead of %d.\n"), progname, tbuf, fsxattr.fsx_extsize, fextsize); close( tofd ); return( -1 ); } } /* * open the source file */ reopen = 0; if ( (fromfd = open(source, O_RDONLY|O_DIRECT)) < 0 ) { fprintf(stderr, _("%s: open of %s source failed: %s\n"), progname, source, strerror(errno)); close( tofd ); if (remove) unlink( tbuf ); return( -1 ); } fsxattr.fsx_xflags = 0; fsxattr.fsx_extsize = 0; if ( xfsctl(source, fromfd, FS_IOC_FSGETXATTR, &fsxattr) ) { reopen = 1; } else { if (! (fsxattr.fsx_xflags & FS_XFLAG_REALTIME) ){ fprintf(stderr, _("%s: %s is not a realtime file.\n"), progname, source); reopen = 1; } } if (reopen) { close( fromfd ); if ( (fromfd = open(source, O_RDONLY )) < 0 ) { fprintf(stderr, _("%s: open of %s source failed: %s\n"), progname, source, strerror(errno)); close( tofd ); if (remove) unlink( tbuf ); return( -1 ); } } /* * get direct I/O parameters */ if ( xfsctl(tbuf, tofd, XFS_IOC_DIOINFO, &dioattr) ) { fprintf(stderr, _("%s: couldn't get direct I/O information: %s\n"), progname, strerror(errno)); close( fromfd ); close( tofd ); if ( remove ) unlink( tbuf ); return( -1 ); } if ( rtextsize % dioattr.d_miniosz ) { fprintf(stderr, _("%s: extent size %d not a multiple of %d.\n"), progname, rtextsize, dioattr.d_miniosz); close( fromfd ); close( tofd ); if ( remove ) unlink( tbuf ); return( -1 ); } /* * Check that the source file size is a multiple of the * file system block size. */ if ( s1.st_size % dioattr.d_miniosz ) { printf(_("The size of %s is not a multiple of %d.\n"), source, dioattr.d_miniosz); if ( pflag ) { printf(_("%s will be padded to %lld bytes.\n"), tbuf, (long long) (((s1.st_size / dioattr.d_miniosz) + 1) * dioattr.d_miniosz) ); } else { printf(_("Use the -p option to pad %s to a " "size which is a multiple of %d bytes.\n"), tbuf, dioattr.d_miniosz); close( fromfd ); close( tofd ); if ( remove ) unlink( tbuf ); return( -1 ); } } iosz = dioattr.d_miniosz; fbuf = memalign( dioattr.d_mem, iosz); memset(fbuf, 0, iosz); /* * read the entire source file */ while ( ( readct = read( fromfd, fbuf, iosz) ) != 0 ) { /* * if there is a read error - break */ if (readct < 0 ) { break; } /* * if there is a short read, pad to a block boundary */ if ( readct != iosz ) { if ( (readct % dioattr.d_miniosz) != 0 ) { readct = ( (readct/dioattr.d_miniosz) + 1 ) * dioattr.d_miniosz; } } /* * write to target file */ writect = write( tofd, fbuf, readct); if ( writect != readct ) { fprintf(stderr, _("%s: write error: %s\n"), progname, strerror(errno)); close(fromfd); close(tofd); free( fbuf ); return( -1 ); } memset( fbuf, 0, iosz); } close(fromfd); close(tofd); free( fbuf ); return( 0 ); } /* * Determine the realtime extent size of the XFS file system */ int xfsrtextsize( char *path) { int fd, rval, rtextsize; xfs_fsop_geom_v1_t geo; fd = open( path, O_RDONLY ); if ( fd < 0 ) { fprintf(stderr, _("%s: could not open %s: %s\n"), progname, path, strerror(errno)); return -1; } rval = xfsctl( path, fd, XFS_IOC_FSGEOMETRY_V1, &geo ); close(fd); if ( rval < 0 ) return -1; rtextsize = geo.rtextsize * geo.blocksize; return rtextsize; } xfsprogs-4.9.0+nmu1ubuntu2/tools/0000755000000000000000000000000013063067174013635 5ustar xfsprogs-4.9.0+nmu1ubuntu2/tools/find-api-violations.sh0000755000000000000000000000252113033541503020036 0ustar #!/bin/bash # Find libxfs API violations -- calls to functions defined in libxfs/*.c that # don't use the libxfs wrappers; or failing to negate the integer return # values. # NOTE: This script doesn't look for API violations in function parameters. tool_dirs="copy db estimate fs fsck fsr growfs io mdrestore mkfs quota repair rtcp" # Calls to xfs_* functions in libxfs/*.c without the libxfs_ prefix find_possible_api_calls() { grep -rn '[[:space:],-(]xfs_[a-z_]*(' $tool_dirs | sed -e 's/^.*\(xfs_[a-z_]*\)(.*$/\1/g' | sort | uniq } check_if_api_calls() { while read f; do grep "^$f(" libxfs/*.c; done | sed -e 's/^.*:xfs_/xfs_/g' -e 's/.$//g' } find_libxfs_violations() { grep -r -n -f <(find_possible_api_calls | check_if_api_calls | sed -e 's/^/[[:space:],-(]/g' -e 's/$/(/g' ) $tool_dirs } # libxfs calls without negated error codes find_errcode_violations() { grep -r -n 'err.* = libxfs' $tool_dirs } # Find xfs_* calls that are in the libxfs definition list find_possible_libxfs_api_calls() { grep '#define[[:space:]]*xfs' libxfs/libxfs_api_defs.h | awk '{print $2}' } find_libxfs_api_violations() { grep -r -n -f <(find_possible_libxfs_api_calls | sed -e 's/^/[[:space:],-(]/g' -e 's/$/(/g') $tool_dirs } (find_libxfs_violations ; find_errcode_violations ; find_libxfs_api_violations) | sort -g -t ':' -k 2 | sort -g -t ':' -k 1 | uniq xfsprogs-4.9.0+nmu1ubuntu2/tools/libxfs-apply0000755000000000000000000002337013063067170016176 0ustar #!/bin/bash # 2 args: # libxfs-apply usage() { echo $* echo echo "Usage:" echo " libxfs-apply [--verbose] --source --commit " echo " libxfs-apply --patch " echo echo "libxfs-apply should be run in the destination git repository." exit } cleanup() { rm -f $PATCH } # output to stderr so it is not caught by file redirects fail() { >&2 echo "Fail:" >&2 echo $* cleanup exit } # filterdiff 0.3.4 is the first version that handles git diff metadata (almost) # correctly. It just doesn't work properly in prior versions, so those versions # can't be used to extract the commit message prior to the diff. Hence just # abort and tell the user to upgrade if an old version is detected. We need to # check against x.y.z version numbers here. _version=`filterdiff --version | cut -d " " -f 5` _major=`echo $_version | cut -d "." -f 1` _minor=`echo $_version | cut -d "." -f 2` _patch=`echo $_version | cut -d "." -f 3` if [ $_major -eq 0 ]; then if [ $_minor -lt 3 ]; then fail "filterdiff $_version found. 0.3.4 or greater is required." fi if [ $_minor -eq 3 -a $_patch -le 3 ]; then fail "filterdiff $_version found. 0.3.4 or greater is required." fi fi # We should see repository contents we recognise, both at the source and # destination. Kernel repositorys will have fs/xfs/libxfs, and xfsprogs # repositories will have libxcmd. SOURCE="kernel" check_repo() { if [ ! -d "fs/xfs/libxfs" -a ! -d "libxcmd" ]; then usage "$1 repository contents not recognised!" fi if [ -d "$REPO/libxcmd" ]; then SOURCE="xfsprogs" fi } REPO= PATCH= COMMIT_ID= VERBOSE= GUILT=0 while [ $# -gt 0 ]; do case "$1" in --source) REPO=$2 ; shift ;; --patch) PATCH=$2; shift ;; --commit) COMMIT_ID=$2 ; shift ;; --verbose) VERBOSE=true ;; *) usage ;; esac shift done if [ -n "$PATCH" ]; then if [ -n "$REPO" -o -n "$COMMIT_ID" ]; then usage "Need to specify either patch or source repo/commit" fi VERBOSE=true elif [ -z "$REPO" -o -z "$COMMIT_ID" ]; then usage "Need to specify both source repo and commit id" fi check_repo Destination # Are we using guilt? This works even if no patch is applied. guilt top &> /dev/null if [ $? -eq 0 ]; then GUILT=1 fi #this is pulled from the guilt code to handle commit ids sanely. # usage: munge_hash_range # # this means: # - one commit # .. - hash until head (excludes hash, includes head) # .. - until hash (includes hash) # .. - from hash to hash (inclusive) # # The output of this function is suitable to be passed to "git rev-list" munge_hash_range() { case "$1" in *..*..*|*\ *) # double .. or space is illegal return 1;; ..*) # e.g., "..v0.10" echo ${1#..};; *..) # e.g., "v0.19.." echo ${1%..}..HEAD;; *..*) # e.g., "v0.19-rc1..v0.19" echo ${1%%..*}..${1#*..};; ?*) # e.g., "v0.19" echo $1^..$1;; *) # empty return 1;; esac return 0 } # Filter the patch into the right format & files for the other tree filter_kernel_patch() { local _patch=$1 local _libxfs_files="" # The files we will try to apply to _libxfs_files=`mktemp` ls -1 fs/xfs/libxfs/*.[ch] | sed -e "s%.*/\(.*\)%*\1%" > $_libxfs_files # Create the new patch # filterdiff will have screwed up files that source/sink /dev/null. # fix that up with some sed magic. filterdiff \ --verbose \ -I $_libxfs_files \ --strip=1 \ --addoldprefix=a/fs/xfs/ \ --addnewprefix=b/fs/xfs/ \ $_patch | \ sed -e 's, [ab]\/fs\/xfs\/\(\/dev\/null\), \1,' \ -e '/^diff --git/d' rm -f $_libxfs_files } filter_xfsprogs_patch() { local _patch=$1 local _libxfs_files="" # The files we will try to apply to. We need to pull this from the # patch, as the may be libxfs files added in this patch and so we # need to capture them. _libxfs_files=`mktemp` #ls -1 libxfs/*.[ch] | sed -e "s%.*/\(.*\)%*libxfs/\1%" > $_libxfs_files lsdiff $_patch | sed -e "s%.*/\(.*\)%*libxfs/\1%" > $_libxfs_files # Create the new patch # filterdiff will have screwed up files that source/sink /dev/null. # fix that up with some sed magic. filterdiff \ --verbose \ -I $_libxfs_files \ --strip=3 \ --addoldprefix=a/ \ --addnewprefix=b/ \ $_patch | \ sed -e 's, [ab]\/\(\/dev\/null\), \1,' \ -e '/^diff --git/d' rm -f $_libxfs_files } fixup_header_format() { local _source=$1 local _patch=$2 local _hdr=`mktemp` local _diff=`mktemp` local _new_hdr=$_hdr.new # there's a bug in filterdiff that leaves a line at the end of the # header in the filtered git show output like: # # difflibxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c # # split the header on that (convenient!) sed -e /^difflib/q $_patch > $_hdr cat $_patch | awk ' BEGIN { difflib_seen = 0; index_seen = 0 } /^difflib/ { difflib_seen++; next } /^index/ { if (++index_seen == 1) { next } } // { if (difflib_seen) { print $0 } }' > $_diff # the header now has the format: # commit 0d5a75e9e23ee39cd0d8a167393dcedb4f0f47b2 # Author: Eric Sandeen # Date: Wed Jun 1 17:38:15 2016 +1000 # # xfs: make several functions static #.... # Signed-off-by: Dave Chinner # #difflibxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c # # We want to format it like a normal patch with a line to say what repo # and commit it was sourced from: # # xfs: make several functions static # # From: Eric Sandeen # # Source kernel commit: 0d5a75e9e23ee39cd0d8a167393dcedb4f0f47b2 # # # # To do this, use sed to first strip whitespace, then pass it into awk # to rearrange the headers. sed -e 's/^ *//' $_hdr | awk -v src=$_source ' BEGIN { date_seen=0 subject_seen=0 } /^commit/ { commit=$2 next; } /^Author:/ { split($0, a, ":") from=a[2] next; } /^Date:/ { date_seen=1; next } /^difflib/ { next } // { if (date_seen == 0) next; if (subject_seen == 0) { if (length($0) != 0) { subject_seen=1 subject=$0; } next; } if (subject_seen == 1) { print subject print print "From:" from print print "Source " src " commit: " commit subject_seen=2 } print $0 }' > $_hdr.new # now output the new patch cat $_hdr.new $_diff rm -f $_hdr* $_diff } apply_patch() { local _patch=$1 local _patch_name=$2 local _current_commit=$3 local _new_patch=`mktemp` local _source="kernel" # filter just the libxfs parts of the patch if [ $SOURCE == "xfsprogs" ]; then [ -n "$VERBOSE" ] || lsdiff $_patch | grep -q "[ab]/libxfs/" if [ $? -ne 0 ]; then echo "Doesn't look like an xfsprogs patch with libxfs changes" echo "Skipping commit $_current_commit" return fi filter_kernel_patch $_patch > $_new_patch _source="xfsprogs" elif [ $SOURCE == "kernel" ]; then [ -n "$VERBOSE" ] || lsdiff $_patch | grep -q "[ab]/fs/xfs/libxfs/" if [ $? -ne 0 ]; then echo "Doesn't look like a kernel patch with libxfs changes" echo "Skipping commit $_current_commit" return fi filter_xfsprogs_patch $_patch > $_new_patch else fail "Unknown source repo type: $SOURCE" fi # now munge the header to be in the correct format. fixup_header_format $_source $_new_patch > $_new_patch.2 if [ -n "$VERBOSE" ]; then echo "Filtered patch from $REPO contains:" lsdiff $_new_patch.2 fi # Ok, now apply with guilt or patch; either may fail and require a force # and/or a manual reject fixup if [ $GUILT -eq 1 ]; then [ -n "$VERBOSE" ] || echo "$REPO looks like a guilt directory." PATCHES=`guilt applied | wc -l` if [ -n "$VERBOSE" -a $PATCHES -gt 0 ]; then echo -n "Top patch is: " guilt top fi guilt import -P $_patch_name $_new_patch.2 guilt push if [ $? -eq 0 ]; then guilt refresh else echo "Guilt push failed!" read -r -p "Skip of Fail [s|F]? " response if [ -z "$response" -o "$response" != "s" ]; then echo "Force push patch, fix and refresh." echo "Restart from commit $_current_commit" fail "Manual cleanup required!" else echo "Skipping. Manual series file cleanup needed!" fi fi else echo "Applying with patch utility:" patch -p1 < $_new_patch.2 echo "Patch was applied in $REPO; check for rejects, etc" fi rm -f $_new_patch* } # name a guilt patch. Code is lifted from guilt import-commit. name_patch() { s=`git log --no-decorate --pretty=oneline -1 $1 | cut -c 42-` # Try to convert the first line of the commit message to a # valid patch name. fname=`printf %s "$s" | \ sed -e "s/&/and/g" -e "s/[ :]/_/g" -e "s,[/\\],-,g" \ -e "s/['\\[{}]//g" -e 's/]//g' -e 's/\*/-/g' \ -e 's/\?/-/g' -e 's/\.\.\.*/./g' -e 's/^\.//' \ -e 's/\.patch$//' -e 's/\.$//' | tr A-Z a-z` # Try harder to make it a legal commit name by # removing all but a few safe characters. fname=`echo $fname|tr -d -c _a-zA-Z0-9---/\\n` echo $fname } # single patch is easy. if [ -z "$COMMIT_ID" ]; then apply_patch $PATCH cleanup exit 0 fi # switch to source repo and get individual commit IDs # # git rev-list gives us a list in reverse chronological order, so we need to # reverse that to give us the order we require. pushd $REPO > /dev/null check_repo Source hashr=`munge_hash_range $COMMIT_ID` if [ $SOURCE == "kernel" ]; then hashr="$hashr -- fs/xfs/libxfs" else hashr="$hashr -- libxfs" fi # grab and echo the list of commits for confirmation echo "Commits to apply:" commit_list=`git rev-list $hashr | tac` git log --oneline $hashr |tac read -r -p "Proceed [y|N]? " response if [ -z "$response" -o "$response" != "y" ]; then fail "Aborted!" fi popd > /dev/null PATCH=`mktemp` for commit in $commit_list; do # switch to source repo and pull commit into a patch file pushd $REPO > /dev/null git show $commit > $PATCH || usage "Bad source commit ID!" patch_name=`name_patch $commit` popd > /dev/null apply_patch $PATCH $patch_name $commit done cleanup xfsprogs-4.9.0+nmu1ubuntu2/tools/xfsbuflock.py0000755000000000000000000001254713033541503016357 0ustar #!/usr/bin/env python3 # Read ftrace input, looking for XFS buffer deadlocks. # # Copyright (C) 2016 Oracle. All Rights Reserved. # # Author: Darrick J. Wong # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it would be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. # # Rough guide to using this script: # Collect ftrace data from a deadlock: # # # trace-cmd record -e 'xfs_buf_*lock*' & # ^Z # # killall -INT trace-cmd # # # Now analyze the captured trace data: # # # trace-cmd report | xfsbuflock.py # === fsx-14956 === # # 3732.005575: xfs_buf_trylock_fail: dev 8:16 bno 0x1 nblks 0x1 hold 4 \ # pincount 1 lock 0 flags DONE|KMEM caller 0xc009af36s # Locked buffers: # dev 8:16 bno 0x64c371 nblks 0x1 lock 1 owner fsx-14956@3732.005567 # waiting: fsx-14954 # dev 8:16 bno 0x64c380 nblks 0x8 lock 1 owner fsx-14956@3732.005571 # dev 8:16 bno 0x64c378 nblks 0x8 lock 1 owner fsx-14956@3732.005570 # === fsx-14954 === # # 3732.005592: xfs_buf_trylock_fail: dev 8:16 bno 0x64c371 nblks 0x1 hold 4 \ # pincount 1 lock 0 flags ASYNC|DONE|KMEM caller 0xc009af36s # Locked buffers: # dev 8:16 bno 0x8 nblks 0x8 lock 1 owner fsx-14954@3732.005583 # dev 8:16 bno 0x1 nblks 0x1 lock 1 owner fsx-14954@3732.005574 # waiting: fsx-14956 # waiting: fsx-14957 # waiting: fsx-14958 # dev 8:16 bno 0x10 nblks 0x8 lock 1 owner fsx-14954@3732.005585 # # As you can see, fsx-14596 is locking AGFs in violation of the locking # order rules. import sys import fileinput from collections import namedtuple NR_BACKTRACE = 50 class Process: def __init__(self, pid): self.pid = pid; self.bufs = set() self.locked_bufs = set() self.backtrace = [] def dump(self): print('=== %s ===' % self.pid) for bt in self.backtrace: print('%f: %s' % (bt.time, bt.descr)) print('Locked buffers:') for buf in self.locked_bufs: buf.dump() class Buffer: def __init__(self, dev, bno, blen): self.dev = dev self.bno = int(bno, 0) self.blen = int(blen, 0) self.locked = False self.locktime = None self.owner = None self.waiters = set() def trylock(self, process, time): self.lockdone(process, time) def lockdone(self, process, time): if self.locked: print('Buffer already locked on line %d?!' % nr) # process.dump() # self.dump() # assert False if process in self.waiters: self.waiters.remove(process) self.locked = True self.owner = process self.locktime = time process.locked_bufs.add(self) process.bufs.add(self) locked_buffers.add(self) def waitlock(self, process): self.waiters.add(process) def unlock(self): self.locked = False if self in locked_buffers: locked_buffers.remove(self) if self.owner is not None and \ self in self.owner.locked_bufs: self.owner.locked_bufs.remove(self) def dump(self): if self.owner is not None: pid = '%s@%f' % (self.owner.pid, self.locktime) else: pid = '' print('dev %s bno 0x%x nblks 0x%x lock %d owner %s' % \ (self.dev, self.bno, self.blen, self.locked, \ pid)) for proc in self.waiters: print(' waiting: %s' % proc.pid) Event = namedtuple('Event', 'time descr') # Read ftrace input, looking for events and for buffer lock info processes = {} buffers = {} locked_buffers = set() def getbuf(toks): if int(toks[7], 0) == 18446744073709551615: return None bufkey = ' '.join(toks[4:10]) if bufkey in buffers: return buffers[bufkey] buf = Buffer(toks[5], toks[7], toks[9]) buffers[bufkey] = buf return buf nr = 0 for line in fileinput.input(): nr += 1 toks = line.split() if len(toks) < 4: continue pid = toks[0] try: time = float(toks[2][:-1]) except: continue fn = toks[3][:-1] if pid in processes: proc = processes[pid] else: proc = Process(pid) processes[pid] = proc if fn == 'xfs_buf_unlock' or fn == 'xfs_buf_item_unlock_stale': buf = getbuf(toks) if buf is not None: buf.unlock() elif fn == 'xfs_buf_lock_done': buf = getbuf(toks) if buf is not None: buf.lockdone(proc, time) elif fn == 'xfs_buf_lock': buf = getbuf(toks) if buf is not None: buf.waitlock(proc) elif fn == 'xfs_buf_trylock': buf = getbuf(toks) if buf is not None: buf.trylock(proc, time) elif fn == 'xfs_buf_item_unlock': pass else: e = Event(time, ' '.join(toks[3:])) proc.backtrace.append(e) if len(proc.backtrace) > NR_BACKTRACE: proc.backtrace.pop(0) deadlocked = set() for buf in locked_buffers: deadlocked.add(buf.owner) for proc in deadlocked: proc.dump() sys.exit(0) for key in buffers: buf = buffers[key] if buf.locked: print('dev %s bno 0x%x len 0x%x owner %s' % (buf.dev, buf.bno, buf.blen, buf.owner.pid)) else: print('dev %s bno 0x%x len 0x%x' % (buf.dev, buf.bno, buf.blen)) sys.exit(0) for pid in processes: proc = processes[pid]